Skip to content

Commit 477e057

Browse files
committed
Sema: Tighten invariants in associated type inference
1 parent 1867b38 commit 477e057

File tree

2 files changed

+20
-30
lines changed

2 files changed

+20
-30
lines changed

lib/Sema/AssociatedTypeInference.cpp

Lines changed: 17 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2316,7 +2316,7 @@ AssociatedTypeInference::computeAbstractTypeWitness(
23162316
continue;
23172317

23182318
if (gp->getName() == assocType->getName())
2319-
return AbstractTypeWitness(assocType, gp);
2319+
return AbstractTypeWitness(assocType, dc->mapTypeIntoContext(gp));
23202320
}
23212321
}
23222322

@@ -2348,7 +2348,8 @@ void AssociatedTypeInference::collectAbstractTypeWitnesses(
23482348
continue;
23492349

23502350
if (gp->getName() == assocType->getName()) {
2351-
system.addTypeWitness(assocType->getName(), gp);
2351+
system.addTypeWitness(assocType->getName(),
2352+
dc->mapTypeIntoContext(gp));
23522353
}
23532354
}
23542355
}
@@ -2661,6 +2662,8 @@ AssociatedTypeDecl *AssociatedTypeInference::inferAbstractTypeWitnesses(
26612662
// not resolve otherwise.
26622663
llvm::SmallVector<AbstractTypeWitness, 2> abstractTypeWitnesses;
26632664

2665+
auto selfTypeInContext = dc->getSelfTypeInContext();
2666+
26642667
if (ctx.LangOpts.EnableExperimentalAssociatedTypeInference) {
26652668
TypeWitnessSystem system(unresolvedAssocTypes);
26662669
collectAbstractTypeWitnesses(system, unresolvedAssocTypes);
@@ -2683,12 +2686,9 @@ AssociatedTypeDecl *AssociatedTypeInference::inferAbstractTypeWitnesses(
26832686

26842687
resolvedTy = resolvedTy.transformRec([&](Type ty) -> llvm::Optional<Type> {
26852688
if (auto *gp = ty->getAs<GenericTypeParamType>()) {
2686-
// FIXME: 'computeFixedTypeWitness' uses 'getReducedType',
2687-
// so if a generic parameter is canonical here, it's 'Self'.
2688-
if (gp->isCanonical() ||
2689-
isa<ProtocolDecl>(gp->getDecl()->getDeclContext()->getAsDecl())) {
2690-
return adoptee;
2691-
}
2689+
assert(gp->getDepth() == 0);
2690+
assert(gp->getIndex() == 0);
2691+
return selfTypeInContext;
26922692
}
26932693

26942694
return llvm::None;
@@ -2715,12 +2715,9 @@ AssociatedTypeDecl *AssociatedTypeInference::inferAbstractTypeWitnesses(
27152715

27162716
resolvedTy = resolvedTy.transformRec([&](Type ty) -> llvm::Optional<Type> {
27172717
if (auto *gp = ty->getAs<GenericTypeParamType>()) {
2718-
// FIXME: 'computeFixedTypeWitness' uses 'getReducedType',
2719-
// so if a generic parameter is canonical here, it's 'Self'.
2720-
if (gp->isCanonical() ||
2721-
isa<ProtocolDecl>(gp->getDecl()->getDeclContext()->getAsDecl())) {
2722-
return adoptee;
2723-
}
2718+
assert(gp->getDepth() == 0);
2719+
assert(gp->getIndex() == 0);
2720+
return selfTypeInContext;
27242721
}
27252722

27262723
return llvm::None;
@@ -2763,8 +2760,10 @@ AssociatedTypeDecl *AssociatedTypeInference::inferAbstractTypeWitnesses(
27632760
LLVM_DEBUG(llvm::dbgs() << "Checking witness for " << assocType->getName()
27642761
<< " " << type << "\n";);
27652762

2763+
assert(!type->hasTypeParameter());
2764+
27662765
// Replace type parameters with other known or tentative type witnesses.
2767-
if (type->hasDependentMember() || type->hasTypeParameter()) {
2766+
if (type->hasDependentMember()) {
27682767
// FIXME: We should find a better way to detect and reason about these
27692768
// cyclic solutions so that we can spot them earlier and express them in
27702769
// diagnostics.
@@ -2826,27 +2825,20 @@ AssociatedTypeDecl *AssociatedTypeInference::inferAbstractTypeWitnesses(
28262825
Type tyWitness;
28272826
if (assocTy->getProtocol() == proto && typeWitnesses.count(assocTy)) {
28282827
tyWitness = typeWitnesses.begin(assocTy)->first;
2828+
assert(!tyWitness->hasTypeParameter());
28292829

28302830
// A tentative type witness may contain a 'Self'-rooted type
28312831
// parameter,
28322832
// FIXME: or a weird concrete-type-rooted dependent member type
28332833
// coming from inference via a value witness. Make sure we sort these
28342834
// out so that we don't break any subst() invariants.
2835-
if (tyWitness->hasTypeParameter() ||
2836-
tyWitness->hasDependentMember()) {
2835+
if (tyWitness->hasDependentMember()) {
28372836
tyWitness = tyWitness.transformRec(substCurrentTypeWitnesses);
28382837
}
28392838

28402839
if (tyWitness) {
2841-
// HACK: Those inferred via value witnesses are eagerly mapped into
2842-
// context. For now, do the same for abstract type witnesses and
2843-
// handle archetypes.
2844-
if (tyWitness->hasArchetype()) {
2845-
tyWitness = tyWitness->mapTypeOutOfContext();
2846-
}
2847-
28482840
// If the transformed base is specialized, apply substitutions.
2849-
if (tyWitness->hasTypeParameter()) {
2841+
if (tyWitness->hasArchetype()) {
28502842
const auto conf = dc->getParentModule()->lookupConformance(
28512843
substBase, assocTy->getProtocol(), /*allowMissing=*/true);
28522844
if (auto *specialized = dyn_cast<SpecializedProtocolConformance>(
@@ -2878,8 +2870,6 @@ AssociatedTypeDecl *AssociatedTypeInference::inferAbstractTypeWitnesses(
28782870
// If any unresolved dependent member types remain, give up.
28792871
assert(!containsConcreteDependentMemberType(type));
28802872

2881-
type = dc->mapTypeIntoContext(type);
2882-
28832873
LLVM_DEBUG(llvm::dbgs() << "Simplified witness type is " << type << "\n";);
28842874
}
28852875

validation-test/compiler_crashers_2_fixed/0163-issue-50566.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ protocol P1 {
88
associatedtype A // expected-note {{protocol requires nested type 'A'; add nested type 'A' for conformance}}
99
}
1010
extension Foo: P1 where A : P1 {}
11-
// expected-error@-1 {{extension of generic struct 'Foo' has self-referential generic requirements}}
12-
// expected-note@-2 {{while resolving type 'A'}}
13-
// expected-note@-3 2{{through reference here}}
11+
// expected-error@-1 2{{extension of generic struct 'Foo' has self-referential generic requirements}}
12+
// expected-note@-2 2{{while resolving type 'A'}}
13+
// expected-note@-3 4{{through reference here}}
1414
// expected-error@-4 {{type 'Foo<T>' does not conform to protocol 'P1'}}

0 commit comments

Comments
 (0)