Skip to content

Commit ecedb33

Browse files
committed
[Sema] In simplifyType, if substitution fails retry with IUOs stripped.
We can end up with IUOs bound as a result of overload resolution. When this happens and the resulting type is used as a generic, we can end up with dependent member types that fail to simplify properly as a result of failing to substitute due to the IUO getting in the way. In these cases it should be completely safe to strip the IUO off and retry substitution with the base type. This isn't really an ideal fix by any means, and we need to revisit how we handle bindings to make it more uniform, but for now I think this is a reasonable path to move forward. Fixes a source compatibility regression. rdar://problem/29960575
1 parent 1d2aa8d commit ecedb33

File tree

2 files changed

+43
-7
lines changed

2 files changed

+43
-7
lines changed

lib/Sema/ConstraintSystem.cpp

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1564,12 +1564,11 @@ Type simplifyTypeImpl(ConstraintSystem &cs, Type type, Fn getFixedTypeFn) {
15641564
if (newBase.getPointer() == depMemTy->getBase().getPointer())
15651565
return type;
15661566

1567-
Type lookupBaseType = newBase->getLValueOrInOutObjectType();
1568-
15691567
// Dependent member types should only be created for associated types.
15701568
auto assocType = depMemTy->getAssocType();
1571-
assert(depMemTy->getAssocType());
1569+
assert(depMemTy->getAssocType() && "Expected associated type!");
15721570

1571+
Type lookupBaseType = newBase->getLValueOrInOutObjectType();
15731572
if (!lookupBaseType->mayHaveMembers()) return type;
15741573

15751574
auto result = assocType->getDeclaredInterfaceType()
@@ -1578,12 +1577,32 @@ Type simplifyTypeImpl(ConstraintSystem &cs, Type type, Fn getFixedTypeFn) {
15781577
assocType->getDeclContext()));
15791578

15801579

1581-
if (!result) {
1582-
return DependentMemberType::get(
1583-
ErrorType::get(newBase), assocType);
1580+
if (result)
1581+
return result;
1582+
1583+
if (!lookupBaseType->getImplicitlyUnwrappedOptionalObjectType())
1584+
return DependentMemberType::get(ErrorType::get(newBase), assocType);
1585+
1586+
// "Force" the IUO for substitution purposes. We can end up in
1587+
// this situation if we use the results of overload resolution
1588+
// as a generic type and the overload resolution resulted in an
1589+
// IUO-typed entity.
1590+
while (auto objectType =
1591+
lookupBaseType->getImplicitlyUnwrappedOptionalObjectType()) {
1592+
lookupBaseType = objectType;
15841593
}
15851594

1586-
return result;
1595+
if (!lookupBaseType->mayHaveMembers()) return type;
1596+
1597+
result = assocType->getDeclaredInterfaceType()
1598+
.subst(cs.DC->getParentModule(),
1599+
lookupBaseType->getContextSubstitutions(
1600+
assocType->getDeclContext()));
1601+
1602+
if (result)
1603+
return result;
1604+
1605+
return DependentMemberType::get(ErrorType::get(newBase), assocType);
15871606
}
15881607

15891608
// If this is a FunctionType and we inferred new function attributes, apply

test/Constraints/dynamic_lookup.swift

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,3 +230,20 @@ var anyDict: [String : Any] = Dictionary<String, Any>()
230230
anyDict["test"] = anyValue
231231
_ = anyDict["test"]!.bar() // expected-error {{value of type 'Any' has no member 'bar'}}
232232
// expected-note@-1 {{cast 'Any' to 'AnyObject' or use 'as!' to force downcast to a more specific type to access members}}{{5-5=(}}{{21-21= as AnyObject)}}
233+
234+
// Test that overload resolution during constraint solving of values
235+
// looked-up dynamically through AnyObject are treated as conforming
236+
// to the protocols they are supposed to conform to.
237+
class NSObjDerived1 : NSObject {
238+
var everything: [Any] = []
239+
}
240+
241+
class NSObjDerived2 : NSObject {
242+
var everything: Any = 1
243+
}
244+
245+
func rdar29960565(_ o: AnyObject) {
246+
for i in o.everything {
247+
_ = i
248+
}
249+
}

0 commit comments

Comments
 (0)