Skip to content

Commit d34222d

Browse files
committed
[CSBindings] Avoid delaying leading-dot inference only if chain is directly connected to a contextual type
Additional restrictions on when protocol inference could be considered viable. If the chain is connected directly to a contextual type there cannot be any other inference sources for the base type. Resolves: rdar://148256978
1 parent 367e5e2 commit d34222d

File tree

2 files changed

+40
-6
lines changed

2 files changed

+40
-6
lines changed

lib/Sema/CSBindings.cpp

+13-6
Original file line numberDiff line numberDiff line change
@@ -130,12 +130,19 @@ bool BindingSet::isDelayed() const {
130130
return true;
131131

132132
if (Bindings[0].BindingType->is<ProtocolType>()) {
133-
auto *locator = Bindings[0].getLocator();
134-
// If the binding got inferred from a contextual type
135-
// this set shouldn't be delayed because there won't
136-
// be any other inference sources for this leading-dot
137-
// syntax member.
138-
if (!locator->findLast<LocatorPathElt::ContextualType>())
133+
auto *bindingLoc = Bindings[0].getLocator();
134+
// This set shouldn't be delayed because there won't be any
135+
// other inference sources when the protocol binding got
136+
// inferred from a contextual type and the leading-dot chain
137+
// this type variable is a base of, is connected directly to it.
138+
139+
if (!bindingLoc->findLast<LocatorPathElt::ContextualType>())
140+
return true;
141+
142+
auto *chainResult =
143+
getAsExpr<UnresolvedMemberChainResultExpr>(bindingLoc->getAnchor());
144+
if (!chainResult || CS.getParentExpr(chainResult) ||
145+
chainResult->getChainBase() != getAsExpr(locator->getAnchor()))
139146
return true;
140147
}
141148
}

test/expr/delayed-ident/member_chains.swift

+27
Original file line numberDiff line numberDiff line change
@@ -382,3 +382,30 @@ func acceptInt(_ x: Int) {}
382382
func postfixOpIsNotAMemberChain() {
383383
acceptInt(.implicit.another^)
384384
}
385+
386+
// Ensure that base type doesn't get bound to a protocol type too eagerly
387+
do {
388+
struct V : Hashable {
389+
static let v1: V = V()
390+
static let v2: V = V()
391+
}
392+
393+
let _: Set = [V.v1, .v2] // Ok
394+
395+
struct Elements : RandomAccessCollection {
396+
init() {}
397+
init(_ elements: [Int]) {}
398+
399+
var startIndex: Int { 0 }
400+
var endIndex: Int { 0 }
401+
subscript(index: Int) -> Int { 0 }
402+
}
403+
404+
struct TestNilCoalescing {
405+
var data: Elements?
406+
407+
func test() {
408+
for _ in self.data ?? .init() {} // Ok
409+
}
410+
}
411+
}

0 commit comments

Comments
 (0)