Skip to content

Commit 59ee97f

Browse files
committed
[SE-0143] Try harder to substitute conditional requirements fully.
When forming a specialized protocol conformance, we substitute into the conditional requirements. Allow this substitution to look into the module to find conformances, which might be required to accurately represented the requirements. Otherwise, we can silently end up dropping them. We should rethink this notion of eagerly substituting conditional requirements, and consider whether clients should always handle this substitution. For now, fixes rdar://problem/35837054. Allow conformance lookup in module context for conditional
1 parent fde0d92 commit 59ee97f

File tree

2 files changed

+30
-4
lines changed

2 files changed

+30
-4
lines changed

lib/AST/ProtocolConformance.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -747,13 +747,13 @@ SpecializedProtocolConformance::SpecializedProtocolConformance(
747747
// terms of the specialized types, not the conformance-declaring decl's
748748
// types.
749749
auto nominal = GenericConformance->getType()->getAnyNominal();
750-
auto subMap =
751-
getType()->getContextSubstitutionMap(nominal->getModuleContext(),
752-
nominal);
750+
auto module = nominal->getModuleContext();
751+
auto subMap = getType()->getContextSubstitutionMap(module, nominal);
753752

754753
SmallVector<Requirement, 4> newReqs;
755754
for (auto oldReq : GenericConformance->getConditionalRequirements()) {
756-
if (auto newReq = oldReq.subst(subMap))
755+
if (auto newReq = oldReq.subst(QuerySubstitutionMap{subMap},
756+
LookUpConformanceInModule(module)))
757757
newReqs.push_back(*newReq);
758758
}
759759
auto &ctxt = getProtocol()->getASTContext();

test/Generics/conditional_conformances.swift

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,3 +334,29 @@ func existential_bad<T>(_: T.Type) {
334334
_ = Free<T>() as P2 // expected-error{{'Free<T>' is not convertible to 'P2'; did you mean to use 'as!' to force downcast?}}
335335
}
336336

337+
// rdar://problem/35837054
338+
protocol P7 { }
339+
340+
protocol P8 {
341+
associatedtype A
342+
}
343+
344+
struct X0 { }
345+
346+
struct X1 { }
347+
348+
extension X1: P8 {
349+
typealias A = X0
350+
}
351+
352+
struct X2<T> { }
353+
354+
extension X2: P7 where T: P8, T.A: P7 { }
355+
356+
func takesF7<T: P7>(_: T) { }
357+
func passesConditionallyNotF7(x21: X2<X1>) {
358+
takesF7(x21) // expected-error{{type 'X1.A' (aka 'X0') does not conform to protocol 'P7'}}
359+
// expected-error@-1{{'<T where T : P7> (T) -> ()' requires that 'X1.A' (aka 'X0') conform to 'P7'}}
360+
// expected-note@-2{{requirement specified as 'X1.A' (aka 'X0') : 'P7'}}
361+
// expected-note@-3{{requirement from conditional conformance of 'X2<X1>' to 'P7'}}
362+
}

0 commit comments

Comments
 (0)