Skip to content

Commit a62ab69

Browse files
committed
IRGen: Workaround for type substitution limitation
If a constrained extension has fewer conformance requirements than the nominal type declaration, because some of the type parameters of the nominal type are fixed to concrete types by the extension, we would run into trouble because interface type substitution does not correctly handle this case. Applying an identity substitution map to an interface type does not look up concrete types in the output generic signature, so we get back a type parameter that is not valid. getReducedType() has a hack to deal with this. I'd like to get rid of the hack and fix interface type substitution to do this correctly, but until then, this will do. Fixes #76479
1 parent c9c962b commit a62ab69

File tree

2 files changed

+35
-0
lines changed

2 files changed

+35
-0
lines changed

lib/IRGen/GenProto.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,10 +111,24 @@ class PolymorphicConvention {
111111
FulfillmentMap Fulfillments;
112112

113113
GenericSignature::RequiredProtocols getRequiredProtocols(Type t) {
114+
// FIXME: We need to rework this to use archetypes instead of interface
115+
// types, or fix the bad interaction between interface type substitution
116+
// and concretized conformance requirements. Then we can remove the hack
117+
// from getReducedType() to handle this case, and also stop calling
118+
// getReducedType() here.
119+
t = Generics.getReducedType(t);
120+
if (!t->isTypeParameter())
121+
return {};
122+
114123
return Generics->getRequiredProtocols(t);
115124
}
116125

117126
CanType getSuperclassBound(Type t) {
127+
// See above.
128+
t = Generics.getReducedType(t);
129+
if (!t->isTypeParameter())
130+
return CanType();
131+
118132
if (auto superclassTy = Generics->getSuperclassBound(t))
119133
return superclassTy->getCanonicalType();
120134
return CanType();
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// RUN: %target-swift-frontend -emit-ir %s
2+
3+
// https://github.com/swiftlang/swift/issues/76479
4+
5+
public struct G<T> where T: P1, T.A: P1, T.A.A: P1 {}
6+
7+
public protocol P1 {
8+
associatedtype A
9+
}
10+
11+
extension Int: P1 {
12+
public typealias A = Int
13+
}
14+
15+
public protocol P2 {
16+
func f()
17+
}
18+
19+
extension G: P2 where T.A == Int {
20+
public func f() {}
21+
}

0 commit comments

Comments
 (0)