Skip to content

Commit 16e9902

Browse files
authored
Merge pull request #71621 from slavapestov/assoc-type-regression-fixes-5
Sema: Try not to let protocol type aliases leak into inferred type witnesses
2 parents 9780246 + ffd651c commit 16e9902

File tree

3 files changed

+77
-4
lines changed

3 files changed

+77
-4
lines changed

lib/Sema/AssociatedTypeInference.cpp

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -986,7 +986,6 @@ class AssociatedTypeInference {
986986

987987
/// Infer associated type witnesses for the given associated type.
988988
InferredAssociatedTypesByWitnesses inferTypeWitnessesViaAssociatedType(
989-
const llvm::SetVector<AssociatedTypeDecl *> &allUnresolved,
990989
AssociatedTypeDecl *assocType);
991990

992991
/// Infer associated type witnesses for all relevant value requirements.
@@ -1790,8 +1789,7 @@ AssociatedTypeInference::inferTypeWitnessesViaValueWitnesses(
17901789
if (assocTypes.count(assocType) == 0)
17911790
continue;
17921791

1793-
auto reqInferred = inferTypeWitnessesViaAssociatedType(assocTypes,
1794-
assocType);
1792+
auto reqInferred = inferTypeWitnessesViaAssociatedType(assocType);
17951793
if (!reqInferred.empty())
17961794
result.push_back({req, std::move(reqInferred)});
17971795

@@ -1853,6 +1851,19 @@ static Type mapErrorTypeToOriginal(Type type) {
18531851
return type;
18541852
}
18551853

1854+
/// Desugar protocol type aliases, since they can cause request cycles in
1855+
/// type resolution if printed in a module interface and parsed back in.
1856+
static Type getWithoutProtocolTypeAliases(Type type) {
1857+
return type.transformRec([](TypeBase *t) -> llvm::Optional<Type> {
1858+
if (auto *aliasTy = dyn_cast<TypeAliasType>(t)) {
1859+
if (aliasTy->getDecl()->getDeclContext()->getExtendedProtocolDecl())
1860+
return getWithoutProtocolTypeAliases(aliasTy->getSinglyDesugaredType());
1861+
}
1862+
1863+
return llvm::None;
1864+
});
1865+
}
1866+
18561867
/// Produce the type when matching a witness.
18571868
///
18581869
/// If the witness is a member of the type itself or a superclass, we
@@ -1886,6 +1897,9 @@ static Type getWitnessTypeForMatching(NormalProtocolConformance *conformance,
18861897
conformance->getDeclContext()->mapTypeIntoContext(conformance->getType());
18871898
TypeSubstitutionMap substitutions = model->getMemberSubstitutions(witness);
18881899
Type type = witness->getInterfaceType()->getReferenceStorageReferent();
1900+
1901+
type = getWithoutProtocolTypeAliases(type);
1902+
18891903
LLVM_DEBUG(llvm::dbgs() << "Witness interface type is " << type << "\n";);
18901904

18911905
if (substitutions.empty())
@@ -1998,7 +2012,6 @@ static Type removeSelfParam(ValueDecl *value, Type type) {
19982012

19992013
InferredAssociatedTypesByWitnesses
20002014
AssociatedTypeInference::inferTypeWitnessesViaAssociatedType(
2001-
const llvm::SetVector<AssociatedTypeDecl *> &allUnresolved,
20022015
AssociatedTypeDecl *assocType) {
20032016
InferredAssociatedTypesByWitnesses result;
20042017

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// RUN: %target-swift-emit-module-interface(%t.swiftinterface) %s -module-name protocol_extension_type_witness -enable-experimental-associated-type-inference
2+
// RUN: %target-swift-typecheck-module-from-interface(%t.swiftinterface) -module-name protocol_extension_type_witness
3+
// RUN: %FileCheck %s < %t.swiftinterface
4+
5+
// RUN: %target-swift-emit-module-interface(%t.swiftinterface) %s -module-name protocol_extension_type_witness -disable-experimental-associated-type-inference
6+
// RUN: %target-swift-typecheck-module-from-interface(%t.swiftinterface) -module-name protocol_extension_type_witness
7+
// RUN: %FileCheck %s < %t.swiftinterface
8+
9+
public protocol P {
10+
associatedtype A
11+
associatedtype B
12+
associatedtype C
13+
associatedtype D
14+
15+
func b(_: B)
16+
func c(_: C)
17+
func d(_: D)
18+
}
19+
20+
extension P {
21+
public typealias _Default_A = B
22+
public typealias Alias = D
23+
24+
public func c(_: Alias) {}
25+
}
26+
27+
public struct S<B>: P {
28+
public func b(_: B) {}
29+
public func d(_: String) {}
30+
}
31+
32+
// CHECK-LABEL: public struct S<B> : protocol_extension_type_witness.P {
33+
// CHECK-NEXT: public func b(_: B)
34+
// CHECK-NEXT: public func d(_: Swift.String)
35+
// CHECK-NEXT: public typealias A = B
36+
// CHECK-NEXT: public typealias C = Swift.String
37+
// CHECK-NEXT: public typealias D = Swift.String
38+
// CHECK-NEXT: }
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// RUN: %target-typecheck-verify-swift -enable-experimental-associated-type-inference
2+
// RUN: not %target-typecheck-verify-swift -disable-experimental-associated-type-inference
3+
4+
// Reduced from the distributed actors implementation. This didn't type check in 5.10
5+
// but works now.
6+
7+
protocol DistributedActorSystem<SerializationRequirement> {
8+
associatedtype SerializationRequirement
9+
}
10+
11+
protocol DistributedActor where SerializationRequirement == ActorSystem.SerializationRequirement {
12+
associatedtype ActorSystem: DistributedActorSystem
13+
associatedtype SerializationRequirement
14+
}
15+
16+
class Worker<ActorSystem>: DistributedActor where ActorSystem: DistributedActorSystem, ActorSystem.SerializationRequirement == Int {}
17+
18+
struct FakeActorSystem: DistributedActorSystem {
19+
typealias SerializationRequirement = Int
20+
}
21+
22+
print(Worker<FakeActorSystem>.SerializationRequirement.self)

0 commit comments

Comments
 (0)