Skip to content

Commit 23f0d8c

Browse files
committed
Create an inherited conformance in SubstitutionMap::lookupConformance when needed.
If the substituted type for a conformance found via a superclass constraint is a subclass of that superclass, then we should represent that with an InheritedProtocolConformance rather than with the original root conformance that applies to the superclass. If we don't do this, then we end up with spurious inequalities in generic signatures that ought to be equivalent, because some paths use the inherited conformance and some don't, as in SR-12330 | rdar://problem/60174186.
1 parent 1cad4a6 commit 23f0d8c

File tree

3 files changed

+29
-2
lines changed

3 files changed

+29
-2
lines changed

lib/AST/SubstitutionMap.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -355,8 +355,10 @@ SubstitutionMap::lookupConformance(CanType type, ProtocolDecl *proto) const {
355355
// Check whether the superclass conforms.
356356
if (auto superclass = genericSig->getSuperclassBound(type)) {
357357
LookUpConformanceInSignature lookup(getGenericSignature().getPointer());
358-
if (auto conformance = lookup(type->getCanonicalType(), superclass, proto))
358+
auto substType = type.subst(*this);
359+
if (auto conformance = lookup(type->getCanonicalType(), substType, proto)){
359360
return conformance;
361+
}
360362
}
361363

362364
// If the type doesn't conform to this protocol, the result isn't formed

lib/AST/Type.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2400,7 +2400,7 @@ getForeignRepresentable(Type type, ForeignLanguage language,
24002400

24012401
if (wasOptional && !result.isRepresentableAsOptional())
24022402
return failure();
2403-
2403+
24042404
// If our nominal type has type arguments, make sure they are
24052405
// representable as well. Because type arguments are not actually
24062406
// translated separately, whether they are trivially representable
@@ -2447,6 +2447,16 @@ getForeignRepresentable(Type type, ForeignLanguage language,
24472447
break;
24482448
}
24492449
}
2450+
2451+
// Specialize the conformance we were given for the type we're testing.
2452+
if (result.getKind() == ForeignRepresentableKind::Bridged
2453+
&& !result.getConformance()->getType()->isEqual(type)) {
2454+
auto specialized = type->getASTContext()
2455+
.getSpecializedConformance(type, result.getConformance(),
2456+
boundGenericType->getContextSubstitutionMap(dc->getParentModule(),
2457+
boundGenericType->getDecl()));
2458+
result = ForeignRepresentationInfo::forBridged(specialized);
2459+
}
24502460
}
24512461

24522462
return { result.getKind(), result.getConformance() };
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// RUN: %target-swift-emit-silgen %s | %FileCheck %s
2+
protocol P {}
3+
4+
class C: P {}
5+
class D: C {}
6+
7+
struct Butt<T: P> {}
8+
9+
func foo<T: P>(_: (Butt<T>) -> ()) {}
10+
11+
// CHECK-LABEL: sil{{.*}}3bar
12+
func bar(_ f: (Butt<D>) -> ()) {
13+
// CHECK: convert_function {{.*}} $@noescape @callee_guaranteed (Butt<D>) -> () to $@noescape @callee_guaranteed @substituted <τ_0_0 where τ_0_0 : P> (Butt<τ_0_0>) -> () for <D>
14+
foo(f)
15+
}

0 commit comments

Comments
 (0)