Skip to content

Commit 1aaf2c9

Browse files
committed
Allow value generics to show up as static members
1 parent 41120da commit 1aaf2c9

File tree

5 files changed

+54
-11
lines changed

5 files changed

+54
-11
lines changed

include/swift/AST/Expr.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1480,6 +1480,12 @@ class TypeValueExpr : public Expr {
14801480
this->paramType = paramType;
14811481
}
14821482

1483+
/// Retrieves the underlying value type of the parameter type referenced by
1484+
/// this expression.
1485+
Type getValueType() const {
1486+
return valueType;
1487+
}
1488+
14831489
SourceRange getSourceRange() const {
14841490
return loc.getSourceRange();
14851491
}

lib/AST/NameLookup.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2739,6 +2739,17 @@ QualifiedLookupRequest::evaluate(Evaluator &eval, const DeclContext *DC,
27392739
}
27402740
}
27412741

2742+
// Qualified name lookup can find generic value parameters.
2743+
auto gpList = current->getGenericParams();
2744+
2745+
if (gpList && !member.isSpecial()) {
2746+
if (auto gp = gpList->lookUpGenericParam(member.getBaseIdentifier())) {
2747+
if (gp->isValue()) {
2748+
decls.push_back(gp);
2749+
}
2750+
}
2751+
}
2752+
27422753
// If we're not looking at a protocol and we're not supposed to
27432754
// visit the protocols that this type conforms to, skip the next
27442755
// step.

lib/Sema/CSApply.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3222,7 +3222,7 @@ namespace {
32223222

32233223
Expr *visitTypeValueExpr(TypeValueExpr *expr) {
32243224
auto toType = simplifyType(cs.getType(expr));
3225-
assert(toType->isEqual(expr->getParamDecl()->getValueType()));
3225+
ASSERT(toType->isEqual(expr->getParamDecl()->getValueType()));
32263226
cs.setType(expr, toType);
32273227
return expr;
32283228
}

lib/Sema/PreCheckTarget.cpp

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1096,10 +1096,10 @@ class PreCheckTarget final : public ASTWalker {
10961096
/// Simplify expressions which are type sugar productions that got parsed
10971097
/// as expressions due to the parser not knowing which identifiers are
10981098
/// type names.
1099-
TypeExpr *simplifyTypeExpr(Expr *E);
1099+
Expr *simplifyTypeExpr(Expr *E);
11001100

11011101
/// Simplify unresolved dot expressions which are nested type productions.
1102-
TypeExpr *simplifyNestedTypeExpr(UnresolvedDotExpr *UDE);
1102+
Expr *simplifyNestedTypeExpr(UnresolvedDotExpr *UDE);
11031103

11041104
TypeExpr *simplifyUnresolvedSpecializeExpr(UnresolvedSpecializeExpr *USE);
11051105

@@ -1726,7 +1726,7 @@ void PreCheckTarget::diagnoseOutOfPlaceSingleValueStmtExprs(
17261726
}
17271727
}
17281728

1729-
TypeExpr *PreCheckTarget::simplifyNestedTypeExpr(UnresolvedDotExpr *UDE) {
1729+
Expr *PreCheckTarget::simplifyNestedTypeExpr(UnresolvedDotExpr *UDE) {
17301730
if (!UDE->getName().isSimpleName() ||
17311731
UDE->getName().isSpecial())
17321732
return nullptr;
@@ -1841,8 +1841,19 @@ TypeExpr *PreCheckTarget::simplifyNestedTypeExpr(UnresolvedDotExpr *UDE) {
18411841
// If there is no nested type with this name, we have a lookup of
18421842
// a non-type member, so leave the expression as-is.
18431843
if (Result.size() == 1) {
1844-
return TypeExpr::createForMemberDecl(InnerTypeRepr, UDE->getNameLoc(),
1845-
Result.front().Member);
1844+
auto resultDecl = Result.front().Member;
1845+
1846+
if (isa<GenericTypeParamDecl>(resultDecl) &&
1847+
cast<GenericTypeParamDecl>(resultDecl)->isValue()) {
1848+
auto gtpd = cast<GenericTypeParamDecl>(resultDecl);
1849+
return TypeValueExpr::createForMemberDecl(InnerTypeRepr,
1850+
UDE->getNameLoc(),
1851+
gtpd);
1852+
1853+
} else {
1854+
return TypeExpr::createForMemberDecl(InnerTypeRepr, UDE->getNameLoc(),
1855+
resultDecl);
1856+
}
18461857
}
18471858
}
18481859

@@ -2121,7 +2132,7 @@ static bool isTildeOperator(Expr *expr) {
21212132
/// Simplify expressions which are type sugar productions that got parsed
21222133
/// as expressions due to the parser not knowing which identifiers are
21232134
/// type names.
2124-
TypeExpr *PreCheckTarget::simplifyTypeExpr(Expr *E) {
2135+
Expr *PreCheckTarget::simplifyTypeExpr(Expr *E) {
21252136
// If it's already a type expression, return it.
21262137
if (auto typeExpr = dyn_cast<TypeExpr>(E))
21272138
return typeExpr;
@@ -2320,7 +2331,7 @@ TypeExpr *PreCheckTarget::simplifyTypeExpr(Expr *E) {
23202331

23212332
// When simplifying a type expr like "(P1 & P2) -> (P3 & P4) -> Int",
23222333
// it may have been folded at the same time; recursively simplify it.
2323-
if (auto ArgsTypeExpr = simplifyTypeExpr(E)) {
2334+
if (auto ArgsTypeExpr = dyn_cast<TypeExpr>(simplifyTypeExpr(E))) {
23242335
auto ArgRepr = ArgsTypeExpr->getTypeRepr();
23252336
if (auto *TTyRepr = dyn_cast<TupleTypeRepr>(ArgRepr))
23262337
return TTyRepr;
@@ -2341,7 +2352,7 @@ TypeExpr *PreCheckTarget::simplifyTypeExpr(Expr *E) {
23412352

23422353
// When simplifying a type expr like "P1 & P2 -> P3 & P4 -> Int",
23432354
// it may have been folded at the same time; recursively simplify it.
2344-
if (auto ArgsTypeExpr = simplifyTypeExpr(E))
2355+
if (auto ArgsTypeExpr = dyn_cast<TypeExpr>(simplifyTypeExpr(E)))
23452356
return ArgsTypeExpr->getTypeRepr();
23462357
return nullptr;
23472358
};
@@ -2380,7 +2391,8 @@ TypeExpr *PreCheckTarget::simplifyTypeExpr(Expr *E) {
23802391
// Fold '~P' into a composition type.
23812392
if (auto *unaryExpr = dyn_cast<PrefixUnaryExpr>(E)) {
23822393
if (isTildeOperator(unaryExpr->getFn())) {
2383-
if (auto operand = simplifyTypeExpr(unaryExpr->getOperand())) {
2394+
if (auto operand = dyn_cast<TypeExpr>(
2395+
simplifyTypeExpr(unaryExpr->getOperand()))) {
23842396
auto inverseTypeRepr = new (Ctx) InverseTypeRepr(
23852397
unaryExpr->getLoc(), operand->getTypeRepr());
23862398
return new (Ctx) TypeExpr(inverseTypeRepr);
@@ -2400,7 +2412,7 @@ TypeExpr *PreCheckTarget::simplifyTypeExpr(Expr *E) {
24002412
// If the lhs is another binary expression, we have a multi element
24012413
// composition: 'A & B & C' is parsed as ((A & B) & C); we get
24022414
// the protocols from the lhs here
2403-
if (auto expr = simplifyTypeExpr(lhsExpr))
2415+
if (auto expr = dyn_cast<TypeExpr>(simplifyTypeExpr(lhsExpr)))
24042416
if (auto *repr = dyn_cast<CompositionTypeRepr>(expr->getTypeRepr()))
24052417
// add the protocols to our list
24062418
for (auto proto : repr->getTypes())

test/Sema/value_generics.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,3 +119,17 @@ func testC4<let T: Int>(with c: C<T, T>) {
119119
}
120120

121121
struct D<let N: Int & P> {} // expected-error {{non-protocol, non-class type 'Int' cannot be used within a protocol-constrained type}}
122+
123+
struct E<A, let b: Int> {}
124+
125+
func testE1() -> Int {
126+
E<Int, 123>.b // OK
127+
}
128+
129+
func testE2() -> Int {
130+
E<Int, 123>.A // expected-error {{type 'E<Int, 123>' has no member 'A'}}
131+
}
132+
133+
func testE3<let c: Int>(_: E<Int, c>.Type = E<Int, c>.self) -> Int {
134+
E<Int, c>.b // OK
135+
}

0 commit comments

Comments
 (0)