Skip to content

Commit 0d72b81

Browse files
committed
AST: Switch BoundGenericType nodes to storing a substition map
1 parent c777bc0 commit 0d72b81

File tree

14 files changed

+146
-162
lines changed

14 files changed

+146
-162
lines changed

include/swift/AST/Types.h

Lines changed: 30 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -403,13 +403,6 @@ class alignas(1 << TypeAlignInBits) TypeBase {
403403
Count : 32
404404
);
405405

406-
SWIFT_INLINE_BITFIELD_FULL(BoundGenericType, TypeBase, 32,
407-
: NumPadBits,
408-
409-
/// The number of generic arguments.
410-
GenericArgCount : 32
411-
);
412-
413406
SWIFT_INLINE_BITFIELD_FULL(TypeAliasType, SugarType, 1+1,
414407
: NumPadBits,
415408

@@ -2205,33 +2198,37 @@ typedef ArrayRefView<Type,CanType,getAsCanType> CanTypeArrayRef;
22052198
/// given type arguments.
22062199
class BoundGenericType : public NominalOrBoundGenericNominalType,
22072200
public llvm::FoldingSetNode {
2208-
2209-
/// Retrieve the intrusive pointer storage from the subtype
2210-
const Type *getTrailingObjectsPointer() const;
2211-
Type *getTrailingObjectsPointer() {
2212-
const BoundGenericType *temp = this;
2213-
return const_cast<Type *>(temp->getTrailingObjectsPointer());
2214-
}
2201+
const SubstitutionMap Substitutions;
22152202

22162203
protected:
22172204
BoundGenericType(TypeKind K, NominalTypeDecl *TheDecl, Type Parent,
2218-
ArrayRef<Type> GenericArgs, const ASTContext *C,
2219-
RecursiveTypeProperties Properties);
2205+
SubstitutionMap Substitutions, const ASTContext *C,
2206+
RecursiveTypeProperties Properties)
2207+
: NominalOrBoundGenericNominalType(TheDecl, Parent, K, C, Properties),
2208+
Substitutions(Substitutions) {}
22202209

22212210
public:
2222-
static BoundGenericType* get(NominalTypeDecl *TheDecl, Type Parent,
2223-
ArrayRef<Type> GenericArgs);
2211+
static BoundGenericType *get(NominalTypeDecl *TheDecl, Type Parent,
2212+
SubstitutionMap Substitutions);
2213+
2214+
/// Deprecated version of the above .
2215+
static BoundGenericType *get(NominalTypeDecl *TheDecl, Type Parent,
2216+
ArrayRef<Type> GenericArgs,
2217+
ModuleDecl *M = nullptr);
22242218

2225-
/// Retrieve the set of generic arguments provided at this level.
2226-
ArrayRef<Type> getDirectGenericArgs() const {
2227-
return {getTrailingObjectsPointer(), Bits.BoundGenericType.GenericArgCount};
2219+
/// Retrieve the substitution map applied to the declaration's underlying
2220+
/// to produce the described type.
2221+
SubstitutionMap getSubstitutionMap() const {
2222+
return Substitutions;
22282223
}
22292224

2230-
void Profile(llvm::FoldingSetNodeID &ID) {
2231-
Profile(ID, getDecl(), getParent(), getDirectGenericArgs());
2225+
ArrayRef<Type> getDirectGenericArgs() const;
2226+
2227+
void Profile(llvm::FoldingSetNodeID &ID) const {
2228+
Profile(ID, getDecl(), getParent(), Substitutions);
22322229
}
22332230
static void Profile(llvm::FoldingSetNodeID &ID, NominalTypeDecl *TheDecl,
2234-
Type Parent, ArrayRef<Type> GenericArgs);
2231+
Type Parent, SubstitutionMap Substitutions);
22352232

22362233
// Implement isa/cast/dyncast/etc.
22372234
static bool classof(const TypeBase *T) {
@@ -2248,17 +2245,13 @@ END_CAN_TYPE_WRAPPER(BoundGenericType, NominalOrBoundGenericNominalType)
22482245

22492246
/// BoundGenericClassType - A subclass of BoundGenericType for the case
22502247
/// when the nominal type is a generic class type.
2251-
class BoundGenericClassType final : public BoundGenericType,
2252-
private llvm::TrailingObjects<BoundGenericClassType, Type> {
2253-
friend TrailingObjects;
2254-
2255-
private:
2248+
class BoundGenericClassType final : public BoundGenericType {
22562249
BoundGenericClassType(ClassDecl *TheDecl, Type Parent,
2257-
ArrayRef<Type> GenericArgs, const ASTContext *C,
2250+
SubstitutionMap Substitutions, const ASTContext *C,
22582251
RecursiveTypeProperties Properties)
22592252
: BoundGenericType(TypeKind::BoundGenericClass,
22602253
reinterpret_cast<NominalTypeDecl*>(TheDecl), Parent,
2261-
GenericArgs, C, Properties) {}
2254+
Substitutions, C, Properties) {}
22622255
friend class BoundGenericType;
22632256

22642257
public:
@@ -2275,17 +2268,13 @@ DEFINE_EMPTY_CAN_TYPE_WRAPPER(BoundGenericClassType, BoundGenericType)
22752268

22762269
/// BoundGenericEnumType - A subclass of BoundGenericType for the case
22772270
/// when the nominal type is a generic enum type.
2278-
class BoundGenericEnumType final : public BoundGenericType,
2279-
private llvm::TrailingObjects<BoundGenericEnumType, Type> {
2280-
friend TrailingObjects;
2281-
2282-
private:
2271+
class BoundGenericEnumType final : public BoundGenericType {
22832272
BoundGenericEnumType(EnumDecl *TheDecl, Type Parent,
2284-
ArrayRef<Type> GenericArgs, const ASTContext *C,
2273+
SubstitutionMap Substitutions, const ASTContext *C,
22852274
RecursiveTypeProperties Properties)
22862275
: BoundGenericType(TypeKind::BoundGenericEnum,
22872276
reinterpret_cast<NominalTypeDecl*>(TheDecl), Parent,
2288-
GenericArgs, C, Properties) {}
2277+
Substitutions, C, Properties) {}
22892278
friend class BoundGenericType;
22902279

22912280
public:
@@ -2302,17 +2291,13 @@ DEFINE_EMPTY_CAN_TYPE_WRAPPER(BoundGenericEnumType, BoundGenericType)
23022291

23032292
/// BoundGenericStructType - A subclass of BoundGenericType for the case
23042293
/// when the nominal type is a generic struct type.
2305-
class BoundGenericStructType final : public BoundGenericType,
2306-
private llvm::TrailingObjects<BoundGenericStructType, Type> {
2307-
friend TrailingObjects;
2308-
2309-
private:
2294+
class BoundGenericStructType final : public BoundGenericType {
23102295
BoundGenericStructType(StructDecl *TheDecl, Type Parent,
2311-
ArrayRef<Type> GenericArgs, const ASTContext *C,
2296+
SubstitutionMap Substitutions, const ASTContext *C,
23122297
RecursiveTypeProperties Properties)
23132298
: BoundGenericType(TypeKind::BoundGenericStruct,
23142299
reinterpret_cast<NominalTypeDecl*>(TheDecl), Parent,
2315-
GenericArgs, C, Properties) {}
2300+
Substitutions, C, Properties) {}
23162301
friend class BoundGenericType;
23172302

23182303
public:
@@ -6424,16 +6409,6 @@ inline ParameterTypeFlags ParameterTypeFlags::fromParameterType(
64246409
return {isVariadic, isAutoClosure, isNonEphemeral, ownership, isNoDerivative};
64256410
}
64266411

6427-
inline const Type *BoundGenericType::getTrailingObjectsPointer() const {
6428-
if (auto ty = dyn_cast<BoundGenericStructType>(this))
6429-
return ty->getTrailingObjects<Type>();
6430-
if (auto ty = dyn_cast<BoundGenericEnumType>(this))
6431-
return ty->getTrailingObjects<Type>();
6432-
if (auto ty = dyn_cast<BoundGenericClassType>(this))
6433-
return ty->getTrailingObjects<Type>();
6434-
llvm_unreachable("Unhandled BoundGenericType!");
6435-
}
6436-
64376412
inline ArrayRef<AnyFunctionType::Param> AnyFunctionType::getParams() const {
64386413
switch (getKind()) {
64396414
case TypeKind::Function:

lib/AST/ASTContext.cpp

Lines changed: 63 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -2554,48 +2554,58 @@ get(GenericTypeDecl *TheDecl, Type Parent, const ASTContext &C) {
25542554
return result;
25552555
}
25562556

2557-
void BoundGenericType::Profile(llvm::FoldingSetNodeID &ID,
2558-
NominalTypeDecl *TheDecl, Type Parent,
2559-
ArrayRef<Type> GenericArgs) {
2560-
ID.AddPointer(TheDecl);
2561-
ID.AddPointer(Parent.getPointer());
2562-
ID.AddInteger(GenericArgs.size());
2563-
for (Type Arg : GenericArgs) {
2564-
ID.AddPointer(Arg.getPointer());
2557+
BoundGenericType *BoundGenericType::get(NominalTypeDecl *TheDecl,
2558+
Type Parent,
2559+
ArrayRef<Type> GenericArgs,
2560+
ModuleDecl *M) {
2561+
assert(GenericArgs.size() == TheDecl->getGenericParams()->size() &&
2562+
"generic parameter and argument count mismatch");
2563+
2564+
const auto Sig = TheDecl->getGenericSignature();
2565+
assert(Sig);
2566+
2567+
// Add any substitutions from the parent type.
2568+
TypeSubstitutionMap Subs;
2569+
if (Parent)
2570+
Subs = Parent->getContextSubstitutions(TheDecl->getDeclContext());
2571+
2572+
// Now, map the declaration's own generic parameters to
2573+
// the provided arguments.
2574+
const auto GenParams = Sig->getInnermostGenericParams();
2575+
for (const auto I : indices(GenericArgs)) {
2576+
Subs[GenParams[I]->getCanonicalType()->castTo<GenericTypeParamType>()] =
2577+
GenericArgs[I];
25652578
}
2566-
}
25672579

2568-
BoundGenericType::BoundGenericType(TypeKind theKind,
2569-
NominalTypeDecl *theDecl,
2570-
Type parent,
2571-
ArrayRef<Type> genericArgs,
2572-
const ASTContext *context,
2573-
RecursiveTypeProperties properties)
2574-
: NominalOrBoundGenericNominalType(theDecl, parent, theKind, context,
2575-
properties) {
2576-
Bits.BoundGenericType.GenericArgCount = genericArgs.size();
2577-
// Subtypes are required to provide storage for the generic arguments
2578-
std::uninitialized_copy(genericArgs.begin(), genericArgs.end(),
2579-
getTrailingObjectsPointer());
2580+
// If we haven't been given a module for conformance lookup,
2581+
// use the parent module of the referenced decl.
2582+
if (M == nullptr)
2583+
M = TheDecl->getParentModule();
2584+
2585+
// Form the substitution map.
2586+
const auto SubMap = SubstitutionMap::get(
2587+
Sig, QueryTypeSubstitutionMap{Subs}, LookUpConformanceInModule(M));
2588+
2589+
return get(TheDecl, Parent, SubMap);
25802590
}
25812591

25822592
BoundGenericType *BoundGenericType::get(NominalTypeDecl *TheDecl,
25832593
Type Parent,
2584-
ArrayRef<Type> GenericArgs) {
2585-
assert(TheDecl->getGenericParams() && "must be a generic type decl");
2594+
SubstitutionMap Substitutions) {
2595+
assert(Substitutions && "must have non-empty substitutions");
2596+
assert(TheDecl->isGeneric() && "must be a generic type decl");
25862597
assert((!Parent || Parent->is<NominalType>() ||
25872598
Parent->is<BoundGenericType>() ||
25882599
Parent->is<UnboundGenericType>()) &&
25892600
"parent must be a nominal type");
25902601

2591-
ASTContext &C = TheDecl->getDeclContext()->getASTContext();
2602+
const ASTContext &C = TheDecl->getDeclContext()->getASTContext();
25922603
llvm::FoldingSetNodeID ID;
2593-
BoundGenericType::Profile(ID, TheDecl, Parent, GenericArgs);
2604+
BoundGenericType::Profile(ID, TheDecl, Parent, Substitutions);
25942605
RecursiveTypeProperties Properties;
25952606
if (Parent) Properties |= Parent->getRecursiveProperties();
2596-
for (Type Arg : GenericArgs) {
2597-
Properties |= Arg->getRecursiveProperties();
2598-
}
2607+
for (const auto &substGP : Substitutions.getReplacementTypes())
2608+
Properties |= substGP->getRecursiveProperties();
25992609

26002610
const auto Arena = getArena(Properties);
26012611

@@ -2605,32 +2615,22 @@ BoundGenericType *BoundGenericType::get(NominalTypeDecl *TheDecl,
26052615
InsertPos))
26062616
return BGT;
26072617

2608-
bool IsCanonical = !Parent || Parent->isCanonical();
2609-
if (IsCanonical) {
2610-
for (Type Arg : GenericArgs) {
2611-
if (!Arg->isCanonical()) {
2612-
IsCanonical = false;
2613-
break;
2614-
}
2615-
}
2616-
}
2618+
const bool IsCanonical =
2619+
(!Parent || Parent->isCanonical()) && Substitutions.isCanonical();
26172620

26182621
BoundGenericType *BGT;
2622+
void *const Mem = C.Allocate(sizeof(BoundGenericType),
2623+
alignof(BoundGenericType), Arena);
2624+
const ASTContext *CanContext = IsCanonical ? &C : nullptr;
26192625
if (auto *const CD = dyn_cast<ClassDecl>(TheDecl)) {
2620-
auto sz = BoundGenericClassType::totalSizeToAlloc<Type>(GenericArgs.size());
2621-
auto Mem = C.Allocate(sz, alignof(BoundGenericClassType), Arena);
2622-
BGT = new (Mem) BoundGenericClassType(
2623-
CD, Parent, GenericArgs, IsCanonical ? &C : nullptr, Properties);
2626+
BGT = new (Mem) BoundGenericClassType(CD, Parent, Substitutions,
2627+
CanContext, Properties);
26242628
} else if (auto *const SD = dyn_cast<StructDecl>(TheDecl)) {
2625-
auto sz =BoundGenericStructType::totalSizeToAlloc<Type>(GenericArgs.size());
2626-
auto Mem = C.Allocate(sz, alignof(BoundGenericStructType), Arena);
2627-
BGT = new (Mem) BoundGenericStructType(
2628-
SD, Parent, GenericArgs, IsCanonical ? &C : nullptr, Properties);
2629+
BGT = new (Mem) BoundGenericStructType(SD, Parent, Substitutions,
2630+
CanContext, Properties);
26292631
} else if (auto *const ED = dyn_cast<EnumDecl>(TheDecl)) {
2630-
auto sz = BoundGenericEnumType::totalSizeToAlloc<Type>(GenericArgs.size());
2631-
auto Mem = C.Allocate(sz, alignof(BoundGenericEnumType), Arena);
2632-
BGT = new (Mem) BoundGenericEnumType(
2633-
ED, Parent, GenericArgs, IsCanonical ? &C : nullptr, Properties);
2632+
BGT = new (Mem) BoundGenericEnumType(ED, Parent, Substitutions,
2633+
CanContext, Properties);
26342634
} else {
26352635
llvm_unreachable("Unhandled NominalTypeDecl");
26362636
}
@@ -2639,6 +2639,18 @@ BoundGenericType *BoundGenericType::get(NominalTypeDecl *TheDecl,
26392639
return BGT;
26402640
}
26412641

2642+
ArrayRef<Type> BoundGenericType::getDirectGenericArgs() const {
2643+
return getSubstitutionMap().getInnermostReplacementTypes();
2644+
}
2645+
2646+
void BoundGenericType::Profile(llvm::FoldingSetNodeID &ID,
2647+
NominalTypeDecl *TheDecl, Type Parent,
2648+
SubstitutionMap Substitutions) {
2649+
ID.AddPointer(TheDecl);
2650+
ID.AddPointer(Parent.getPointer());
2651+
Substitutions.profile(ID);
2652+
}
2653+
26422654
NominalType *NominalType::get(NominalTypeDecl *D, Type Parent, const ASTContext &C) {
26432655
assert((isa<ProtocolDecl>(D) || !D->getGenericParams()) &&
26442656
"must be a non-generic type decl");
@@ -2990,7 +3002,8 @@ Type AnyFunctionType::Param::getParameterType(bool forCanonical,
29903002
if (!arrayDecl)
29913003
type = ErrorType::get(*ctx);
29923004
else if (forCanonical)
2993-
type = BoundGenericType::get(arrayDecl, Type(), {type});
3005+
type =
3006+
BoundGenericType::get(arrayDecl, Type(), {type})->getCanonicalType();
29943007
else
29953008
type = ArraySliceType::get(type);
29963009
}

lib/AST/ASTDemangler.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -292,8 +292,10 @@ Type ASTBuilder::createBoundGenericType(GenericTypeDecl *decl,
292292
if (!validateParentType(decl, parent))
293293
return Type();
294294

295+
// FIXME: This is the wrong module
296+
auto *moduleDecl = decl->getParentModule();
295297
if (auto *nominalDecl = dyn_cast<NominalTypeDecl>(decl))
296-
return BoundGenericType::get(nominalDecl, parent, args);
298+
return BoundGenericType::get(nominalDecl, parent, args, moduleDecl);
297299

298300
// Combine the substitutions from our parent type with our generic
299301
// arguments.
@@ -312,8 +314,6 @@ Type ASTBuilder::createBoundGenericType(GenericTypeDecl *decl,
312314
substTy;
313315
}
314316

315-
// FIXME: This is the wrong module
316-
auto *moduleDecl = decl->getParentModule();
317317
auto subMap = SubstitutionMap::get(genericSig,
318318
QueryTypeSubstitutionMap{subs},
319319
LookUpConformanceInModule(moduleDecl));

lib/AST/Decl.cpp

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3759,15 +3759,9 @@ static Type computeNominalType(NominalTypeDecl *decl, DeclTypeKind kind) {
37593759
case DeclTypeKind::DeclaredType:
37603760
return UnboundGenericType::get(decl, ParentTy, ctx);
37613761
case DeclTypeKind::DeclaredInterfaceType: {
3762-
// Note that here, we need to be able to produce a type
3763-
// before the decl has been validated, so we rely on
3764-
// the generic parameter list directly instead of looking
3765-
// at the signature.
3766-
SmallVector<Type, 4> args;
3767-
for (auto param : decl->getGenericParams()->getParams())
3768-
args.push_back(param->getDeclaredInterfaceType());
3769-
3770-
return BoundGenericType::get(decl, ParentTy, args);
3762+
const auto sig = decl->getGenericSignature();
3763+
return BoundGenericType::get(decl, ParentTy,
3764+
sig->getIdentitySubstitutionMap());
37713765
}
37723766
}
37733767

0 commit comments

Comments
 (0)