Skip to content

Commit 42b4161

Browse files
committed
Add feature for value generic namelookup
1 parent b3f3dd7 commit 42b4161

File tree

4 files changed

+84
-0
lines changed

4 files changed

+84
-0
lines changed

include/swift/Basic/Features.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,7 @@ LANGUAGE_FEATURE(RawIdentifiers, 451, "Raw identifiers")
256256
LANGUAGE_FEATURE(SendableCompletionHandlers, 463, "Objective-C completion handler parameters are imported as @Sendable")
257257
LANGUAGE_FEATURE(AsyncExecutionBehaviorAttributes, 0, "@concurrent and nonisolated(nonsending)")
258258
LANGUAGE_FEATURE(IsolatedConformances, 407, "Global-actor isolated conformances")
259+
LANGUAGE_FEATURE(ValueGenericsNameLookup, 452, "Value generics appearing as static members for namelookup")
259260

260261
// Swift 6
261262
UPCOMING_FEATURE(ConciseMagicFile, 274, 6)

lib/AST/FeatureSet.cpp

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
#include "FeatureSet.h"
1414

15+
#include "swift/AST/ASTWalker.h"
1516
#include "swift/AST/Decl.h"
1617
#include "swift/AST/ExistentialLayout.h"
1718
#include "swift/AST/GenericParamList.h"
@@ -470,6 +471,54 @@ static bool usesFeatureValueGenerics(Decl *decl) {
470471
return false;
471472
}
472473

474+
class UsesTypeValueExpr : public ASTWalker {
475+
public:
476+
bool used = false;
477+
478+
PreWalkResult<Expr *> walkToExprPre(Expr *expr) override {
479+
if (isa<TypeValueExpr>(expr)) {
480+
used = true;
481+
return Action::Stop();
482+
}
483+
484+
return Action::Continue(expr);
485+
}
486+
};
487+
488+
static bool usesFeatureValueGenericsNameLookup(Decl *decl) {
489+
// Be conservative and mark any function that has a TypeValueExpr in its body
490+
// as having used this feature. It's a little difficult to fine grain this
491+
// check because the following:
492+
//
493+
// func a() -> Int {
494+
// A<123>.n
495+
// }
496+
//
497+
// Would appear to have the same expression as something like:
498+
//
499+
// extension A where n == 123 {
500+
// func b() -> Int {
501+
// n
502+
// }
503+
// }
504+
505+
auto fn = dyn_cast<AbstractFunctionDecl>(decl);
506+
507+
if (!fn)
508+
return false;
509+
510+
auto body = fn->getTypecheckedBody();
511+
512+
if (!body)
513+
return false;
514+
515+
UsesTypeValueExpr utve;
516+
517+
body->walk(utve);
518+
519+
return utve.used;
520+
}
521+
473522
static bool usesFeatureCoroutineAccessors(Decl *decl) {
474523
auto accessorDeclUsesFeatureCoroutineAccessors = [](AccessorDecl *accessor) {
475524
return requiresFeatureCoroutineAccessors(accessor->getAccessorKind());

test/ModuleInterface/value_generics.swift

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ public struct Slab<Element, let N: Int> {
1414
public var count: Int {
1515
N
1616
}
17+
18+
public init() {}
1719
}
1820

1921
// CHECK: public func usesGenericSlab<let N : Swift.Int>(_: ValueGeneric.Slab<Swift.Int, N>)
@@ -24,3 +26,27 @@ public func usesConcreteSlab(_: Slab<Int, 2>) {}
2426

2527
// CHECK: public func usesNegativeSlab(_: ValueGeneric.Slab<Swift.String, -10>)
2628
public func usesNegativeSlab(_: Slab<String, -10>) {}
29+
30+
// CHECK: $ValueGenericsNameLookup
31+
@inlinable
32+
public func test() -> Int {
33+
// CHECK: Slab<Int, 123>.N
34+
Slab<Int, 123>.N
35+
}
36+
37+
// CHECK: $ValueGenericsNameLookup
38+
@inlinable
39+
public func test2() -> Int {
40+
// CHECK: type(of: Slab<Int, 123>()).N
41+
type(of: Slab<Int, 123>()).N
42+
}
43+
44+
// CHECK: $ValueGenericsNameLookup
45+
@inlinable
46+
public func test3() {
47+
{
48+
print(123)
49+
print(123)
50+
print(Slab<Int, 123>.N)
51+
}()
52+
}

test/Sema/value_generics.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,14 @@ struct E<A, let b: Int> { // expected-note {{'b' previously declared here}}
131131

132132
func b() {} // expected-error {{invalid redeclaration of 'b()'}}
133133
// expected-note@-1 {{'b' declared here}}
134+
135+
func dumb() -> Int {
136+
Self.b // OK
137+
}
138+
139+
static func dumb2() -> Int {
140+
Self.b // OK
141+
}
134142
}
135143

136144
func testE1() -> Int {

0 commit comments

Comments
 (0)