Skip to content

Commit 872f242

Browse files
authored
Merge pull request #77683 from slavapestov/opened-type-optzn
Sema: Clean up and optimize interface type opening
2 parents 26e888e + 9a93a8a commit 872f242

File tree

7 files changed

+106
-113
lines changed

7 files changed

+106
-113
lines changed

include/swift/Sema/ConstraintSystem.h

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1198,9 +1198,6 @@ struct Score {
11981198
/// variable.
11991199
using OpenedType = std::pair<GenericTypeParamType *, TypeVariableType *>;
12001200

1201-
using OpenedTypeMap =
1202-
llvm::DenseMap<GenericTypeParamType *, TypeVariableType *>;
1203-
12041201
/// Describes the information about a case label item that needs to be tracked
12051202
/// within the constraint system.
12061203
struct CaseLabelItemInfo {
@@ -4236,7 +4233,7 @@ class ConstraintSystem {
42364233
/// corresponding opened type variables.
42374234
///
42384235
/// \returns The opened type, or \c type if there are no archetypes in it.
4239-
Type openType(Type type, OpenedTypeMap &replacements,
4236+
Type openType(Type type, ArrayRef<OpenedType> replacements,
42404237
ConstraintLocatorBuilder locator);
42414238

42424239
/// "Open" an opaque archetype type, similar to \c openType.
@@ -4247,7 +4244,7 @@ class ConstraintSystem {
42474244
/// opening its pattern and shape types and connecting them to the
42484245
/// aforementioned variable via special constraints.
42494246
Type openPackExpansionType(PackExpansionType *expansion,
4250-
OpenedTypeMap &replacements,
4247+
ArrayRef<OpenedType> replacements,
42514248
ConstraintLocatorBuilder locator);
42524249

42534250
/// Update OpenedPackExpansionTypes and record a change in the trail.
@@ -4280,28 +4277,26 @@ class ConstraintSystem {
42804277
/// \returns The opened type, or \c type if there are no archetypes in it.
42814278
FunctionType *openFunctionType(AnyFunctionType *funcType,
42824279
ConstraintLocatorBuilder locator,
4283-
OpenedTypeMap &replacements,
4280+
SmallVectorImpl<OpenedType> &replacements,
42844281
DeclContext *outerDC);
42854282

42864283
/// Open the generic parameter list and its requirements,
42874284
/// creating type variables for each of the type parameters.
42884285
void openGeneric(DeclContext *outerDC,
42894286
GenericSignature signature,
42904287
ConstraintLocatorBuilder locator,
4291-
OpenedTypeMap &replacements);
4288+
SmallVectorImpl<OpenedType> &replacements);
42924289

42934290
/// Open the generic parameter list creating type variables for each of the
42944291
/// type parameters.
42954292
void openGenericParameters(DeclContext *outerDC,
42964293
GenericSignature signature,
4297-
OpenedTypeMap &replacements,
4294+
SmallVectorImpl<OpenedType> &replacements,
42984295
ConstraintLocatorBuilder locator);
42994296

43004297
/// Open a generic parameter into a type variable and record
43014298
/// it in \c replacements.
4302-
TypeVariableType *openGenericParameter(DeclContext *outerDC,
4303-
GenericTypeParamType *parameter,
4304-
OpenedTypeMap &replacements,
4299+
TypeVariableType *openGenericParameter(GenericTypeParamType *parameter,
43054300
ConstraintLocatorBuilder locator);
43064301

43074302
/// Given generic signature open its generic requirements,
@@ -4328,7 +4323,7 @@ class ConstraintSystem {
43284323
/// Record the set of opened types for the given locator.
43294324
void recordOpenedTypes(
43304325
ConstraintLocatorBuilder locator,
4331-
const OpenedTypeMap &replacements,
4326+
SmallVectorImpl<OpenedType> &replacements,
43324327
bool fixmeAllowDuplicates=false);
43334328

43344329
/// Check whether the given type conforms to the given protocol and if
@@ -4340,7 +4335,7 @@ class ConstraintSystem {
43404335
FunctionType *adjustFunctionTypeForConcurrency(
43414336
FunctionType *fnType, Type baseType, ValueDecl *decl, DeclContext *dc,
43424337
unsigned numApplies, bool isMainDispatchQueue,
4343-
OpenedTypeMap &replacements, ConstraintLocatorBuilder locator);
4338+
ArrayRef<OpenedType> replacements, ConstraintLocatorBuilder locator);
43444339

43454340
/// Retrieve the type of a reference to the given value declaration.
43464341
///
@@ -4380,7 +4375,7 @@ class ConstraintSystem {
43804375
Type getMemberReferenceTypeFromOpenedType(
43814376
Type &openedType, Type baseObjTy, ValueDecl *value, DeclContext *outerDC,
43824377
ConstraintLocator *locator, bool hasAppliedSelf, bool isDynamicLookup,
4383-
OpenedTypeMap &replacements);
4378+
ArrayRef<OpenedType> replacements);
43844379

43854380
/// Retrieve the type of a reference to the given value declaration,
43864381
/// as a member with a base of the given type.
@@ -4396,7 +4391,7 @@ class ConstraintSystem {
43964391
DeclReferenceType getTypeOfMemberReference(
43974392
Type baseTy, ValueDecl *decl, DeclContext *useDC, bool isDynamicLookup,
43984393
FunctionRefKind functionRefKind, ConstraintLocator *locator,
4399-
OpenedTypeMap *replacements = nullptr);
4394+
SmallVectorImpl<OpenedType> *replacements = nullptr);
44004395

44014396
/// Retrieve a list of generic parameter types solver has "opened" (replaced
44024397
/// with a type variable) at the given location.

lib/Sema/CSApply.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ Solution::computeSubstitutions(NullablePtr<ValueDecl> decl,
103103
if (openedTypes == OpenedTypes.end())
104104
return SubstitutionMap();
105105

106-
TypeSubstitutionMap subs;
106+
SmallVector<Type, 4> replacementTypes;
107107
for (const auto &opened : openedTypes->second) {
108108
auto type = getFixedType(opened.second);
109109
if (opened.first->isParameterPack()) {
@@ -115,7 +115,7 @@ Solution::computeSubstitutions(NullablePtr<ValueDecl> decl,
115115
} else if (!type->is<PackType>())
116116
type = PackType::getSingletonPackExpansion(type);
117117
}
118-
subs[opened.first] = type;
118+
replacementTypes.push_back(type);
119119
}
120120

121121
auto lookupConformanceFn =
@@ -145,7 +145,7 @@ Solution::computeSubstitutions(NullablePtr<ValueDecl> decl,
145145
};
146146

147147
return SubstitutionMap::get(sig,
148-
QueryTypeSubstitutionMap{subs},
148+
replacementTypes,
149149
lookupConformanceFn);
150150
}
151151

lib/Sema/CSRanking.cpp

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -425,15 +425,18 @@ static bool isProtocolExtensionAsSpecializedAs(DeclContext *dc1,
425425
// Form a constraint system where we've opened up all of the requirements of
426426
// the second protocol extension.
427427
ConstraintSystem cs(dc1, std::nullopt);
428-
OpenedTypeMap replacements;
428+
SmallVector<OpenedType, 4> replacements;
429429
cs.openGeneric(dc2, sig2, ConstraintLocatorBuilder(nullptr), replacements);
430430

431431
// Bind the 'Self' type from the first extension to the type parameter from
432432
// opening 'Self' of the second extension.
433433
Type selfType1 = sig1.getGenericParams()[0];
434434
Type selfType2 = sig2.getGenericParams()[0];
435+
ASSERT(selfType1->isEqual(selfType2));
436+
ASSERT(replacements[0].first->isEqual(selfType2));
437+
435438
cs.addConstraint(ConstraintKind::Bind,
436-
replacements[cast<GenericTypeParamType>(selfType2->getCanonicalType())],
439+
replacements[0].second,
437440
dc1->mapTypeIntoContext(selfType1),
438441
nullptr);
439442

@@ -578,7 +581,7 @@ bool CompareDeclSpecializationRequest::evaluate(
578581

579582
auto openType = [&](ConstraintSystem &cs, DeclContext *innerDC,
580583
DeclContext *outerDC, Type type,
581-
OpenedTypeMap &replacements,
584+
SmallVectorImpl<OpenedType> &replacements,
582585
ConstraintLocator *locator) -> Type {
583586
if (auto *funcType = type->getAs<AnyFunctionType>()) {
584587
return cs.openFunctionType(funcType, locator, replacements, outerDC);
@@ -596,12 +599,11 @@ bool CompareDeclSpecializationRequest::evaluate(
596599
// FIXME: Locator when anchored on a declaration.
597600
// Get the type of a reference to the second declaration.
598601

599-
OpenedTypeMap unused, replacements;
600-
auto openedType2 = openType(cs, innerDC1, outerDC2, type2, unused, locator);
601-
auto openedType1 =
602-
openType(cs, innerDC2, outerDC1, type1, replacements, locator);
602+
SmallVector<OpenedType, 4> unused, replacements;
603+
auto openedType2 = openType(cs, innerDC2, outerDC2, type2, unused, locator);
604+
auto openedType1 = openType(cs, innerDC1, outerDC1, type1, replacements, locator);
603605

604-
for (const auto &replacement : replacements) {
606+
for (auto replacement : replacements) {
605607
if (auto mapped = innerDC1->mapTypeIntoContext(replacement.first)) {
606608
cs.addConstraint(ConstraintKind::Bind, replacement.second, mapped,
607609
locator);

lib/Sema/CSSimplify.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11534,10 +11534,9 @@ static Type getOpenedResultBuilderTypeFor(ConstraintSystem &cs,
1153411534
// Find the opened type for this callee and substitute in the type
1153511535
// parameters.
1153611536
auto substitutions = cs.getOpenedTypes(calleeLocator);
11537-
if (!substitutions.empty()) {
11538-
OpenedTypeMap replacements(substitutions.begin(), substitutions.end());
11539-
builderType = cs.openType(builderType, replacements, locator);
11540-
}
11537+
if (!substitutions.empty())
11538+
builderType = cs.openType(builderType, substitutions, locator);
11539+
1154111540
assert(!builderType->hasTypeParameter());
1154211541
}
1154311542
return builderType;

lib/Sema/TypeCheckConstraints.cpp

Lines changed: 29 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -573,7 +573,7 @@ Type TypeChecker::typeCheckParameterDefault(Expr *&defaultValue,
573573
// If both of aforementioned conditions are true, let's attempt
574574
// to open generic parameter and infer the type of this default
575575
// expression.
576-
OpenedTypeMap genericParameters;
576+
SmallVector<OpenedType, 4> genericParameters;
577577

578578
ConstraintSystemOptions options;
579579
options |= ConstraintSystemFlags::AllowFixes;
@@ -584,8 +584,13 @@ Type TypeChecker::typeCheckParameterDefault(Expr *&defaultValue,
584584
defaultValue, LocatorPathElt::ContextualType(
585585
defaultExprTarget.getExprContextualTypePurpose()));
586586

587-
auto getCanonicalGenericParamTy = [](GenericTypeParamType *GP) {
588-
return cast<GenericTypeParamType>(GP->getCanonicalType());
587+
auto findParam = [&](GenericTypeParamType *GP) -> TypeVariableType * {
588+
for (auto pair : genericParameters) {
589+
if (pair.first->isEqual(GP))
590+
return pair.second;
591+
}
592+
593+
return nullptr;
589594
};
590595

591596
// Find and open all of the generic parameters used by the parameter
@@ -594,29 +599,29 @@ Type TypeChecker::typeCheckParameterDefault(Expr *&defaultValue,
594599
assert(!type->is<UnboundGenericType>());
595600

596601
if (auto *GP = type->getAs<GenericTypeParamType>()) {
597-
auto openedVar = genericParameters.find(getCanonicalGenericParamTy(GP));
598-
if (openedVar != genericParameters.end()) {
599-
return openedVar->second;
600-
}
601-
return cs.openGenericParameter(DC->getParent(), GP, genericParameters,
602-
locator);
602+
if (auto *typeVar = findParam(GP))
603+
return typeVar;
604+
605+
auto *typeVar = cs.openGenericParameter(GP, locator);
606+
genericParameters.emplace_back(GP, typeVar);
607+
608+
return typeVar;
603609
}
604610
return std::nullopt;
605611
});
606612

607-
auto containsTypes = [&](Type type, OpenedTypeMap &toFind) {
608-
return type.findIf([&](Type nested) {
613+
auto containsTypes = [&](Type type) {
614+
return type.findIf([&](Type nested) -> bool {
609615
if (auto *GP = nested->getAs<GenericTypeParamType>())
610-
return toFind.count(getCanonicalGenericParamTy(GP)) > 0;
616+
return findParam(GP);
611617
return false;
612618
});
613619
};
614620

615-
auto containsGenericParamsExcluding = [&](Type type,
616-
OpenedTypeMap &exclusions) -> bool {
617-
return type.findIf([&](Type type) {
621+
auto containsGenericParamsExcluding = [&](Type type) -> bool {
622+
return type.findIf([&](Type type) -> bool {
618623
if (auto *GP = type->getAs<GenericTypeParamType>())
619-
return !exclusions.count(getCanonicalGenericParamTy(GP));
624+
return !findParam(GP);
620625
return false;
621626
});
622627
};
@@ -637,7 +642,7 @@ Type TypeChecker::typeCheckParameterDefault(Expr *&defaultValue,
637642
for (unsigned i : indices(anchorTy->getParams())) {
638643
const auto &param = anchorTy->getParams()[i];
639644

640-
if (containsTypes(param.getPlainType(), genericParameters))
645+
if (containsTypes(param.getPlainType()))
641646
affectedParams.push_back(i);
642647
}
643648

@@ -704,8 +709,8 @@ Type TypeChecker::typeCheckParameterDefault(Expr *&defaultValue,
704709
auto rhsTy = requirement.getSecondType();
705710

706711
// Unrelated requirement.
707-
if (!containsTypes(lhsTy, genericParameters) &&
708-
!containsTypes(rhsTy, genericParameters))
712+
if (!containsTypes(lhsTy) &&
713+
!containsTypes(rhsTy))
709714
continue;
710715

711716
// If both sides are dependent members, that's okay because types
@@ -716,8 +721,8 @@ Type TypeChecker::typeCheckParameterDefault(Expr *&defaultValue,
716721

717722
// Allow a subset of generic same-type requirements that only mention
718723
// "in scope" generic parameters e.g. `T.X == Int` or `T == U.Z`
719-
if (!containsGenericParamsExcluding(lhsTy, genericParameters) &&
720-
!containsGenericParamsExcluding(rhsTy, genericParameters)) {
724+
if (!containsGenericParamsExcluding(lhsTy) &&
725+
!containsGenericParamsExcluding(rhsTy)) {
721726
recordRequirement(reqIdx, requirement, requirementBaseLocator);
722727
continue;
723728
}
@@ -737,20 +742,20 @@ Type TypeChecker::typeCheckParameterDefault(Expr *&defaultValue,
737742
auto adheringTy = requirement.getFirstType();
738743

739744
// Unrelated requirement.
740-
if (!containsTypes(adheringTy, genericParameters))
745+
if (!containsTypes(adheringTy))
741746
continue;
742747

743748
// If adhering type has a mix or in- and out-of-scope parameters
744749
// mentioned we need to diagnose.
745-
if (containsGenericParamsExcluding(adheringTy, genericParameters)) {
750+
if (containsGenericParamsExcluding(adheringTy)) {
746751
diagnoseInvalidRequirement(requirement);
747752
return Type();
748753
}
749754

750755
if (requirement.getKind() == RequirementKind::Superclass) {
751756
auto superclassTy = requirement.getSecondType();
752757

753-
if (containsGenericParamsExcluding(superclassTy, genericParameters)) {
758+
if (containsGenericParamsExcluding(superclassTy)) {
754759
diagnoseInvalidRequirement(requirement);
755760
return Type();
756761
}

lib/Sema/TypeCheckProtocol.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1197,7 +1197,7 @@ swift::matchWitness(WitnessChecker::RequirementEnvironmentCache &reqEnvCache,
11971197
// Open up the type of the requirement.
11981198
reqLocator =
11991199
cs->getConstraintLocator(req, ConstraintLocator::ProtocolRequirement);
1200-
OpenedTypeMap reqReplacements;
1200+
SmallVector<OpenedType, 4> reqReplacements;
12011201
reqType = cs->getTypeOfMemberReference(selfTy, req, dc,
12021202
/*isDynamicResult=*/false,
12031203
FunctionRefKind::DoubleApply,

0 commit comments

Comments
 (0)