Skip to content

Commit a2645b7

Browse files
authored
Merge pull request #62589 from rjmccall/local-archetypes
Generalize the tracking of opened archetypes to cover pack element archetypes
2 parents 68d4f24 + 6d4588c commit a2645b7

File tree

15 files changed

+210
-159
lines changed

15 files changed

+210
-159
lines changed

include/swift/AST/TypeNodes.def

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,8 +147,10 @@ ABSTRACT_TYPE(Substitutable, Type)
147147
ABSTRACT_TYPE(Archetype, SubstitutableType)
148148
ALWAYS_CANONICAL_TYPE(PrimaryArchetype, ArchetypeType)
149149
ALWAYS_CANONICAL_TYPE(OpaqueTypeArchetype, ArchetypeType)
150-
ALWAYS_CANONICAL_TYPE(OpenedArchetype, ArchetypeType)
151-
ALWAYS_CANONICAL_TYPE(ElementArchetype, ArchetypeType)
150+
ABSTRACT_TYPE(LocalArchetype, ArchetypeType)
151+
ALWAYS_CANONICAL_TYPE(OpenedArchetype, LocalArchetypeType)
152+
ALWAYS_CANONICAL_TYPE(ElementArchetype, LocalArchetypeType)
153+
TYPE_RANGE(LocalArchetype, OpenedArchetype, ElementArchetype)
152154
ALWAYS_CANONICAL_TYPE(PackArchetype, ArchetypeType)
153155
TYPE_RANGE(Archetype, PrimaryArchetype, PackArchetype)
154156
TYPE(GenericTypeParam, SubstitutableType)

include/swift/AST/Types.h

Lines changed: 52 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,10 @@ class RecursiveTypeProperties {
168168
/// This type contains a parameterized existential type \c any P<T>.
169169
HasParameterizedExistential = 0x2000,
170170

171-
Last_Property = HasParameterizedExistential
171+
/// This type contains an ElementArchetype.
172+
HasElementArchetype = 0x4000,
173+
174+
Last_Property = HasElementArchetype
172175
};
173176
enum { BitWidth = countBitsUsed(Property::Last_Property) };
174177

@@ -212,9 +215,19 @@ class RecursiveTypeProperties {
212215
bool hasDependentMember() const { return Bits & HasDependentMember; }
213216

214217
/// Does a type with these properties structurally contain an
215-
/// archetype?
218+
/// opened existential archetype?
216219
bool hasOpenedExistential() const { return Bits & HasOpenedExistential; }
217220

221+
/// Does a type with these properties structurally contain an
222+
/// opened element archetype?
223+
bool hasElementArchetype() const { return Bits & HasElementArchetype; }
224+
225+
/// Does a type with these properties structurally contain a local
226+
/// archetype?
227+
bool hasLocalArchetype() const {
228+
return hasOpenedExistential() || hasElementArchetype();
229+
}
230+
218231
/// Does a type with these properties structurally contain a
219232
/// reference to DynamicSelf?
220233
bool hasDynamicSelf() const { return Bits & HasDynamicSelf; }
@@ -629,6 +642,16 @@ class alignas(1 << TypeAlignInBits) TypeBase
629642
return getRecursiveProperties().hasOpenedExistential();
630643
}
631644

645+
/// Determine whether the type involves an opened element archetype.
646+
bool hasElementArchetype() const {
647+
return getRecursiveProperties().hasElementArchetype();
648+
}
649+
650+
/// Determine whether the type involves a local archetype.
651+
bool hasLocalArchetype() const {
652+
return getRecursiveProperties().hasLocalArchetype();
653+
}
654+
632655
bool hasParameterPack() const {
633656
return getRecursiveProperties().hasParameterPack();
634657
}
@@ -5914,8 +5937,29 @@ class ReplaceOpaqueTypesWithUnderlyingTypes {
59145937
bool isWholeModule() const { return inContextAndIsWholeModule.getInt(); }
59155938
};
59165939

5940+
/// An archetype that's only valid in a portion of a local context.
5941+
class LocalArchetypeType : public ArchetypeType {
5942+
protected:
5943+
using ArchetypeType::ArchetypeType;
5944+
5945+
public:
5946+
LocalArchetypeType *getRoot() const {
5947+
return cast<LocalArchetypeType>(ArchetypeType::getRoot());
5948+
}
5949+
5950+
static bool classof(const TypeBase *type) {
5951+
return type->getKind() == TypeKind::OpenedArchetype ||
5952+
type->getKind() == TypeKind::ElementArchetype;
5953+
}
5954+
};
5955+
BEGIN_CAN_TYPE_WRAPPER(LocalArchetypeType, ArchetypeType)
5956+
CanLocalArchetypeType getRoot() const {
5957+
return CanLocalArchetypeType(getPointer()->getRoot());
5958+
}
5959+
END_CAN_TYPE_WRAPPER(LocalArchetypeType, ArchetypeType)
5960+
59175961
/// An archetype that represents the dynamic type of an opened existential.
5918-
class OpenedArchetypeType final : public ArchetypeType,
5962+
class OpenedArchetypeType final : public LocalArchetypeType,
59195963
private ArchetypeTrailingObjects<OpenedArchetypeType>
59205964
{
59215965
friend TrailingObjects;
@@ -6016,11 +6060,11 @@ class OpenedArchetypeType final : public ArchetypeType,
60166060
ArrayRef<ProtocolDecl *> conformsTo, Type superclass,
60176061
LayoutConstraint layout);
60186062
};
6019-
BEGIN_CAN_TYPE_WRAPPER(OpenedArchetypeType, ArchetypeType)
6063+
BEGIN_CAN_TYPE_WRAPPER(OpenedArchetypeType, LocalArchetypeType)
60206064
CanOpenedArchetypeType getRoot() const {
60216065
return CanOpenedArchetypeType(getPointer()->getRoot());
60226066
}
6023-
END_CAN_TYPE_WRAPPER(OpenedArchetypeType, ArchetypeType)
6067+
END_CAN_TYPE_WRAPPER(OpenedArchetypeType, LocalArchetypeType)
60246068

60256069
/// A wrapper around a shape type to use in ArchetypeTrailingObjects
60266070
/// for PackArchetypeType.
@@ -6065,7 +6109,7 @@ BEGIN_CAN_TYPE_WRAPPER(PackArchetypeType, ArchetypeType)
60656109
END_CAN_TYPE_WRAPPER(PackArchetypeType, ArchetypeType)
60666110

60676111
/// An archetype that represents the element type of a pack archetype.
6068-
class ElementArchetypeType final : public ArchetypeType,
6112+
class ElementArchetypeType final : public LocalArchetypeType,
60696113
private ArchetypeTrailingObjects<ElementArchetypeType>
60706114
{
60716115
friend TrailingObjects;
@@ -6104,11 +6148,11 @@ class ElementArchetypeType final : public ArchetypeType,
61046148
ArrayRef<ProtocolDecl *> conformsTo, Type superclass,
61056149
LayoutConstraint layout);
61066150
};
6107-
BEGIN_CAN_TYPE_WRAPPER(ElementArchetypeType, ArchetypeType)
6151+
BEGIN_CAN_TYPE_WRAPPER(ElementArchetypeType, LocalArchetypeType)
61086152
CanElementArchetypeType getRoot() const {
61096153
return CanElementArchetypeType(getPointer()->getRoot());
61106154
}
6111-
END_CAN_TYPE_WRAPPER(ElementArchetypeType, ArchetypeType)
6155+
END_CAN_TYPE_WRAPPER(ElementArchetypeType, LocalArchetypeType)
61126156

61136157
template<typename Type>
61146158
const Type *ArchetypeType::getSubclassTrailingObjects() const {

include/swift/SIL/SILInstruction.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -685,13 +685,13 @@ class SILInstruction : public llvm::ilist_node<SILInstruction> {
685685
return getResultsImpl().getTypes();
686686
}
687687

688-
/// Run the given function for each opened archetype this instruction
688+
/// Run the given function for each local archetype this instruction
689689
/// defines, passing the value that should be used to record the
690690
/// dependency.
691-
void forEachDefinedOpenedArchetype(
692-
llvm::function_ref<void(CanOpenedArchetypeType archetype,
691+
void forEachDefinedLocalArchetype(
692+
llvm::function_ref<void(CanLocalArchetypeType archetype,
693693
SILValue typeDependency)> function) const;
694-
bool definesOpenedArchetypes() const;
694+
bool definesLocalArchetypes() const;
695695

696696
MemoryBehavior getMemoryBehavior() const;
697697
ReleasingBehavior getReleasingBehavior() const;

include/swift/SIL/SILModule.h

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -345,22 +345,22 @@ class SILModule {
345345
/// projections, shared between all functions in the module.
346346
std::unique_ptr<IndexTrieNode> indexTrieRoot;
347347

348-
/// A mapping from root opened archetypes to the instructions which define
348+
/// A mapping from root local archetypes to the instructions which define
349349
/// them.
350350
///
351-
/// The value is either a SingleValueInstruction or a PlaceholderValue, in case
352-
/// an opened archetype definition is looked up during parsing or
353-
/// deserializing SIL, where opened archetypes can be forward referenced.
351+
/// The value is either a SingleValueInstruction or a PlaceholderValue,
352+
/// in case a local archetype definition is looked up during parsing or
353+
/// deserializing SIL, where local archetypes can be forward referenced.
354354
///
355355
/// In theory we wouldn't need to have the SILFunction in the key, because
356-
/// opened archetypes \em should be unique across the module. But currently
357-
/// in some rare cases SILGen re-uses the same opened archetype for multiple
356+
/// local archetypes \em should be unique across the module. But currently
357+
/// in some rare cases SILGen re-uses the same local archetype for multiple
358358
/// functions.
359-
using OpenedArchetypeKey = std::pair<OpenedArchetypeType *, SILFunction *>;
360-
llvm::DenseMap<OpenedArchetypeKey, SILValue> RootOpenedArchetypeDefs;
359+
using LocalArchetypeKey = std::pair<LocalArchetypeType *, SILFunction *>;
360+
llvm::DenseMap<LocalArchetypeKey, SILValue> RootLocalArchetypeDefs;
361361

362-
/// The number of PlaceholderValues in RootOpenedArchetypeDefs.
363-
int numUnresolvedOpenedArchetypes = 0;
362+
/// The number of PlaceholderValues in RootLocalArchetypeDefs.
363+
int numUnresolvedLocalArchetypes = 0;
364364

365365
/// The options passed into this SILModule.
366366
const SILOptions &Options;
@@ -444,31 +444,31 @@ class SILModule {
444444
regDeserializationNotificationHandlerForAllFuncOME = true;
445445
}
446446

447-
/// Returns the instruction which defines the given root opened archetype,
447+
/// Returns the instruction which defines the given root local archetype,
448448
/// e.g. an open_existential_addr.
449449
///
450-
/// In case the opened archetype is not defined yet (e.g. during parsing or
450+
/// In case the local archetype is not defined yet (e.g. during parsing or
451451
/// deserialization), a PlaceholderValue is returned. This should not be the
452452
/// case outside of parsing or deserialization.
453-
SILValue getRootOpenedArchetypeDef(CanOpenedArchetypeType archetype,
454-
SILFunction *inFunction);
453+
SILValue getRootLocalArchetypeDef(CanLocalArchetypeType archetype,
454+
SILFunction *inFunction);
455455

456-
/// Returns the instruction which defines the given root opened archetype,
456+
/// Returns the instruction which defines the given root local archetype,
457457
/// e.g. an open_existential_addr.
458458
///
459-
/// In contrast to getOpenedArchetypeDef, it is required that all opened
459+
/// In contrast to getLocalArchetypeDef, it is required that all local
460460
/// archetypes are resolved.
461461
SingleValueInstruction *
462-
getRootOpenedArchetypeDefInst(CanOpenedArchetypeType archetype,
463-
SILFunction *inFunction) {
462+
getRootLocalArchetypeDefInst(CanLocalArchetypeType archetype,
463+
SILFunction *inFunction) {
464464
return cast<SingleValueInstruction>(
465-
getRootOpenedArchetypeDef(archetype, inFunction));
465+
getRootLocalArchetypeDef(archetype, inFunction));
466466
}
467467

468-
/// Returns true if there are unresolved opened archetypes in the module.
468+
/// Returns true if there are unresolved local archetypes in the module.
469469
///
470470
/// This should only be the case during parsing or deserialization.
471-
bool hasUnresolvedOpenedArchetypeDefinitions();
471+
bool hasUnresolvedLocalArchetypeDefinitions();
472472

473473
/// Get a unique index for a struct or class field in layout order.
474474
///

include/swift/SIL/SILType.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ namespace swift {
5050
/// this is the task of the type visitor invoking it.
5151
/// \returns The found opened archetype or empty type otherwise.
5252
CanOpenedArchetypeType getOpenedArchetypeOf(CanType Ty);
53+
CanLocalArchetypeType getLocalArchetypeOf(CanType Ty);
5354

5455
/// How an existential type container is represented.
5556
enum class ExistentialRepresentation {

lib/AST/ASTContext.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3837,7 +3837,7 @@ isAnyFunctionTypeCanonical(ArrayRef<AnyFunctionType::Param> params,
38373837
static RecursiveTypeProperties
38383838
getGenericFunctionRecursiveProperties(ArrayRef<AnyFunctionType::Param> params,
38393839
Type result) {
3840-
static_assert(RecursiveTypeProperties::BitWidth == 14,
3840+
static_assert(RecursiveTypeProperties::BitWidth == 15,
38413841
"revisit this if you add new recursive type properties");
38423842
RecursiveTypeProperties properties;
38433843

@@ -4464,7 +4464,7 @@ CanSILFunctionType SILFunctionType::get(
44644464
void *mem = ctx.Allocate(bytes, alignof(SILFunctionType));
44654465

44664466
RecursiveTypeProperties properties;
4467-
static_assert(RecursiveTypeProperties::BitWidth == 14,
4467+
static_assert(RecursiveTypeProperties::BitWidth == 15,
44684468
"revisit this if you add new recursive type properties");
44694469
for (auto &param : params)
44704470
properties |= param.getInterfaceType()->getRecursiveProperties();

lib/AST/Type.cpp

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3964,11 +3964,12 @@ OpenedArchetypeType::OpenedArchetypeType(
39643964
GenericEnvironment *environment, Type interfaceType,
39653965
ArrayRef<ProtocolDecl *> conformsTo, Type superclass,
39663966
LayoutConstraint layout)
3967-
: ArchetypeType(TypeKind::OpenedArchetype, interfaceType->getASTContext(),
3968-
RecursiveTypeProperties::HasArchetype
3969-
| RecursiveTypeProperties::HasOpenedExistential,
3970-
interfaceType, conformsTo, superclass, layout,
3971-
environment)
3967+
: LocalArchetypeType(TypeKind::OpenedArchetype,
3968+
interfaceType->getASTContext(),
3969+
RecursiveTypeProperties::HasArchetype
3970+
| RecursiveTypeProperties::HasOpenedExistential,
3971+
interfaceType, conformsTo, superclass, layout,
3972+
environment)
39723973
{
39733974
assert(!interfaceType->isParameterPack());
39743975
}
@@ -4022,9 +4023,11 @@ ElementArchetypeType::ElementArchetypeType(
40224023
const ASTContext &Ctx, GenericEnvironment *GenericEnv, Type InterfaceType,
40234024
ArrayRef<ProtocolDecl *> ConformsTo, Type Superclass,
40244025
LayoutConstraint Layout)
4025-
: ArchetypeType(TypeKind::ElementArchetype, Ctx,
4026-
RecursiveTypeProperties::HasArchetype, InterfaceType,
4027-
ConformsTo, Superclass, Layout, GenericEnv) {
4026+
: LocalArchetypeType(TypeKind::ElementArchetype, Ctx,
4027+
RecursiveTypeProperties::HasArchetype |
4028+
RecursiveTypeProperties::HasElementArchetype,
4029+
InterfaceType,
4030+
ConformsTo, Superclass, Layout, GenericEnv) {
40284031
}
40294032

40304033
CanTypeWrapper<ElementArchetypeType> ElementArchetypeType::getNew(

lib/SIL/IR/SILInstruction.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1531,17 +1531,17 @@ const ValueBase *SILInstructionResultArray::back() const {
15311531
// Defined opened archetypes
15321532
//===----------------------------------------------------------------------===//
15331533

1534-
bool SILInstruction::definesOpenedArchetypes() const {
1534+
bool SILInstruction::definesLocalArchetypes() const {
15351535
bool definesAny = false;
1536-
forEachDefinedOpenedArchetype([&](CanOpenedArchetypeType type,
1537-
SILValue dependency) {
1536+
forEachDefinedLocalArchetype([&](CanLocalArchetypeType type,
1537+
SILValue dependency) {
15381538
definesAny = true;
15391539
});
15401540
return definesAny;
15411541
}
15421542

1543-
void SILInstruction::forEachDefinedOpenedArchetype(
1544-
llvm::function_ref<void(CanOpenedArchetypeType, SILValue)> fn) const {
1543+
void SILInstruction::forEachDefinedLocalArchetype(
1544+
llvm::function_ref<void(CanLocalArchetypeType, SILValue)> fn) const {
15451545
switch (getKind()) {
15461546
#define SINGLE_VALUE_SINGLE_OPEN(TYPE) \
15471547
case SILInstructionKind::TYPE: { \

lib/SIL/IR/SILInstructions.cpp

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ static void *allocateTrailingInst(SILFunction &F, CountTypes... counts) {
4545

4646
namespace {
4747
class TypeDependentOperandCollector {
48-
SmallVector<CanOpenedArchetypeType, 4> rootOpenedArchetypes;
48+
SmallVector<CanLocalArchetypeType, 4> rootLocalArchetypes;
4949
bool hasDynamicSelf = false;
5050
public:
5151
void collect(CanType type);
@@ -72,27 +72,27 @@ class TypeDependentOperandCollector {
7272

7373
}
7474

75-
/// Collect root open archetypes from a given type into \p RootOpenedArchetypes.
76-
/// \p RootOpenedArchetypes is being used as a set. We don't use a real set type
75+
/// Collect root open archetypes from a given type into \p RootLocalArchetypes.
76+
/// \p RootLocalArchetypes is being used as a set. We don't use a real set type
7777
/// here for performance reasons.
7878
void TypeDependentOperandCollector::collect(CanType type) {
7979
if (!type)
8080
return;
8181
if (type->hasDynamicSelfType())
8282
hasDynamicSelf = true;
83-
if (!type->hasOpenedExistential())
83+
if (!type->hasLocalArchetype())
8484
return;
8585
type.visit([&](CanType t) {
86-
if (const auto opened = dyn_cast<OpenedArchetypeType>(t)) {
87-
const auto root = opened.getRoot();
86+
if (const auto local = dyn_cast<LocalArchetypeType>(t)) {
87+
const auto root = local.getRoot();
8888

89-
// Add this root opened archetype if it was not seen yet.
89+
// Add this root local archetype if it was not seen yet.
9090
// We don't use a set here, because the number of open archetypes
9191
// is usually very small and using a real set may introduce too
9292
// much overhead.
93-
if (std::find(rootOpenedArchetypes.begin(), rootOpenedArchetypes.end(),
94-
root) == rootOpenedArchetypes.end())
95-
rootOpenedArchetypes.push_back(root);
93+
if (std::find(rootLocalArchetypes.begin(), rootLocalArchetypes.end(),
94+
root) == rootLocalArchetypes.end())
95+
rootLocalArchetypes.push_back(root);
9696
}
9797
});
9898
}
@@ -112,12 +112,12 @@ void TypeDependentOperandCollector::collect(SubstitutionMap subs) {
112112
void TypeDependentOperandCollector::addTo(SmallVectorImpl<SILValue> &operands,
113113
SILFunction &F) {
114114
size_t firstArchetypeOperand = operands.size();
115-
for (CanOpenedArchetypeType archetype : rootOpenedArchetypes) {
116-
SILValue def = F.getModule().getRootOpenedArchetypeDef(archetype, &F);
115+
for (CanLocalArchetypeType archetype : rootLocalArchetypes) {
116+
SILValue def = F.getModule().getRootLocalArchetypeDef(archetype, &F);
117117
assert(def->getFunction() == &F &&
118-
"def of root opened archetype is in wrong function");
118+
"def of root local archetype is in wrong function");
119119

120-
// The archetypes in rootOpenedArchetypes have already been uniqued,
120+
// The archetypes in rootLocalArchetypes have already been uniqued,
121121
// but a single instruction can open multiple archetypes (e.g.
122122
// open_pack_element), so we also unique the actual operand values.
123123
// As above, we assume there are very few values in practice and so
@@ -130,9 +130,9 @@ void TypeDependentOperandCollector::addTo(SmallVectorImpl<SILValue> &operands,
130130
operands.push_back(F.getDynamicSelfMetadata());
131131
}
132132

133-
/// Collects all root opened archetypes from a type and a substitution list, and
133+
/// Collects all root local archetypes from a type and a substitution list, and
134134
/// forms a corresponding list of operands.
135-
/// We need to know the number of root opened archetypes to estimate the number
135+
/// We need to know the number of root local archetypes to estimate the number
136136
/// of corresponding operands for the instruction being formed, because we need
137137
/// to reserve enough memory for these operands.
138138
template <class... Sources>

0 commit comments

Comments
 (0)