Skip to content

Commit 8ab5ca2

Browse files
committed
Sema: Use weighted reduction order for opaque return types
If the opaque generic signature has a same-type requirement between an outer type parameter and an opaque type parameter, the former should always precede the latter in the type parameter order, even if it is longer. Achieve this by giving the innermost generic parameters a non-zero weight in the opaque generic signature. Now, when we map a type parameter into an opaque generic environment, we correctly decide if it is represented by a type parameter of the outer generic signature, in which case we apply the outer substitution map instead of instantiating an archetype. The included test case demonstrates the issue; we declare an opaque return type `some P<T.A.A>`, so the opaque generic signature has a requirement `T.A.A == <<some P>>.A`. Previously, the reduced type of `<<some P>>.A` was `<<some P>>.A`, so it remained opaque; now we apply outer substitutions to `T.A.A`. - Fixes #81036. - Fixes rdar://problem/149871931.
1 parent 651e0af commit 8ab5ca2

File tree

2 files changed

+31
-4
lines changed

2 files changed

+31
-4
lines changed

lib/Sema/TypeCheckGeneric.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ OpaqueResultTypeRequest::evaluate(Evaluator &evaluator,
142142
for (unsigned i = 0; i < opaqueReprs.size(); ++i) {
143143
auto *currentRepr = opaqueReprs[i];
144144

145-
if( auto opaqueReturn = dyn_cast<OpaqueReturnTypeRepr>(currentRepr) ) {
145+
if (auto opaqueReturn = dyn_cast<OpaqueReturnTypeRepr>(currentRepr)) {
146146
// Usually, we resolve the opaque constraint and bail if it isn't a class
147147
// or existential type (see below). However, in this case we know we will
148148
// fail, so we can bail early and provide a better diagnostic.
@@ -163,13 +163,13 @@ OpaqueResultTypeRequest::evaluate(Evaluator &evaluator,
163163
}
164164
}
165165

166-
auto *paramType = GenericTypeParamType::getType(opaqueSignatureDepth, i,
167-
ctx);
166+
auto *paramType = GenericTypeParamType::getOpaqueResultType(
167+
opaqueSignatureDepth, i, ctx);
168168
genericParamTypes.push_back(paramType);
169169

170170
TypeRepr *constraint = currentRepr;
171171

172-
if (auto opaqueReturn = dyn_cast<OpaqueReturnTypeRepr>(currentRepr)){
172+
if (auto opaqueReturn = dyn_cast<OpaqueReturnTypeRepr>(currentRepr)) {
173173
constraint = opaqueReturn->getConstraint();
174174
}
175175
// Try to resolve the constraint repr in the parent decl context. It
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// RUN: %target-swift-emit-silgen %s
2+
3+
protocol N {
4+
associatedtype A: N
5+
}
6+
7+
struct G<T>: N {
8+
typealias A = G<G<T>>
9+
}
10+
11+
protocol P<A> {
12+
associatedtype A
13+
}
14+
15+
struct GG<T>: P {
16+
typealias A = T
17+
}
18+
19+
func f<T: N>(_: T) -> some P<T.A.A> {
20+
return GG<T.A.A>()
21+
}
22+
23+
func g<T: P>(_: T) -> T.A { fatalError() }
24+
25+
func h(_: G<G<G<Int>>>) {}
26+
27+
h(g(f(G<Int>())))

0 commit comments

Comments
 (0)