Skip to content

Commit 970740b

Browse files
committed
AST: Fix substitution map composition edge case
Adding `T == Int` to G1 := <T where T: Equatable> gives us G2 := <T where T == Int> which means that if I have this substitution map for G2: S2 := { Int } then `SubstitutionMap::get(G1, S2)` should give me this substitution map for G1: S2 := { Int, [Int: Equatable] } But it didn't, instead returning a substitution map with an invalid conformance. The problem is that local conformance lookup alone cannot recover `[Int: Equatable]` in this case, because there is no "concrete conformance requirement" `[T == Int: Equatable]` recorded anywhere in G2. This is of course a legacy of the GenericSignatureBuilder. It would have been better to not drop conformance requirements made concrete. But oh well. Fixes swiftlang#74465 Fixes rdar://130404629.
1 parent 05ffb67 commit 970740b

File tree

3 files changed

+35
-7
lines changed

3 files changed

+35
-7
lines changed

lib/AST/TypeSubstitution.cpp

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,14 +220,29 @@ operator()(CanType dependentType, Type conformingReplacementType,
220220
ProtocolConformanceRef LookUpConformanceInSubstitutionMap::
221221
operator()(CanType dependentType, Type conformingReplacementType,
222222
ProtocolDecl *conformedProtocol) const {
223+
auto result = Subs.lookupConformance(dependentType, conformedProtocol);
224+
if (!result.isInvalid())
225+
return result;
226+
223227
// Lookup conformances for archetypes that conform concretely
224228
// via a superclass.
225229
if (auto archetypeType = conformingReplacementType->getAs<ArchetypeType>()) {
226230
return conformedProtocol->getModuleContext()->lookupConformance(
227231
conformingReplacementType, conformedProtocol,
228232
/*allowMissing=*/true);
229233
}
230-
return Subs.lookupConformance(dependentType, conformedProtocol);
234+
235+
// Otherwise, the original type might be fixed to a concrete type in
236+
// the substitution map's input generic signature.
237+
if (auto genericSig = Subs.getGenericSignature()) {
238+
if (genericSig->isConcreteType(dependentType)) {
239+
return conformedProtocol->getModuleContext()->lookupConformance(
240+
conformingReplacementType, conformedProtocol,
241+
/*allowMissing=*/true);
242+
}
243+
}
244+
245+
return ProtocolConformanceRef::forInvalid();
231246
}
232247

233248
ProtocolConformanceRef MakeAbstractConformanceForGenericType::
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// RUN: %target-swift-emit-silgen %s
2+
3+
public protocol P {
4+
associatedtype A : Equatable
5+
}
6+
7+
public struct G<A: Equatable>: P {}
8+
9+
extension P where A == Int {
10+
public init(integerLiteral: Int) {
11+
fatalError()
12+
}
13+
}
14+
15+
extension G: ExpressibleByIntegerLiteral where A == Int {}
16+
17+
public func f() -> G<Int> {
18+
return 123
19+
}

validation-test/compiler_crashers_2_fixed/0022-rdar21625478.swift

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,5 @@
11
// RUN: %target-swift-frontend %s -emit-silgen
22

3-
// rdar://80395274 tracks getting this to pass with the requirement machine.
4-
// XFAIL: *
5-
6-
// The test hangs in a noassert build:
7-
// REQUIRES: asserts
8-
93
import StdlibUnittest
104

115
public struct MyRange<Bound : ForwardIndex> {

0 commit comments

Comments
 (0)