Skip to content

Commit d7f2fc8

Browse files
rudkxtkremenek
authored andcommitted
[Sema] In simplifyType, if substitution fails retry with IUOs stripped. (#7196)
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 (cherry picked from ecedb33 with edits to handle conflicts between branches)
1 parent 36e166c commit d7f2fc8

File tree

2 files changed

+47
-6
lines changed

2 files changed

+47
-6
lines changed

lib/Sema/ConstraintSystem.cpp

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1570,6 +1570,10 @@ Type ConstraintSystem::simplifyType(Type type) {
15701570
if (newBase.getPointer() == depMemTy->getBase().getPointer())
15711571
return type;
15721572

1573+
// Dependent member types should only be created for associated types.
1574+
auto assocType = depMemTy->getAssocType();
1575+
assert(depMemTy->getAssocType());
1576+
15731577
Type lookupBaseType = newBase->getLValueOrInOutObjectType();
15741578

15751579
// If the new base is still something we can't handle, just build a
@@ -1582,21 +1586,41 @@ Type ConstraintSystem::simplifyType(Type type) {
15821586
return DependentMemberType::get(newBase, assocType);
15831587
}
15841588

1585-
// Dependent member types should only be created for associated types.
1586-
auto assocType = depMemTy->getAssocType();
1587-
assert(depMemTy->getAssocType());
1588-
15891589
if (!lookupBaseType->mayHaveMembers()) return type;
15901590

15911591
auto result = assocType->getDeclaredInterfaceType()
15921592
.subst(DC->getParentModule(),
15931593
lookupBaseType->getContextSubstitutions(
15941594
assocType->getDeclContext()));
15951595

1596+
if (result)
1597+
return result;
1598+
15961599
// FIXME: Record failure somehow?
1597-
if (!result) return type;
1600+
if (!lookupBaseType->getImplicitlyUnwrappedOptionalObjectType())
1601+
return type;
15981602

1599-
return result;
1603+
// "Force" the IUO for substitution purposes. We can end up in
1604+
// this situation if we use the results of overload resolution
1605+
// as a generic type and the overload resolution resulted in an
1606+
// IUO-typed entity.
1607+
while (auto objectType =
1608+
lookupBaseType->getImplicitlyUnwrappedOptionalObjectType()) {
1609+
lookupBaseType = objectType;
1610+
}
1611+
1612+
if (!lookupBaseType->mayHaveMembers()) return type;
1613+
1614+
result = assocType->getDeclaredInterfaceType()
1615+
.subst(DC->getParentModule(),
1616+
lookupBaseType->getContextSubstitutions(
1617+
assocType->getDeclContext()));
1618+
1619+
if (result)
1620+
return result;
1621+
1622+
// FIXME: Record failure somehow?
1623+
return type;
16001624
}
16011625

16021626
// 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)