Skip to content

Commit 3dfd737

Browse files
authored
Merge pull request #15416 from DougGregor/generic-typealias-sugar
[AST] Preserve type sugar for generic typealiases
2 parents aeb9283 + 253bd10 commit 3dfd737

33 files changed

+515
-33
lines changed

include/swift/AST/SubstitutionMap.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@
3636
#include "llvm/ADT/SmallPtrSet.h"
3737
#include "llvm/ADT/SmallVector.h"
3838

39+
namespace llvm {
40+
class FoldingSetNodeID;
41+
}
42+
3943
namespace swift {
4044

4145
class GenericSignature;
@@ -174,6 +178,9 @@ class SubstitutionMap {
174178

175179
LLVM_ATTRIBUTE_DEPRECATED(void dump() const, "only for use in the debugger");
176180

181+
/// Profile the substitution map, for use with LLVM's FoldingSet.
182+
void profile(llvm::FoldingSetNodeID &id) const;
183+
177184
private:
178185
friend class GenericSignature;
179186
friend class GenericEnvironment;

include/swift/AST/TypeNodes.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ UNCHECKED_TYPE(TypeVariable, Type)
146146
ABSTRACT_SUGARED_TYPE(Sugar, Type)
147147
SUGARED_TYPE(Paren, SugarType)
148148
SUGARED_TYPE(NameAlias, SugarType)
149+
SUGARED_TYPE(BoundNameAlias, SugarType)
149150
ABSTRACT_SUGARED_TYPE(SyntaxSugar, SugarType)
150151
ABSTRACT_SUGARED_TYPE(UnarySyntaxSugar, SyntaxSugarType)
151152
SUGARED_TYPE(ArraySlice, UnarySyntaxSugarType)

include/swift/AST/Types.h

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,16 @@ class alignas(1 << TypeAlignInBits) TypeBase {
373373
GenericArgCount : 32
374374
);
375375

376+
SWIFT_INLINE_BITFIELD_FULL(BoundNameAliasType, SugarType, 1+16,
377+
: NumPadBits,
378+
379+
/// Whether we have a parent type.
380+
HasParent : 1,
381+
382+
/// The number of substitutions.
383+
NumSubstitutions : 16
384+
);
385+
376386
} Bits;
377387

378388
protected:
@@ -1560,6 +1570,81 @@ class NameAliasType : public SugarType {
15601570
}
15611571
};
15621572

1573+
/// A reference to a type alias that is somehow generic, along with the
1574+
/// set of substitutions to apply to make the type concrete.
1575+
class BoundNameAliasType final
1576+
: public SugarType, public llvm::FoldingSetNode,
1577+
llvm::TrailingObjects<BoundNameAliasType, Type, Substitution>
1578+
{
1579+
TypeAliasDecl *typealias;
1580+
1581+
friend class ASTContext;
1582+
friend TrailingObjects;
1583+
1584+
BoundNameAliasType(TypeAliasDecl *typealias, Type parent,
1585+
const SubstitutionMap &substitutions, Type underlying,
1586+
RecursiveTypeProperties properties);
1587+
1588+
unsigned getNumSubstitutions() const {
1589+
return Bits.BoundNameAliasType.NumSubstitutions;
1590+
}
1591+
1592+
size_t numTrailingObjects(OverloadToken<Type>) const {
1593+
return Bits.BoundNameAliasType.HasParent ? 1 : 0;
1594+
}
1595+
1596+
size_t numTrailingObjects(OverloadToken<Substitution>) const {
1597+
return getNumSubstitutions();
1598+
}
1599+
1600+
/// Retrieve the set of substitutions to be applied to the declaration to
1601+
/// produce the underlying type.
1602+
SubstitutionList getSubstitutionList() const {
1603+
return {getTrailingObjects<Substitution>(), getNumSubstitutions()};
1604+
}
1605+
1606+
public:
1607+
static BoundNameAliasType *get(TypeAliasDecl *typealias, Type parent,
1608+
const SubstitutionMap &substitutions,
1609+
Type underlying);
1610+
1611+
/// \brief Returns the declaration that declares this type.
1612+
TypeAliasDecl *getDecl() const {
1613+
// Avoid requiring the definition of TypeAliasDecl.
1614+
return typealias;
1615+
}
1616+
1617+
/// Retrieve the parent of this type as written, e.g., the part that was
1618+
/// written before ".", if provided.
1619+
Type getParent() const {
1620+
return Bits.BoundNameAliasType.HasParent ? *getTrailingObjects<Type>()
1621+
: Type();
1622+
}
1623+
1624+
/// Retrieve the substitution map applied to the declaration's underlying
1625+
/// to produce the described type.
1626+
SubstitutionMap getSubstitutionMap() const;
1627+
1628+
/// Get the innermost generic arguments, which correspond to the generic
1629+
/// arguments that are directly applied to the typealias declaration in
1630+
/// produced by \c getDecl().
1631+
///
1632+
/// The result can be empty, if the declaration itself is non-generic but
1633+
/// the parent is generic.
1634+
SmallVector<Type, 2> getInnermostGenericArgs() const;
1635+
1636+
// Support for FoldingSet.
1637+
void Profile(llvm::FoldingSetNodeID &id) const;
1638+
1639+
static void Profile(llvm::FoldingSetNodeID &id, TypeAliasDecl *typealias,
1640+
Type parent, const SubstitutionMap &substitutions);
1641+
1642+
// Implement isa/cast/dyncast/etc.
1643+
static bool classof(const TypeBase *T) {
1644+
return T->getKind() == TypeKind::BoundNameAlias;
1645+
}
1646+
};
1647+
15631648
// TODO: As part of AST modernization, replace with a proper
15641649
// 'ParameterTypeElt' or similar, and have FunctionTypes only have a list
15651650
// of 'ParameterTypeElt's. Then, this information can be removed from

include/swift/Serialization/DeclTypeRecordNodes.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ TYPE(OPENED_EXISTENTIAL)
106106
TYPE(EXISTENTIAL_METATYPE)
107107
TYPE(SIL_BLOCK_STORAGE)
108108
TYPE(SIL_BOX)
109+
TYPE(BOUND_NAME_ALIAS)
109110

110111
FIRST_DECL(TYPE_ALIAS, 60)
111112
DECL(GENERIC_TYPE_PARAM)

include/swift/Serialization/ModuleFormat.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -647,6 +647,14 @@ namespace decls_block {
647647
TypeIDField // canonical type (a fallback)
648648
>;
649649

650+
using BoundNameAliasTypeLayout = BCRecordLayout<
651+
BOUND_NAME_ALIAS_TYPE,
652+
DeclIDField, // typealias decl
653+
TypeIDField, // parent type
654+
TypeIDField // underlying type
655+
// trailing substitutions
656+
>;
657+
650658
using GenericTypeParamTypeLayout = BCRecordLayout<
651659
GENERIC_TYPE_PARAM_TYPE,
652660
DeclIDField, // generic type parameter decl or depth

lib/AST/ASTContext.cpp

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,7 @@ FOR_KNOWN_FOUNDATION_TYPES(CACHE_FOUNDATION_DECL)
278278
/// arenas.
279279
struct Arena {
280280
llvm::DenseMap<Type, ErrorType *> ErrorTypesWithOriginal;
281+
llvm::FoldingSet<BoundNameAliasType> BoundNameAliasTypes;
281282
llvm::FoldingSet<TupleType> TupleTypes;
282283
llvm::DenseMap<std::pair<Type,char>, MetatypeType*> MetatypeTypes;
283284
llvm::DenseMap<std::pair<Type,char>,
@@ -2886,6 +2887,88 @@ StringRef ASTContext::getSwiftName(KnownFoundationEntity kind) {
28862887
// Type manipulation routines.
28872888
//===----------------------------------------------------------------------===//
28882889

2890+
BoundNameAliasType::BoundNameAliasType(TypeAliasDecl *typealias, Type parent,
2891+
const SubstitutionMap &substitutions,
2892+
Type underlying,
2893+
RecursiveTypeProperties properties)
2894+
: SugarType(TypeKind::BoundNameAlias, underlying, properties),
2895+
typealias(typealias) {
2896+
// Record the parent (or absence of a parent).
2897+
if (parent) {
2898+
Bits.BoundNameAliasType.HasParent = true;
2899+
*getTrailingObjects<Type>() = parent;
2900+
} else {
2901+
Bits.BoundNameAliasType.HasParent = false;
2902+
}
2903+
2904+
// Record the substitutions.
2905+
if (auto genericSig = typealias->getGenericSignature()) {
2906+
SmallVector<Substitution, 4> flatSubs;
2907+
genericSig->getSubstitutions(substitutions, flatSubs);
2908+
Bits.BoundNameAliasType.NumSubstitutions = flatSubs.size();
2909+
std::copy(flatSubs.begin(), flatSubs.end(),
2910+
getTrailingObjects<Substitution>());
2911+
} else {
2912+
Bits.BoundNameAliasType.NumSubstitutions = 0;
2913+
}
2914+
}
2915+
2916+
BoundNameAliasType *BoundNameAliasType::get(
2917+
TypeAliasDecl *typealias,
2918+
Type parent,
2919+
const SubstitutionMap &substitutions,
2920+
Type underlying) {
2921+
// Compute the recursive properties.
2922+
auto properties = underlying->getRecursiveProperties();
2923+
if (parent)
2924+
properties |= parent->getRecursiveProperties();
2925+
auto genericSig = typealias->getGenericSignature();
2926+
if (genericSig) {
2927+
for (Type gp : genericSig->getGenericParams()) {
2928+
properties |= gp.subst(substitutions, SubstFlags::UseErrorType)
2929+
->getRecursiveProperties();
2930+
}
2931+
}
2932+
2933+
// Figure out which arena this type will go into.
2934+
auto &ctx = underlying->getASTContext();
2935+
auto arena = getArena(properties);
2936+
2937+
// Profile the type.
2938+
llvm::FoldingSetNodeID id;
2939+
BoundNameAliasType::Profile(id, typealias, parent, substitutions);
2940+
2941+
// Did we already record this type?
2942+
void *insertPos;
2943+
auto &types = ctx.Impl.getArena(arena).BoundNameAliasTypes;
2944+
if (auto result = types.FindNodeOrInsertPos(id, insertPos))
2945+
return result;
2946+
2947+
// Build a new type.
2948+
unsigned numSubstitutions =
2949+
genericSig ? genericSig->getSubstitutionListSize() : 0;
2950+
auto size =
2951+
totalSizeToAlloc<Type, Substitution>(parent ? 1 : 0, numSubstitutions);
2952+
auto mem = ctx.Allocate(size, alignof(BoundNameAliasType), arena);
2953+
auto result = new (mem) BoundNameAliasType(typealias, parent, substitutions,
2954+
underlying, properties);
2955+
types.InsertNode(result, insertPos);
2956+
return result;
2957+
}
2958+
2959+
void BoundNameAliasType::Profile(llvm::FoldingSetNodeID &id) const {
2960+
Profile(id, getDecl(), getParent(), getSubstitutionMap());
2961+
}
2962+
2963+
void BoundNameAliasType::Profile(
2964+
llvm::FoldingSetNodeID &id,
2965+
TypeAliasDecl *typealias,
2966+
Type parent, const SubstitutionMap &substitutions) {
2967+
id.AddPointer(typealias);
2968+
id.AddPointer(parent.getPointer());
2969+
substitutions.profile(id);
2970+
}
2971+
28892972
// Simple accessors.
28902973
Type ErrorType::get(const ASTContext &C) { return C.TheErrorType; }
28912974

lib/AST/ASTDumper.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3035,6 +3035,17 @@ namespace {
30353035
OS << ")";
30363036
}
30373037

3038+
void visitBoundNameAliasType(BoundNameAliasType *T, StringRef label) {
3039+
printCommon(label, "bound_name_alias_type");
3040+
printField("decl", T->getDecl()->printRef());
3041+
if (T->getParent())
3042+
printRec("parent", T->getParent());
3043+
3044+
for (auto arg : T->getInnermostGenericArgs())
3045+
printRec(arg);
3046+
OS << ")";
3047+
}
3048+
30383049
void visitParenType(ParenType *T, StringRef label) {
30393050
printCommon(label, "paren_type");
30403051
dumpParameterFlags(T->getParameterFlags());

lib/AST/ASTMangler.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -746,6 +746,13 @@ void ASTMangler::appendType(Type type) {
746746
// unless the type alias references a builtin type.
747747
return appendAnyGenericType(decl);
748748
}
749+
case TypeKind::BoundNameAlias: {
750+
assert(DWARFMangling && "sugared types are only legal for the debugger");
751+
auto boundAliasTy = cast<BoundNameAliasType>(tybase);
752+
753+
// FIXME: Mangle as a generic type.
754+
return appendType(boundAliasTy->getSinglyDesugaredType());
755+
}
749756

750757
case TypeKind::Paren:
751758
return appendSugaredType<ParenType>(type);

lib/AST/ASTPrinter.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3283,6 +3283,21 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
32833283
printTypeDeclName(T);
32843284
}
32853285

3286+
void visitBoundNameAliasType(BoundNameAliasType *T) {
3287+
if (Options.PrintForSIL || Options.PrintNameAliasUnderlyingType) {
3288+
visit(T->getSinglyDesugaredType());
3289+
return;
3290+
}
3291+
3292+
if (auto parent = T->getParent()) {
3293+
visit(parent);
3294+
Printer << ".";
3295+
}
3296+
3297+
printTypeDeclName(T);
3298+
printGenericArgs(T->getInnermostGenericArgs());
3299+
}
3300+
32863301
void visitParenType(ParenType *T) {
32873302
Printer << "(";
32883303
printParameterFlags(Printer, Options, T->getParameterFlags());

lib/AST/DiagnosticEngine.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,9 @@ static void formatSelectionArgument(StringRef ModifierArguments,
327327
}
328328

329329
static bool isInterestingTypealias(Type type) {
330+
// Bound name alias types are always interesting.
331+
if (isa<BoundNameAliasType>(type.getPointer())) return true;
332+
330333
auto aliasTy = dyn_cast<NameAliasType>(type.getPointer());
331334
if (!aliasTy)
332335
return false;

lib/AST/SubstitutionMap.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -533,3 +533,24 @@ void SubstitutionMap::dump(llvm::raw_ostream &out) const {
533533
void SubstitutionMap::dump() const {
534534
return dump(llvm::errs());
535535
}
536+
537+
void SubstitutionMap::profile(llvm::FoldingSetNodeID &id) const {
538+
if (empty() || !genericSig) return;
539+
540+
// Replacement types.
541+
for (Type gp : genericSig->getGenericParams()) {
542+
id.AddPointer(gp.subst(*this).getPointer());
543+
}
544+
545+
// Conformance requirements.
546+
for (const auto &req : genericSig->getRequirements()) {
547+
if (req.getKind() != RequirementKind::Conformance)
548+
continue;
549+
550+
auto conformance =
551+
lookupConformance(req.getFirstType()->getCanonicalType(),
552+
req.getSecondType()->castTo<ProtocolType>()->getDecl());
553+
id.AddPointer(conformance ? conformance->getOpaqueValue() : nullptr);
554+
}
555+
}
556+

0 commit comments

Comments
 (0)