Skip to content

Commit d49a20e

Browse files
committed
Eliminate use of the opaque type's generic environment from type matching.
Introduce a new primitive operation on opaque type archetypes that canonicalizes a type within the environment of the opaque type archetype without building the environment itself. Use it when matching opaque archetype types in the solver.
1 parent 52194b2 commit d49a20e

File tree

3 files changed

+70
-13
lines changed

3 files changed

+70
-13
lines changed

include/swift/AST/Types.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5587,7 +5587,11 @@ class OpaqueTypeArchetypeType final : public ArchetypeType,
55875587

55885588
/// Get a generic environment that has this opaque archetype bound within it.
55895589
GenericEnvironment *getGenericEnvironment() const;
5590-
5590+
5591+
/// Compute the canonical interface type within the environment of this
5592+
/// opaque type archetype.
5593+
CanType getCanonicalInterfaceType(Type interfaceType);
5594+
55915595
static bool classof(const TypeBase *T) {
55925596
return T->getKind() == TypeKind::OpaqueTypeArchetype;
55935597
}

lib/AST/Type.cpp

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3304,6 +3304,63 @@ SequenceArchetypeType::SequenceArchetypeType(
33043304
assert(cast<GenericTypeParamType>(InterfaceType.getPointer())->isTypeSequence());
33053305
}
33063306

3307+
namespace {
3308+
3309+
/// Substitute the outer generic parameters from a substitution map, ignoring
3310+
/// innter generic parameters with a given depth.
3311+
struct SubstituteOuterFromSubstitutionMap {
3312+
SubstitutionMap subs;
3313+
unsigned depth;
3314+
3315+
/// Whether this is a type parameter that should not be substituted.
3316+
bool isUnsubstitutedTypeParameter(Type type) const {
3317+
if (!type->isTypeParameter())
3318+
return false;
3319+
3320+
if (auto depMemTy = type->getAs<DependentMemberType>())
3321+
return isUnsubstitutedTypeParameter(depMemTy->getBase());
3322+
3323+
if (auto genericParam = type->getAs<GenericTypeParamType>())
3324+
return genericParam->getDepth() >= depth;
3325+
3326+
return false;
3327+
}
3328+
3329+
Type operator()(SubstitutableType *type) const {
3330+
if (isUnsubstitutedTypeParameter(type))
3331+
return Type(type);
3332+
3333+
return QuerySubstitutionMap{subs}(type);
3334+
}
3335+
3336+
ProtocolConformanceRef operator()(CanType dependentType,
3337+
Type conformingReplacementType,
3338+
ProtocolDecl *conformedProtocol) const {
3339+
if (isUnsubstitutedTypeParameter(dependentType))
3340+
return ProtocolConformanceRef(conformedProtocol);
3341+
3342+
return LookUpConformanceInSubstitutionMap(subs)(
3343+
dependentType, conformingReplacementType, conformedProtocol);
3344+
}
3345+
};
3346+
3347+
}
3348+
3349+
CanType OpaqueTypeArchetypeType::getCanonicalInterfaceType(Type interfaceType) {
3350+
// Compute the canonical type within the generic signature of the opaque
3351+
// type declaration.
3352+
auto sig = getDecl()->getOpaqueInterfaceGenericSignature();
3353+
CanType canonicalType = interfaceType->getCanonicalType(sig);
3354+
if (!interfaceType->hasTypeParameter())
3355+
return canonicalType;
3356+
3357+
// Substitute outer generic parameters only.
3358+
unsigned opaqueDepth =
3359+
getDecl()->getOpaqueGenericParams().front()->getDepth();
3360+
SubstituteOuterFromSubstitutionMap replacer{Substitutions, opaqueDepth};
3361+
return canonicalType.subst(replacer, replacer)->getCanonicalType();
3362+
}
3363+
33073364
GenericEnvironment *OpaqueTypeArchetypeType::getGenericEnvironment() const {
33083365
if (Environment)
33093366
return Environment;

lib/Sema/CSSimplify.cpp

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2851,12 +2851,10 @@ ConstraintSystem::matchDeepEqualityTypes(Type type1, Type type2,
28512851
auto arch2 = type2->castTo<ArchetypeType>();
28522852
auto opaque1 = cast<OpaqueTypeArchetypeType>(arch1->getRoot());
28532853
auto opaque2 = cast<OpaqueTypeArchetypeType>(arch2->getRoot());
2854-
assert(arch1->getInterfaceType()->getCanonicalType(
2855-
opaque1->getGenericEnvironment()->getGenericSignature())
2856-
== arch2->getInterfaceType()->getCanonicalType(
2857-
opaque2->getGenericEnvironment()->getGenericSignature()));
28582854
assert(opaque1->getDecl() == opaque2->getDecl());
2859-
2855+
assert(opaque1->getCanonicalInterfaceType(arch1->getInterfaceType())->isEqual(
2856+
opaque2->getCanonicalInterfaceType(arch2->getInterfaceType())));
2857+
28602858
auto args1 = opaque1->getSubstitutions().getReplacementTypes();
28612859
auto args2 = opaque2->getSubstitutions().getReplacementTypes();
28622860

@@ -5896,13 +5894,11 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
58965894
auto rootOpaque1 = dyn_cast<OpaqueTypeArchetypeType>(nested1->getRoot());
58975895
auto rootOpaque2 = dyn_cast<OpaqueTypeArchetypeType>(nested2->getRoot());
58985896
if (rootOpaque1 && rootOpaque2) {
5899-
auto interfaceTy1 = nested1->getInterfaceType()
5900-
->getCanonicalType(rootOpaque1->getGenericEnvironment()
5901-
->getGenericSignature());
5902-
auto interfaceTy2 = nested2->getInterfaceType()
5903-
->getCanonicalType(rootOpaque2->getGenericEnvironment()
5904-
->getGenericSignature());
5905-
if (interfaceTy1 == interfaceTy2
5897+
auto interfaceTy1 = rootOpaque1->getCanonicalInterfaceType(
5898+
nested1->getInterfaceType());
5899+
auto interfaceTy2 = rootOpaque2->getCanonicalInterfaceType(
5900+
nested2->getInterfaceType());
5901+
if (interfaceTy1->isEqual(interfaceTy2)
59065902
&& rootOpaque1->getDecl() == rootOpaque2->getDecl()) {
59075903
conversionsOrFixes.push_back(ConversionRestrictionKind::DeepEquality);
59085904
break;

0 commit comments

Comments
 (0)