Skip to content

Commit c37a4ba

Browse files
committed
Sema: Eagerly resolve typealiases in protocol extensions in ::Structural mode
We resolve protocol typealiases to DependentMemberTypes because the Requirement Machine treats them as rewrite rules. However, it doesn't do this for typealiases in protocol extensions. Fixes rdar://problem/94150249.
1 parent 3ccf723 commit c37a4ba

File tree

2 files changed

+52
-1
lines changed

2 files changed

+52
-1
lines changed

lib/Sema/TypeCheckType.cpp

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -430,7 +430,7 @@ Type TypeResolution::resolveTypeInContext(TypeDecl *typeDecl,
430430
selfType = foundDC->getSelfInterfaceType();
431431

432432
if (selfType->is<GenericTypeParamType>()) {
433-
if (typeDecl->getDeclContext()->getSelfProtocolDecl()) {
433+
if (isa<ProtocolDecl>(typeDecl->getDeclContext())) {
434434
if (isa<AssociatedTypeDecl>(typeDecl) ||
435435
(isa<TypeAliasDecl>(typeDecl) &&
436436
!cast<TypeAliasDecl>(typeDecl)->isGeneric() &&
@@ -1434,6 +1434,23 @@ static Type resolveTopLevelIdentTypeComponent(TypeResolution resolution,
14341434
auto globals = TypeChecker::lookupUnqualifiedType(DC, id, comp->getLoc(),
14351435
lookupOptions);
14361436

1437+
// If we're doing structural resolution and one of the results is an
1438+
// associated type, ignore any other results found from the same
1439+
// DeclContext; they are going to be protocol typealiases, possibly
1440+
// from constrained extensions, and trying to compute their type in
1441+
// resolveTypeInContext() might hit request cycles since structural
1442+
// resolution is performed while computing the requirement signature
1443+
// of the protocol.
1444+
DeclContext *assocTypeDC = nullptr;
1445+
if (resolution.getStage() == TypeResolutionStage::Structural) {
1446+
for (const auto &entry : globals) {
1447+
if (isa<AssociatedTypeDecl>(entry.getValueDecl())) {
1448+
assocTypeDC = entry.getDeclContext();
1449+
break;
1450+
}
1451+
}
1452+
}
1453+
14371454
// Process the names we found.
14381455
Type current;
14391456
TypeDecl *currentDecl = nullptr;
@@ -1443,6 +1460,13 @@ static Type resolveTopLevelIdentTypeComponent(TypeResolution resolution,
14431460
auto *foundDC = entry.getDeclContext();
14441461
auto *typeDecl = cast<TypeDecl>(entry.getValueDecl());
14451462

1463+
// See the comment above.
1464+
if (assocTypeDC != nullptr &&
1465+
foundDC == assocTypeDC && !isa<AssociatedTypeDecl>(typeDecl))
1466+
continue;
1467+
1468+
// Compute the type of the found declaration when referenced from this
1469+
// location.
14461470
Type type = resolveTypeDecl(typeDecl, foundDC, resolution, silParams, comp);
14471471
if (type->is<ErrorType>())
14481472
return type;

test/Generics/rdar94150249.swift

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// RUN: %target-swift-frontend -typecheck %s -debug-generic-signatures 2>&1 | %FileCheck %s
2+
3+
protocol P1 {
4+
associatedtype Value
5+
}
6+
7+
protocol P2 {
8+
associatedtype Value
9+
}
10+
11+
class G<Value> : P2 {}
12+
13+
protocol P3 {}
14+
15+
extension P1 where Value: P2 {
16+
typealias Element = Value.Value
17+
18+
// Make sure we can resolve 'Element' to 'V' on the left hand side of 'Element: P3'.
19+
20+
// CHECK-LABEL: .P1 extension.set()@
21+
// CHECK-NEXT: Generic signature: <Self, V where Self : P1, V : P3, Self.[P1]Value == G<V>>
22+
func set<V>() where Element: P3, Value == G<V> {
23+
takeP3(V.self)
24+
}
25+
}
26+
27+
func takeP3<T : P3>(_: T.Type) {}

0 commit comments

Comments
 (0)