Skip to content

Commit 8271c1a

Browse files
authored
Merge pull request #5626 from DougGregor/dependent-type-variables
[Type checker] Use DependentMemberType instead of type variables for nested types.
2 parents 7d241ed + 4cadee4 commit 8271c1a

21 files changed

+366
-424
lines changed

include/swift/AST/ASTContext.h

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -121,11 +121,6 @@ enum class KnownFoundationEntity {
121121
/// entity name.
122122
Optional<KnownFoundationEntity> getKnownFoundationEntity(StringRef name);
123123

124-
/// Callback function used when referring to a type member of a given
125-
/// type variable.
126-
typedef std::function<Type(TypeVariableType *, AssociatedTypeDecl *)>
127-
GetTypeVariableMemberCallback;
128-
129124
/// \brief Introduces a new constraint checker arena, whose lifetime is
130125
/// tied to the lifetime of this RAII object.
131126
class ConstraintCheckerArenaRAII {
@@ -142,8 +137,7 @@ class ConstraintCheckerArenaRAII {
142137
/// \param allocator The allocator used for allocating any data that
143138
/// goes into the constraint checker arena.
144139
ConstraintCheckerArenaRAII(ASTContext &self,
145-
llvm::BumpPtrAllocator &allocator,
146-
GetTypeVariableMemberCallback getTypeMember);
140+
llvm::BumpPtrAllocator &allocator);
147141

148142
ConstraintCheckerArenaRAII(const ConstraintCheckerArenaRAII &) = delete;
149143
ConstraintCheckerArenaRAII(ConstraintCheckerArenaRAII &&) = delete;
@@ -519,13 +513,6 @@ class ASTContext {
519513
const CanType TheIEEE128Type; /// 128-bit IEEE floating point
520514
const CanType ThePPC128Type; /// 128-bit PowerPC 2xDouble
521515

522-
/// Retrieve a type member of the given base type variable.
523-
///
524-
/// Note that this routine is only usable when a constraint system
525-
/// is active.
526-
Type getTypeVariableMemberType(TypeVariableType *baseTypeVar,
527-
AssociatedTypeDecl *assocType);
528-
529516
/// Adds a search path to SearchPathOpts, unless it is already present.
530517
///
531518
/// Does any proper bookkeeping to keep all module loaders up to date as well.

lib/AST/ASTContext.cpp

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -330,12 +330,8 @@ struct ASTContext::Implementation {
330330
/// The allocator used for all allocations within this arena.
331331
llvm::BumpPtrAllocator &Allocator;
332332

333-
/// Callback used to get a type member of a type variable.
334-
GetTypeVariableMemberCallback GetTypeMember;
335-
336-
ConstraintSolverArena(llvm::BumpPtrAllocator &allocator,
337-
GetTypeVariableMemberCallback &&getTypeMember)
338-
: Allocator(allocator), GetTypeMember(std::move(getTypeMember)) { }
333+
ConstraintSolverArena(llvm::BumpPtrAllocator &allocator)
334+
: Allocator(allocator) { }
339335

340336
ConstraintSolverArena(const ConstraintSolverArena &) = delete;
341337
ConstraintSolverArena(ConstraintSolverArena &&) = delete;
@@ -369,14 +365,11 @@ ASTContext::Implementation::~Implementation() {
369365
}
370366

371367
ConstraintCheckerArenaRAII::
372-
ConstraintCheckerArenaRAII(ASTContext &self, llvm::BumpPtrAllocator &allocator,
373-
GetTypeVariableMemberCallback getTypeMember)
368+
ConstraintCheckerArenaRAII(ASTContext &self, llvm::BumpPtrAllocator &allocator)
374369
: Self(self), Data(self.Impl.CurrentConstraintSolverArena.release())
375370
{
376371
Self.Impl.CurrentConstraintSolverArena.reset(
377-
new ASTContext::Implementation::ConstraintSolverArena(
378-
allocator,
379-
std::move(getTypeMember)));
372+
new ASTContext::Implementation::ConstraintSolverArena(allocator));
380373
}
381374

382375
ConstraintCheckerArenaRAII::~ConstraintCheckerArenaRAII() {
@@ -1164,12 +1157,6 @@ void ASTContext::setSubstitutions(TypeBase* type,
11641157
boundGenericSubstitutions[{type, gpContext}] = Subs;
11651158
}
11661159

1167-
Type ASTContext::getTypeVariableMemberType(TypeVariableType *baseTypeVar,
1168-
AssociatedTypeDecl *assocType) {
1169-
auto &arena = *Impl.CurrentConstraintSolverArena;
1170-
return arena.GetTypeMember(baseTypeVar, assocType);
1171-
}
1172-
11731160
void ASTContext::addSearchPath(StringRef searchPath, bool isFramework) {
11741161
OptionSet<SearchPathKind> &loaded = Impl.SearchPathsSet[searchPath];
11751162
auto kind = isFramework ? SearchPathKind::Framework : SearchPathKind::Import;
@@ -1386,6 +1373,15 @@ ASTContext::getBehaviorConformance(Type conformingType,
13861373
auto conformance = new (*this, AllocationArena::Permanent)
13871374
NormalProtocolConformance(conformingType, conformingInterfaceType,
13881375
protocol, loc, storage, state);
1376+
1377+
if (auto nominal = conformingInterfaceType->getAnyNominal()) {
1378+
// Note: this is an egregious hack. The conformances need to be associated
1379+
// with the actual storage declarations.
1380+
SmallVector<ProtocolConformance *, 2> conformances;
1381+
if (!nominal->lookupConformance(nominal->getModuleContext(), protocol,
1382+
conformances))
1383+
nominal->registerProtocolConformance(conformance);
1384+
}
13891385
return conformance;
13901386
}
13911387

lib/AST/Module.cpp

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -586,28 +586,24 @@ TypeBase::gatherAllSubstitutions(Module *module,
586586
// The type itself contains substitutions up to the innermost
587587
// non-type context.
588588
CanType parent(canon);
589-
auto *parentDC = gpContext;
589+
ArrayRef<GenericTypeParamType *> genericParams =
590+
genericSig->getGenericParams();
591+
unsigned lastGenericIndex = genericParams.size();
590592
while (parent) {
591593
if (auto boundGeneric = dyn_cast<BoundGenericType>(parent)) {
592-
auto genericSig = parentDC->getGenericSignatureOfContext();
593-
unsigned index = 0;
594-
595-
assert(boundGeneric->getGenericArgs().size() ==
596-
genericSig->getInnermostGenericParams().size());
597-
594+
unsigned index = lastGenericIndex - boundGeneric->getGenericArgs().size();
598595
for (Type arg : boundGeneric->getGenericArgs()) {
599-
auto paramTy = genericSig->getInnermostGenericParams()[index++];
596+
auto paramTy = genericParams[index++];
600597
substitutions[paramTy->getCanonicalType().getPointer()] = arg;
601598
}
599+
lastGenericIndex -= boundGeneric->getGenericArgs().size();
602600

603601
parent = CanType(boundGeneric->getParent());
604-
parentDC = parentDC->getParent();
605602
continue;
606603
}
607604

608605
if (auto nominal = dyn_cast<NominalType>(parent)) {
609606
parent = CanType(nominal->getParent());
610-
parentDC = parentDC->getParent();
611607
continue;
612608
}
613609

@@ -616,6 +612,9 @@ TypeBase::gatherAllSubstitutions(Module *module,
616612

617613
// Add forwarding substitutions from the outer context if we have
618614
// a type nested inside a generic function.
615+
auto *parentDC = gpContext;
616+
while (parentDC->isTypeContext())
617+
parentDC = parentDC->getParent();
619618
if (auto *outerEnv = parentDC->getGenericEnvironmentOfContext())
620619
for (auto pair : outerEnv->getInterfaceToArchetypeMap()) {
621620
auto result = substitutions.insert(pair);

lib/AST/Type.cpp

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -521,7 +521,13 @@ class GetRValueTypeVisitor : public TypeVisitor<GetRValueTypeVisitor, Type> {
521521
Type visitParenType(ParenType *pt) {
522522
return ParenType::get(pt->getASTContext(), visit(pt->getUnderlyingType()));
523523
}
524-
524+
525+
Type visitSubstitutedType(SubstitutedType *st) {
526+
return SubstitutedType::get(st->getOriginal(),
527+
visit(st->getReplacementType()),
528+
st->getASTContext());
529+
}
530+
525531
Type visitType(TypeBase *t) {
526532
// Other types should not structurally contain lvalues.
527533
assert(!t->isLValueType()
@@ -2774,13 +2780,10 @@ static Type getMemberForBaseType(ConformanceSource conformances,
27742780
return getDependentMemberType(ErrorType::get(substBase));
27752781
}
27762782

2777-
// If the parent is a type variable, retrieve its member type
2778-
// variable.
2779-
if (auto typeVarParent = substBase->getAs<TypeVariableType>()) {
2780-
assert(assocType && "Missing associated type");
2781-
return substBase->getASTContext().getTypeVariableMemberType(typeVarParent,
2782-
assocType);
2783-
}
2783+
// If the parent is a type variable or a member rooted in a type variable,
2784+
// we're done.
2785+
if (substBase->isTypeVariableOrMember())
2786+
return getDependentMemberType(substBase);
27842787

27852788
// Retrieve the member type with the given name.
27862789

lib/Sema/CSGen.cpp

Lines changed: 6 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1690,17 +1690,11 @@ namespace {
16901690
locator);
16911691

16921692
// Its subexpression should be convertible to a tuple (T.Element...).
1693-
// FIXME: We should really go through the conformance above to extract
1694-
// the element type, rather than just looking for the element type.
1695-
// FIXME: Member constraint is still weird here.
1696-
ConstraintLocatorBuilder builder(locator);
1697-
auto arrayElementTy = CS.getMemberType(arrayTy, elementAssocTy,
1698-
builder.withPathElement(
1699-
ConstraintLocator::Member),
1700-
/*options=*/0);
1693+
Type arrayElementTy = DependentMemberType::get(arrayTy, elementAssocTy);
17011694

17021695
// Introduce conversions from each element to the element type of the
17031696
// array.
1697+
ConstraintLocatorBuilder builder(locator);
17041698
unsigned index = 0;
17051699
for (auto element : expr->getElements()) {
17061700
CS.addConstraint(ConstraintKind::Conversion,
@@ -1758,18 +1752,10 @@ namespace {
17581752

17591753
// Its subexpression should be convertible to a tuple ((T.Key,T.Value)...).
17601754
ConstraintLocatorBuilder locatorBuilder(locator);
1761-
auto dictionaryKeyTy = CS.getMemberType(dictionaryTy,
1762-
keyAssocTy,
1763-
locatorBuilder.withPathElement(
1764-
ConstraintLocator::Member),
1765-
/*options=*/0);
1766-
/// FIXME: ArrayElementType is a total hack here.
1767-
auto dictionaryValueTy = CS.getMemberType(dictionaryTy,
1768-
valueAssocTy,
1769-
locatorBuilder.withPathElement(
1770-
ConstraintLocator::ArrayElementType),
1771-
/*options=*/0);
1772-
1755+
auto dictionaryKeyTy = DependentMemberType::get(dictionaryTy,
1756+
keyAssocTy);
1757+
auto dictionaryValueTy = DependentMemberType::get(dictionaryTy,
1758+
valueAssocTy);
17731759
TupleTypeElt tupleElts[2] = { TupleTypeElt(dictionaryKeyTy),
17741760
TupleTypeElt(dictionaryValueTy) };
17751761
Type elementTy = TupleType::get(tupleElts, C);

lib/Sema/CSSimplify.cpp

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1438,8 +1438,11 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
14381438
}
14391439
}
14401440

1441+
bool isTypeVarOrMember1 = desugar1->isTypeVariableOrMember();
1442+
bool isTypeVarOrMember2 = desugar2->isTypeVariableOrMember();
1443+
14411444
llvm::SmallVector<RestrictionOrFix, 4> conversionsOrFixes;
1442-
bool concrete = !typeVar1 && !typeVar2;
1445+
bool concrete = !isTypeVarOrMember1 && !isTypeVarOrMember2;
14431446

14441447
// If this is an argument conversion, handle it directly. The rules are
14451448
// different from normal conversions.
@@ -1482,9 +1485,12 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
14821485
return SolutionKind::Error;
14831486

14841487
case TypeKind::GenericTypeParam:
1485-
case TypeKind::DependentMember:
14861488
llvm_unreachable("unmapped dependent type in type checker");
14871489

1490+
case TypeKind::DependentMember:
1491+
// Nothing we can solve.
1492+
return formUnsolvedResult();
1493+
14881494
case TypeKind::TypeVariable:
14891495
case TypeKind::Archetype:
14901496
// Nothing to do here; handle type variables and archetypes below.
@@ -2077,7 +2083,7 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
20772083

20782084
// If we should attempt fixes, add those to the list. They'll only be visited
20792085
// if there are no other possible solutions.
2080-
if (shouldAttemptFixes() && !typeVar1 && !typeVar2 &&
2086+
if (shouldAttemptFixes() && !isTypeVarOrMember1 && !isTypeVarOrMember2 &&
20812087
!flags.contains(TMF_ApplyingFix) && kind >= ConstraintKind::Conversion) {
20822088
Type objectType1 = type1->getRValueObjectType();
20832089

@@ -2136,8 +2142,10 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
21362142
}
21372143

21382144
if (conversionsOrFixes.empty()) {
2139-
// If one of the types is a type variable, we leave this unsolved.
2140-
if (typeVar1 || typeVar2) return formUnsolvedResult();
2145+
// If one of the types is a type variable or member thereof, we leave this
2146+
// unsolved.
2147+
if (isTypeVarOrMember1 || isTypeVarOrMember2)
2148+
return formUnsolvedResult();
21412149

21422150
return SolutionKind::Error;
21432151
}
@@ -2200,6 +2208,7 @@ ConstraintSystem::SolutionKind
22002208
ConstraintSystem::simplifyConstructionConstraint(
22012209
Type valueType, FunctionType *fnType, TypeMatchOptions flags,
22022210
FunctionRefKind functionRefKind, ConstraintLocator *locator) {
2211+
22032212
// Desugar the value type.
22042213
auto desugarValueType = valueType->getDesugaredType();
22052214

@@ -2223,10 +2232,10 @@ ConstraintSystem::simplifyConstructionConstraint(
22232232

22242233
case TypeKind::GenericFunction:
22252234
case TypeKind::GenericTypeParam:
2226-
case TypeKind::DependentMember:
22272235
llvm_unreachable("unmapped dependent type");
22282236

22292237
case TypeKind::TypeVariable:
2238+
case TypeKind::DependentMember:
22302239
return SolutionKind::Unsolved;
22312240

22322241
case TypeKind::Tuple: {

0 commit comments

Comments
 (0)