Skip to content

Commit 819dfd5

Browse files
committed
Sema: Better type safety for opened types map
Now that we no longer map dependent member types to fresh type variables, the keys in the replacement map can just be GenericTypeParamTypes.
1 parent ed4c681 commit 819dfd5

File tree

5 files changed

+47
-51
lines changed

5 files changed

+47
-51
lines changed

lib/Sema/CSRanking.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -442,7 +442,7 @@ static bool isProtocolExtensionAsSpecializedAs(TypeChecker &tc,
442442
// Form a constraint system where we've opened up all of the requirements of
443443
// the second protocol extension.
444444
ConstraintSystem cs(tc, dc1, None);
445-
llvm::DenseMap<CanType, TypeVariableType *> replacements;
445+
OpenedTypeMap replacements;
446446
cs.openGeneric(dc2, dc2, sig2,
447447
/*skipProtocolSelfConstraint=*/false,
448448
ConstraintLocatorBuilder(nullptr),
@@ -453,7 +453,7 @@ static bool isProtocolExtensionAsSpecializedAs(TypeChecker &tc,
453453
Type selfType1 = sig1->getGenericParams()[0];
454454
Type selfType2 = sig2->getGenericParams()[0];
455455
cs.addConstraint(ConstraintKind::Bind,
456-
replacements[selfType2->getCanonicalType()],
456+
replacements[cast<GenericTypeParamType>(selfType2->getCanonicalType())],
457457
dc1->mapTypeIntoContext(selfType1),
458458
nullptr);
459459

@@ -568,7 +568,7 @@ static bool isDeclAsSpecializedAs(TypeChecker &tc, DeclContext *dc,
568568
auto locator = cs.getConstraintLocator(nullptr);
569569
// FIXME: Locator when anchored on a declaration.
570570
// Get the type of a reference to the second declaration.
571-
llvm::DenseMap<CanType, TypeVariableType *> unused;
571+
OpenedTypeMap unused;
572572
Type openedType2;
573573
if (auto *funcType = type2->getAs<AnyFunctionType>()) {
574574
openedType2 = cs.openFunctionType(
@@ -583,7 +583,7 @@ static bool isDeclAsSpecializedAs(TypeChecker &tc, DeclContext *dc,
583583

584584
// Get the type of a reference to the first declaration, swapping in
585585
// archetypes for the dependent types.
586-
llvm::DenseMap<CanType, TypeVariableType *> replacements;
586+
OpenedTypeMap replacements;
587587
auto dc1 = decl1->getInnermostDeclContext();
588588
Type openedType1;
589589
if (auto *funcType = type1->getAs<AnyFunctionType>()) {

lib/Sema/ConstraintSystem.cpp

Lines changed: 25 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -355,14 +355,13 @@ namespace {
355355
class ReplaceDependentTypes {
356356
ConstraintSystem &cs;
357357
ConstraintLocatorBuilder &locator;
358-
llvm::DenseMap<CanType, TypeVariableType *> &replacements;
359-
llvm::DenseMap<CanType, Type> dependentMemberReplacements;
358+
OpenedTypeMap &replacements;
360359

361360
public:
362361
ReplaceDependentTypes(
363362
ConstraintSystem &cs,
364363
ConstraintLocatorBuilder &locator,
365-
llvm::DenseMap<CanType, TypeVariableType *> &replacements)
364+
OpenedTypeMap &replacements)
366365
: cs(cs), locator(locator), replacements(replacements) { }
367366

368367
Type operator()(Type type) {
@@ -371,7 +370,8 @@ namespace {
371370

372371
// Replace a generic type parameter with its corresponding type variable.
373372
if (auto genericParam = type->getAs<GenericTypeParamType>()) {
374-
auto known = replacements.find(genericParam->getCanonicalType());
373+
auto known = replacements.find(
374+
cast<GenericTypeParamType>(genericParam->getCanonicalType()));
375375

376376
if (known == replacements.end())
377377
return cs.createTypeVariable(nullptr, TVO_PrefersSubtypeBinding);
@@ -382,21 +382,11 @@ namespace {
382382
// Replace a dependent member with a fresh type variable and make it a
383383
// member of its base type.
384384
if (auto dependentMember = type->getAs<DependentMemberType>()) {
385-
// Check whether we've already dealt with this dependent member.
386-
auto known = dependentMemberReplacements.find(
387-
dependentMember->getCanonicalType());
388-
if (known != dependentMemberReplacements.end())
389-
return known->second;
390-
391-
// Replace archetypes in the base type.
392-
// FIXME: Tracking the dependent members seems unnecessary.
385+
// Replace type parameters in the base type.
393386
if (auto base =
394387
((*this)(dependentMember->getBase()))->getAs<TypeVariableType>()) {
395-
auto result =
388+
return
396389
DependentMemberType::get(base, dependentMember->getAssocType());
397-
dependentMemberReplacements[dependentMember->getCanonicalType()] =
398-
result;
399-
return result;
400390
}
401391
}
402392

@@ -421,7 +411,7 @@ namespace {
421411
return ErrorType::get(type);
422412
}
423413

424-
llvm::DenseMap<CanType, TypeVariableType *> unboundReplacements;
414+
OpenedTypeMap unboundReplacements;
425415

426416
// Open up the generic type.
427417
cs.openGeneric(unboundDecl->getInnermostDeclContext(),
@@ -435,7 +425,8 @@ namespace {
435425
// Map the generic parameters to their corresponding type variables.
436426
llvm::SmallVector<TypeLoc, 4> arguments;
437427
for (auto gp : unboundDecl->getInnermostGenericParamTypes()) {
438-
auto found = unboundReplacements.find(gp->getCanonicalType());
428+
auto found = unboundReplacements.find(
429+
cast<GenericTypeParamType>(gp->getCanonicalType()));
439430
assert(found != unboundReplacements.end() &&
440431
"Missing generic parameter?");
441432
arguments.push_back(TypeLoc::withoutLoc(found->second));
@@ -461,7 +452,7 @@ namespace {
461452
Type ConstraintSystem::openType(
462453
Type startingType,
463454
ConstraintLocatorBuilder locator,
464-
llvm::DenseMap<CanType, TypeVariableType *> &replacements) {
455+
OpenedTypeMap &replacements) {
465456
if (!startingType->hasTypeParameter() &&
466457
!startingType->hasUnboundGenericType())
467458
return startingType;
@@ -498,7 +489,7 @@ Type ConstraintSystem::openFunctionType(
498489
AnyFunctionType *funcType,
499490
unsigned numArgumentLabelsToRemove,
500491
ConstraintLocatorBuilder locator,
501-
llvm::DenseMap<CanType, TypeVariableType *> &replacements,
492+
OpenedTypeMap &replacements,
502493
DeclContext *innerDC,
503494
DeclContext *outerDC,
504495
bool skipProtocolSelfConstraint) {
@@ -645,7 +636,7 @@ Type ConstraintSystem::getFixedTypeRecursive(Type type,
645636

646637
void ConstraintSystem::recordOpenedTypes(
647638
ConstraintLocatorBuilder locator,
648-
const llvm::DenseMap<CanType, TypeVariableType *> &replacements) {
639+
const OpenedTypeMap &replacements) {
649640
if (replacements.empty())
650641
return;
651642

@@ -720,7 +711,7 @@ ConstraintSystem::getTypeOfReference(ValueDecl *value,
720711
FunctionRefKind functionRefKind,
721712
ConstraintLocatorBuilder locator,
722713
const DeclRefExpr *base) {
723-
llvm::DenseMap<CanType, TypeVariableType *> replacements;
714+
OpenedTypeMap replacements;
724715

725716
if (value->getDeclContext()->isTypeContext() && isa<FuncDecl>(value)) {
726717
// Unqualified lookup can find operator names within nominal types.
@@ -829,7 +820,7 @@ void ConstraintSystem::openGeneric(
829820
GenericSignature *signature,
830821
bool skipProtocolSelfConstraint,
831822
ConstraintLocatorBuilder locator,
832-
llvm::DenseMap<CanType, TypeVariableType *> &replacements) {
823+
OpenedTypeMap &replacements) {
833824
openGeneric(innerDC,
834825
outerDC,
835826
signature->getGenericParams(),
@@ -874,7 +865,7 @@ static void bindArchetypesFromContext(
874865
ConstraintSystem &cs,
875866
DeclContext *outerDC,
876867
ConstraintLocator *locatorPtr,
877-
const llvm::DenseMap<CanType, TypeVariableType *> &replacements) {
868+
const OpenedTypeMap &replacements) {
878869

879870
auto *genericEnv = outerDC->getGenericEnvironmentOfContext();
880871

@@ -891,7 +882,8 @@ static void bindArchetypesFromContext(
891882
break;
892883

893884
for (auto *paramTy : genericSig->getGenericParams()) {
894-
auto found = replacements.find(paramTy->getCanonicalType());
885+
auto found = replacements.find(cast<GenericTypeParamType>(
886+
paramTy->getCanonicalType()));
895887

896888
// We might not have a type variable for this generic parameter
897889
// because either we're opening up an UnboundGenericType,
@@ -917,7 +909,7 @@ void ConstraintSystem::openGeneric(
917909
ArrayRef<Requirement> requirements,
918910
bool skipProtocolSelfConstraint,
919911
ConstraintLocatorBuilder locator,
920-
llvm::DenseMap<CanType, TypeVariableType *> &replacements) {
912+
OpenedTypeMap &replacements) {
921913
auto locatorPtr = getConstraintLocator(locator);
922914
auto *genericEnv = innerDC->getGenericEnvironmentOfContext();
923915

@@ -932,7 +924,8 @@ void ConstraintSystem::openGeneric(
932924
TVO_PrefersSubtypeBinding |
933925
TVO_MustBeMaterializable);
934926
auto result = replacements.insert(
935-
std::make_pair(gp->getCanonicalType(), typeVar));
927+
std::make_pair(cast<GenericTypeParamType>(gp->getCanonicalType()),
928+
typeVar));
936929
assert(result.second);
937930
(void) result;
938931
}
@@ -1033,7 +1026,7 @@ ConstraintSystem::getTypeOfMemberReference(
10331026
FunctionRefKind functionRefKind,
10341027
ConstraintLocatorBuilder locator,
10351028
const DeclRefExpr *base,
1036-
llvm::DenseMap<CanType, TypeVariableType *> *replacementsPtr) {
1029+
OpenedTypeMap *replacementsPtr) {
10371030
// Figure out the instance type used for the base.
10381031
Type baseObjTy = getFixedTypeRecursive(baseTy, /*wantRValue=*/true);
10391032
bool isInstance = true;
@@ -1077,7 +1070,7 @@ ConstraintSystem::getTypeOfMemberReference(
10771070

10781071
// Open the type of the generic function or member of a generic type.
10791072
Type openedType;
1080-
llvm::DenseMap<CanType, TypeVariableType *> localReplacements;
1073+
OpenedTypeMap localReplacements;
10811074
auto &replacements = replacementsPtr ? *replacementsPtr : localReplacements;
10821075
bool isCurriedInstanceReference = value->isInstanceMember() && !isInstance;
10831076
unsigned numRemovedArgumentLabels =
@@ -1225,8 +1218,9 @@ ConstraintSystem::getTypeOfMemberReference(
12251218
// parameter with the existential type, since formally the access will
12261219
// operate on existentials and not type parameters.
12271220
if (!isDynamicResult && baseObjTy->isExistentialType()) {
1228-
auto selfTy = replacements[outerDC->getSelfInterfaceType()
1229-
->getCanonicalType()];
1221+
auto selfTy = replacements[
1222+
cast<GenericTypeParamType>(outerDC->getSelfInterfaceType()
1223+
->getCanonicalType())];
12301224
type = type.transform([&](Type t) -> Type {
12311225
if (auto *selfTy = t->getAs<DynamicSelfType>())
12321226
t = selfTy->getSelfType();

lib/Sema/ConstraintSystem.h

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -494,7 +494,9 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &out, const Score &score);
494494

495495
/// Describes a dependent type that has been opened to a particular type
496496
/// variable.
497-
typedef std::pair<CanType, TypeVariableType *> OpenedType;
497+
typedef std::pair<GenericTypeParamType *, TypeVariableType *> OpenedType;
498+
499+
typedef llvm::DenseMap<GenericTypeParamType *, TypeVariableType *> OpenedTypeMap;
498500

499501
/// \brief A complete solution to a constraint system.
500502
///
@@ -1874,7 +1876,7 @@ class ConstraintSystem {
18741876
///
18751877
/// \returns The opened type.
18761878
Type openType(Type type, ConstraintLocatorBuilder locator) {
1877-
llvm::DenseMap<CanType, TypeVariableType *> replacements;
1879+
OpenedTypeMap replacements;
18781880
return openType(type, locator, replacements);
18791881
}
18801882

@@ -1889,7 +1891,7 @@ class ConstraintSystem {
18891891
/// \returns The opened type, or \c type if there are no archetypes in it.
18901892
Type openType(Type type,
18911893
ConstraintLocatorBuilder locator,
1892-
llvm::DenseMap<CanType, TypeVariableType *> &replacements);
1894+
OpenedTypeMap &replacements);
18931895

18941896
/// \brief "Open" the given function type.
18951897
///
@@ -1914,7 +1916,7 @@ class ConstraintSystem {
19141916
AnyFunctionType *funcType,
19151917
unsigned numArgumentLabelsToRemove,
19161918
ConstraintLocatorBuilder locator,
1917-
llvm::DenseMap<CanType, TypeVariableType *> &replacements,
1919+
OpenedTypeMap &replacements,
19181920
DeclContext *innerDC,
19191921
DeclContext *outerDC,
19201922
bool skipProtocolSelfConstraint);
@@ -1938,19 +1940,19 @@ class ConstraintSystem {
19381940
GenericSignature *signature,
19391941
bool skipProtocolSelfConstraint,
19401942
ConstraintLocatorBuilder locator,
1941-
llvm::DenseMap<CanType, TypeVariableType *> &replacements);
1943+
OpenedTypeMap &replacements);
19421944
void openGeneric(DeclContext *innerDC,
19431945
DeclContext *outerDC,
19441946
ArrayRef<GenericTypeParamType *> params,
19451947
ArrayRef<Requirement> requirements,
19461948
bool skipProtocolSelfConstraint,
19471949
ConstraintLocatorBuilder locator,
1948-
llvm::DenseMap<CanType, TypeVariableType *> &replacements);
1950+
OpenedTypeMap &replacements);
19491951

19501952
/// Record the set of opened types for the given locator.
19511953
void recordOpenedTypes(
19521954
ConstraintLocatorBuilder locator,
1953-
const llvm::DenseMap<CanType, TypeVariableType *> &replacements);
1955+
const OpenedTypeMap &replacements);
19541956

19551957
/// \brief Retrieve the type of a reference to the given value declaration.
19561958
///
@@ -1997,8 +1999,7 @@ class ConstraintSystem {
19971999
FunctionRefKind functionRefKind,
19982000
ConstraintLocatorBuilder locator,
19992001
const DeclRefExpr *base = nullptr,
2000-
llvm::DenseMap<CanType, TypeVariableType *>
2001-
*replacements = nullptr);
2002+
OpenedTypeMap *replacements = nullptr);
20022003

20032004
/// \brief Add a new overload set to the list of unresolved overload
20042005
/// sets.

lib/Sema/TypeCheckConstraints.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2694,7 +2694,7 @@ void Solution::dump(raw_ostream &out) const {
26942694
out << " opens ";
26952695
interleave(opened.second.begin(), opened.second.end(),
26962696
[&](OpenedType opened) {
2697-
opened.first.print(out);
2697+
opened.first->print(out);
26982698
out << " -> ";
26992699
opened.second->print(out);
27002700
},
@@ -2852,7 +2852,7 @@ void ConstraintSystem::print(raw_ostream &out) {
28522852
out << " opens ";
28532853
interleave(opened.second.begin(), opened.second.end(),
28542854
[&](OpenedType opened) {
2855-
opened.first.print(out);
2855+
opened.first->print(out);
28562856
out << " -> ";
28572857
opened.second->print(out);
28582858
},

lib/Sema/TypeCheckProtocol.cpp

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1193,7 +1193,7 @@ matchWitness(TypeChecker &tc,
11931193
reqLocator = cs->getConstraintLocator(
11941194
static_cast<Expr *>(nullptr),
11951195
LocatorPathElt(ConstraintLocator::Requirement, req));
1196-
llvm::DenseMap<CanType, TypeVariableType *> reqReplacements;
1196+
OpenedTypeMap reqReplacements;
11971197
std::tie(openedFullReqType, reqType)
11981198
= cs->getTypeOfMemberReference(selfTy, req, dc,
11991199
/*isTypeReference=*/false,
@@ -1207,7 +1207,7 @@ matchWitness(TypeChecker &tc,
12071207
// For any type parameters we replaced in the witness, map them
12081208
// to the corresponding archetypes in the witness's context.
12091209
for (const auto &replacement : reqReplacements) {
1210-
auto replacedInReq = replacement.first.subst(reqSubMap);
1210+
auto replacedInReq = Type(replacement.first).subst(reqSubMap);
12111211

12121212
// If substitution failed, skip the requirement. This only occurs in
12131213
// invalid code.
@@ -1229,7 +1229,7 @@ matchWitness(TypeChecker &tc,
12291229
witnessLocator = cs->getConstraintLocator(
12301230
static_cast<Expr *>(nullptr),
12311231
LocatorPathElt(ConstraintLocator::Witness, witness));
1232-
llvm::DenseMap<CanType, TypeVariableType *> witnessReplacements;
1232+
OpenedTypeMap witnessReplacements;
12331233
if (witness->getDeclContext()->isTypeContext()) {
12341234
std::tie(openedFullWitnessType, openWitnessType)
12351235
= cs->getTypeOfMemberReference(selfTy, witness, dc,
@@ -6318,7 +6318,7 @@ bool TypeChecker::isProtocolExtensionUsable(DeclContext *dc, Type type,
63186318
// Set up a constraint system where we open the generic parameters of the
63196319
// protocol extension.
63206320
ConstraintSystem cs(*this, dc, None);
6321-
llvm::DenseMap<CanType, TypeVariableType *> replacements;
6321+
OpenedTypeMap replacements;
63226322
auto genericSig = protocolExtension->getGenericSignature();
63236323

63246324
cs.openGeneric(protocolExtension, protocolExtension,
@@ -6327,7 +6327,8 @@ bool TypeChecker::isProtocolExtensionUsable(DeclContext *dc, Type type,
63276327
ConstraintLocatorBuilder(nullptr), replacements);
63286328

63296329
// Bind the 'Self' type variable to the provided type.
6330-
CanType selfType = genericSig->getGenericParams().back()->getCanonicalType();
6330+
auto selfType = cast<GenericTypeParamType>(
6331+
genericSig->getGenericParams().back()->getCanonicalType());
63316332
auto selfTypeVar = replacements[selfType];
63326333
cs.addConstraint(ConstraintKind::Bind, selfTypeVar, type, nullptr);
63336334

0 commit comments

Comments
 (0)