Skip to content

Commit 72c44b4

Browse files
committed
Sema: Fix getTypeOfMemberReference() for unbound instance methods
Always rewrite the Self type to the base type. Previously we only did it if the method had a dynamic self return. This caused some confusing behavior in this case: class C { func m1() {} func m2() -> Self {} } class D : C {} The types of D.m1 and D.m2 are: - D.m1: C -> () -> () - D.m2: D -> () -> D For protocols, this also meant that the type of an instance method reference P.f had an open existential that could "leak out" of the OpenExistentialExpr. Now, P.f will have type P -> ... -> ..., however using such a reference still crashes, just in SILGen instead of Sema, because we don't generate the right thunks yet. Progress on <rdar://problem/21289579>. Swift SVN r29447
1 parent 5bbc879 commit 72c44b4

File tree

2 files changed

+22
-26
lines changed

2 files changed

+22
-26
lines changed

lib/Sema/ConstraintSystem.cpp

Lines changed: 16 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1205,11 +1205,13 @@ ConstraintSystem::getTypeOfMemberReference(Type baseTy, ValueDecl *value,
12051205
}
12061206

12071207
// If we are looking at a member of an existential, open the existential.
1208+
Type baseOpenedTy = baseObjTy;
1209+
12081210
if (baseObjTy->isExistentialType()) {
12091211
ArchetypeType *openedArchetype = ArchetypeType::getOpened(baseObjTy);
12101212
OpenedExistentialTypes.push_back({ getConstraintLocator(locator),
12111213
openedArchetype });
1212-
baseObjTy = openedArchetype;
1214+
baseOpenedTy = openedArchetype;
12131215
}
12141216

12151217
// Constrain the 'self' object type.
@@ -1219,10 +1221,10 @@ ConstraintSystem::getTypeOfMemberReference(Type baseTy, ValueDecl *value,
12191221
// For a protocol, substitute the base object directly. We don't need a
12201222
// conformance constraint because we wouldn't have found the declaration
12211223
// if it didn't conform.
1222-
addConstraint(ConstraintKind::Equal, baseObjTy, selfObjTy,
1224+
addConstraint(ConstraintKind::Equal, baseOpenedTy, selfObjTy,
12231225
getConstraintLocator(locator));
12241226
} else if (!isDynamicResult) {
1225-
addSelfConstraint(*this, baseObjTy, selfObjTy, locator);
1227+
addSelfConstraint(*this, baseOpenedTy, selfObjTy, locator);
12261228
}
12271229

12281230
// Compute the type of the reference.
@@ -1248,23 +1250,19 @@ ConstraintSystem::getTypeOfMemberReference(Type baseTy, ValueDecl *value,
12481250
auto assocType = cast<AssociatedTypeDecl>(value);
12491251

12501252
type = openedFnType->getResult();
1251-
if (baseObjTy->is<ArchetypeType>()) {
1253+
if (baseOpenedTy->is<ArchetypeType>()) {
12521254
// For an archetype, we substitute the base object for the base.
12531255
// FIXME: Feels like a total hack.
1254-
} else if (!baseObjTy->isExistentialType() &&
1255-
!baseObjTy->is<ArchetypeType>()) {
1256+
} else if (!baseOpenedTy->isExistentialType() &&
1257+
!baseOpenedTy->is<ArchetypeType>()) {
12561258
ProtocolConformance *conformance = nullptr;
1257-
if (TC.conformsToProtocol(baseObjTy, proto, DC,
1259+
if (TC.conformsToProtocol(baseOpenedTy, proto, DC,
12581260
ConformanceCheckFlags::InExpression,
12591261
&conformance)) {
12601262
type = conformance->getTypeWitness(assocType, &TC).getReplacement();
12611263
}
12621264
}
1263-
} else if (isa<ConstructorDecl>(value) || isa<EnumElementDecl>(value) ||
1264-
(isa<FuncDecl>(value) && cast<FuncDecl>(value)->isStatic()) ||
1265-
(isa<VarDecl>(value) && cast<VarDecl>(value)->isStatic()) ||
1266-
isa<TypeDecl>(value) ||
1267-
isInstance) {
1265+
} else if (!value->isInstanceMember() || isInstance) {
12681266
// For a constructor, enum element, static method, static property,
12691267
// or an instance method referenced through an instance, we've consumed the
12701268
// curried 'self' already. For a type, strip off the 'self' we artificially
@@ -1280,18 +1278,12 @@ ConstraintSystem::getTypeOfMemberReference(Type baseTy, ValueDecl *value,
12801278
->getDeclaredTypeOfContext();
12811279
type = FunctionType::get(inputTy, resultTy, funcTy->getExtInfo());
12821280
} else {
1283-
type = openedType;
1284-
1285-
// If we're referencing a method with dynamic Self that has 'self'
1286-
// curried, replace the type of 'self' with the actual base object
1287-
// type.
1288-
if (hasDynamicSelf) {
1289-
auto fnType = type->castTo<FunctionType>();
1290-
auto selfTy = rebuildSelfTypeWithObjectType(fnType->getInput(),
1291-
baseObjTy);
1292-
type = FunctionType::get(selfTy, fnType->getResult(),
1293-
fnType->getExtInfo());
1294-
}
1281+
// For an unbound instance method reference, replace the 'Self'
1282+
// parameter with the base type.
1283+
auto selfTy = rebuildSelfTypeWithObjectType(openedFnType->getInput(),
1284+
baseObjTy);
1285+
type = FunctionType::get(selfTy, openedFnType->getResult(),
1286+
openedFnType->getExtInfo());
12951287
}
12961288

12971289
// If we opened up any type variables, record the replacements.

test/NameBinding/name_lookup.swift

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -223,9 +223,13 @@ class ThisDerived1 : ThisBase1 {
223223
self.baseInstanceVar = 42 // expected-error {{'ThisDerived1.Type' does not have a member named 'baseInstanceVar'}}
224224
self.baseProp = 42 // expected-error {{'ThisDerived1.Type' does not have a member named 'baseProp'}}
225225
self.baseFunc0() // expected-error {{missing argument}}
226-
self.baseFunc0(ThisBase1())()
226+
// FIXME: crappy diagnostic
227+
self.baseFunc0(ThisBase1())() // expected-error {{unable to infer closure type in the current context}}
228+
self.baseFunc0(ThisDerived1())()
227229
self.baseFunc1(42) // expected-error {{cannot invoke 'baseFunc1' with an argument list of type '(Int)'}}
228-
self.baseFunc1(ThisBase1())(42)
230+
// FIXME: crappy diagnostic
231+
self.baseFunc1(ThisBase1())(42) // expected-error {{unexpected trailing closure}}
232+
self.baseFunc1(ThisDerived1())(42)
229233
self[0] = 42.0 // expected-error {{'ThisDerived1.Type' does not have a member named 'subscript'}}
230234
self.baseStaticVar = 42
231235
self.baseStaticProp = 42

0 commit comments

Comments
 (0)