Skip to content

Commit a3c15f2

Browse files
committed
Sema: References to TypeDecls should always be TypeExpr
In a few corner cases we built DeclRefExpr and MemberRefExpr for references to types. These should just be TypeExpr so that SILGen doesn't have to deal with it. This also fixes a bug where a protocol typealias with an unbound generic type could not be accessed properly from expression context, but that is just so incredibly obscure.
1 parent ff30333 commit a3c15f2

File tree

5 files changed

+34
-34
lines changed

5 files changed

+34
-34
lines changed

lib/SILGen/SILGenExpr.cpp

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -866,15 +866,6 @@ emitRValueForDecl(SILLocation loc, ConcreteDeclRef declRef, Type ncRefType,
866866
return emitUndefRValue(loc, refType);
867867
}
868868

869-
// If this is a reference to a type, produce a metatype.
870-
if (isa<TypeDecl>(decl)) {
871-
assert(refType->is<MetatypeType>() &&
872-
"type declref does not have metatype type?!");
873-
return RValue(*this, loc, refType,
874-
ManagedValue::forUnmanaged(
875-
B.createMetatype(loc, getLoweredType(refType))));
876-
}
877-
878869
// If this is a reference to a var, emit it as an l-value and then load.
879870
if (auto *var = dyn_cast<VarDecl>(decl)) {
880871
assert(!declRef.isSpecialized() &&
@@ -883,6 +874,8 @@ emitRValueForDecl(SILLocation loc, ConcreteDeclRef declRef, Type ncRefType,
883874
return emitRValueForNonMemberVarDecl(loc, var, refType, semantics, C);
884875
}
885876

877+
assert(!isa<TypeDecl>(decl));
878+
886879
// If the referenced decl isn't a VarDecl, it should be a constant of some
887880
// sort.
888881
SILDeclRef silDeclRef(decl);
@@ -2016,14 +2009,7 @@ RValue RValueEmitter::visitMemberRefExpr(MemberRefExpr *e,
20162009
SGFContext resultCtx) {
20172010
assert(!e->getType()->is<LValueType>() &&
20182011
"RValueEmitter shouldn't be called on lvalues");
2019-
2020-
if (isa<TypeDecl>(e->getMember().getDecl())) {
2021-
// Emit the metatype for the associated type.
2022-
visit(e->getBase());
2023-
SILValue mt =
2024-
SGF.B.createMetatype(e, SGF.getLoweredLoadableType(e->getType()));
2025-
return RValue(SGF, e, ManagedValue::forUnmanaged(mt));
2026-
}
2012+
assert(isa<VarDecl>(e->getMember().getDecl()));
20272013

20282014
// Everything else should use the l-value logic.
20292015

lib/Sema/CSApply.cpp

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -551,6 +551,16 @@ namespace {
551551
/*isDynamic=*/false);
552552
}
553553

554+
auto type = solution.simplifyType(openedType);
555+
556+
if (isa<TypeDecl>(decl) && !isa<ModuleDecl>(decl)) {
557+
auto typeExpr = TypeExpr::createImplicitHack(
558+
loc.getBaseNameLoc(), type->getMetatypeInstanceType(),
559+
ctx);
560+
cs.cacheType(typeExpr);
561+
return typeExpr;
562+
}
563+
554564
SubstitutionMap substitutions;
555565

556566
// Due to a SILGen quirk, unqualified property references do not
@@ -562,7 +572,6 @@ namespace {
562572
locator);
563573
}
564574

565-
auto type = solution.simplifyType(openedType);
566575
auto declRefExpr =
567576
new (ctx) DeclRefExpr(ConcreteDeclRef(decl, substitutions),
568577
loc, implicit, semantics, type);
@@ -842,6 +851,20 @@ namespace {
842851
return forceUnwrapIfExpected(DSBI, choice, memberLocator);
843852
}
844853

854+
// If we're referring to a member type, it's just a type
855+
// reference.
856+
if (isa<TypeDecl>(member)) {
857+
Type refType = simplifyType(openedType);
858+
auto ref =
859+
TypeExpr::createImplicitHack(memberLoc.getBaseNameLoc(),
860+
refType, context);
861+
cs.setType(ref, refType);
862+
auto *result = new (context) DotSyntaxBaseIgnoredExpr(
863+
base, dotLoc, ref, refType);
864+
cs.setType(result, refType);
865+
return result;
866+
}
867+
845868
// The formal type of the 'self' value for the member's declaration.
846869
Type containerTy = getBaseType(refTy->castTo<FunctionType>());
847870

@@ -983,8 +1006,8 @@ namespace {
9831006
member->getAttrs().hasAttribute<OptionalAttr>());
9841007
}
9851008

986-
// For types and properties, build member references.
987-
if (isa<TypeDecl>(member) || isa<VarDecl>(member)) {
1009+
// For properties, build member references.
1010+
if (isa<VarDecl>(member)) {
9881011
assert(!dynamicSelfFnType && "Converted type doesn't make sense here");
9891012
if (!baseIsInstance && member->isInstanceMember()) {
9901013
assert(memberLocator.getBaseLocator() &&

lib/Sema/ConstraintSystem.cpp

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1206,19 +1206,6 @@ ConstraintSystem::getTypeOfMemberReference(
12061206

12071207
FunctionType::Param baseObjParam(baseObjTy);
12081208

1209-
// Don't open existentials when accessing typealias members of
1210-
// protocols.
1211-
if (auto *alias = dyn_cast<TypeAliasDecl>(value)) {
1212-
if (baseObjTy->isExistentialType()) {
1213-
auto memberTy = alias->getInterfaceType();
1214-
// If we end up with a protocol typealias here, it's underlying
1215-
// type must be fully concrete.
1216-
assert(!memberTy->hasTypeParameter());
1217-
auto openedType = FunctionType::get({baseObjParam}, memberTy);
1218-
return { openedType, memberTy };
1219-
}
1220-
}
1221-
12221209
if (auto *typeDecl = dyn_cast<TypeDecl>(value)) {
12231210
assert(!isa<ModuleDecl>(typeDecl) && "Nested module?");
12241211

test/Constraints/protocols.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ protocol P : Initable {
110110

111111
typealias E = Int
112112
typealias F = Self.E
113+
typealias G = Array
113114
}
114115

115116
protocol ClassP : class {
@@ -226,6 +227,9 @@ func staticExistential(_ p: P.Type, pp: P.Protocol) {
226227

227228
_ = pp.F.self
228229
_ = p.F.self
230+
231+
// Make sure that we open generics
232+
let _: [Int].Type = p.G.self
229233
}
230234

231235
protocol StaticP {

test/Sema/typo_correction.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ protocol P {} // expected-error {{invalid redeclaration of 'P'}}
121121
// expected-note@-1 {{did you mean 'P'?}}
122122

123123
func hasTypo() {
124-
_ = P.a.a // expected-error {{type 'P.a' (aka 'Generic') has no member 'a'}}
124+
_ = P.a.a // expected-error {{type 'Generic<_>' has no member 'a'}}
125125
}
126126

127127
// Typo correction with AnyObject.

0 commit comments

Comments
 (0)