Skip to content

Commit 2217916

Browse files
committed
Type utilities for working with opened existential types.
Swift SVN r27188
1 parent 3cebb14 commit 2217916

File tree

3 files changed

+93
-4
lines changed

3 files changed

+93
-4
lines changed

include/swift/AST/Types.h

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ namespace swift {
7676
/// on structural types.
7777
class RecursiveTypeProperties {
7878
public:
79-
enum { BitWidth = 5 };
79+
enum { BitWidth = 6 };
8080

8181
/// A single property.
8282
///
@@ -99,6 +99,9 @@ class RecursiveTypeProperties {
9999
/// This type expression contains an LValueType and can be loaded to convert
100100
/// to an rvalue.
101101
IsLValue = 0x10,
102+
103+
/// This type expression contains an opened existential ArchetypeType.
104+
HasOpenedExistential = 0x20,
102105
};
103106

104107
private:
@@ -132,6 +135,10 @@ class RecursiveTypeProperties {
132135
/// Is a type with these properties an lvalue?
133136
bool isLValue() const { return Bits & IsLValue; }
134137

138+
/// Does a type with these properties structurally contain an
139+
/// archetype?
140+
bool hasOpenedExistential() const { return Bits & HasOpenedExistential; }
141+
135142
/// Returns the set of properties present in either set.
136143
friend RecursiveTypeProperties operator+(Property lhs, Property rhs) {
137144
return RecursiveTypeProperties(lhs | rhs);
@@ -365,6 +372,29 @@ class alignas(1 << TypeAlignInBits) TypeBase {
365372
return getRecursiveProperties().hasArchetype();
366373
}
367374

375+
/// Determine whether the type involves an opened existential archetype.
376+
bool hasOpenedExistential() const {
377+
return getRecursiveProperties().hasOpenedExistential();
378+
}
379+
380+
/// Determine whether the type involves the given opend existential
381+
/// archetype.
382+
bool hasOpenedExistential(ArchetypeType *opened);
383+
384+
/// Determine whether the type is an opened existential type.
385+
///
386+
/// To determine whether there is an opened existential type
387+
/// anywhere in the type, use \c hasOpenedExistential.
388+
bool isOpenedExistential();
389+
390+
/// Retrieve the set of opened existential archetypes that occur
391+
/// within this type.
392+
void getOpenedExistentials(SmallVectorImpl<ArchetypeType *> &opened);
393+
394+
/// Erase the given opened existential type by replacing it with its
395+
/// existential type throughout the given type.
396+
Type eraseOpenedExistential(Module *module, ArchetypeType *opened);
397+
368398
/// \brief Compute and return the set of type variables that occur within this
369399
/// type.
370400
///
@@ -3486,7 +3516,9 @@ class ArchetypeType : public SubstitutableType {
34863516
ArrayRef<ProtocolDecl *> ConformsTo,
34873517
Type Superclass, bool isRecursive = false)
34883518
: SubstitutableType(TypeKind::Archetype, &Ctx,
3489-
RecursiveTypeProperties::HasArchetype),
3519+
RecursiveTypeProperties(
3520+
RecursiveTypeProperties::HasArchetype |
3521+
RecursiveTypeProperties::HasOpenedExistential)),
34903522
ConformsTo(ConformsTo), Superclass(Superclass),
34913523
ParentOrOpened(Existential.getPointer()),
34923524
isRecursive(isRecursive) { }
@@ -3901,6 +3933,16 @@ inline bool TypeBase::isClassExistentialType() {
39013933
return false;
39023934
}
39033935

3936+
inline bool TypeBase::isOpenedExistential() {
3937+
if (!hasOpenedExistential())
3938+
return false;
3939+
3940+
CanType T = getCanonicalType();
3941+
if (auto archetype = dyn_cast<ArchetypeType>(T))
3942+
return !archetype->getOpenedExistentialType().isNull();
3943+
return false;
3944+
}
3945+
39043946
inline ClassDecl *TypeBase::getClassOrBoundGenericClass() {
39053947
return getCanonicalType().getClassOrBoundGenericClass();
39063948
}

lib/AST/ASTContext.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2584,7 +2584,7 @@ GenericFunctionType::get(GenericSignature *sig,
25842584
// always materializable.
25852585
checkFunctionRecursiveProperties(input, output);
25862586
RecursiveTypeProperties properties;
2587-
static_assert(RecursiveTypeProperties::BitWidth == 5,
2587+
static_assert(RecursiveTypeProperties::BitWidth == 6,
25882588
"revisit this if you add new recursive type properties");
25892589

25902590
auto result = new (mem) GenericFunctionType(sig, input, output, info,
@@ -2739,7 +2739,7 @@ CanSILFunctionType SILFunctionType::get(GenericSignature *genericSig,
27392739
// FIXME: If we ever have first-class polymorphic values, we'll need to
27402740
// revisit this.
27412741
RecursiveTypeProperties properties;
2742-
static_assert(RecursiveTypeProperties::BitWidth == 5,
2742+
static_assert(RecursiveTypeProperties::BitWidth == 6,
27432743
"revisit this if you add new recursive type properties");
27442744
if (!genericSig) {
27452745
// Nongeneric SIL functions are dependent if they have dependent argument

lib/AST/Type.cpp

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,53 @@ bool TypeBase::isUnspecializedGeneric() {
388388
llvm_unreachable("bad TypeKind");
389389
}
390390

391+
bool TypeBase::hasOpenedExistential(ArchetypeType *opened) {
392+
assert(opened->getOpenedExistentialType() &&
393+
"not an opened existential type");
394+
395+
if (!hasOpenedExistential())
396+
return false;
397+
398+
return getCanonicalType().findIf([&](Type type) -> bool {
399+
return opened == dyn_cast<ArchetypeType>(type.getPointer());
400+
});
401+
}
402+
403+
void TypeBase::getOpenedExistentials(
404+
SmallVectorImpl<ArchetypeType *> &opened) {
405+
if (!hasOpenedExistential())
406+
return;
407+
408+
SmallPtrSet<ArchetypeType *, 4> known;
409+
getCanonicalType().findIf([&](Type type) -> bool {
410+
auto archetype = dyn_cast<ArchetypeType>(type.getPointer());
411+
if (!archetype)
412+
return false;
413+
414+
if (!archetype->getOpenedExistentialType())
415+
return false;
416+
417+
if (known.insert(archetype).second)
418+
opened.push_back(archetype);
419+
420+
return false;
421+
});
422+
}
423+
424+
Type TypeBase::eraseOpenedExistential(Module *module,
425+
ArchetypeType *opened) {
426+
assert(opened->getOpenedExistentialType() &&
427+
"Not an opened existential type?");
428+
429+
if (!hasOpenedExistential())
430+
return Type(this);
431+
432+
TypeSubstitutionMap substitutions;
433+
substitutions[opened] = opened->getOpenedExistentialType();
434+
return Type(this).subst(module, substitutions, false,
435+
getASTContext().getLazyResolver());
436+
}
437+
391438
void
392439
TypeBase::getTypeVariables(SmallVectorImpl<TypeVariableType *> &typeVariables) {
393440
// If we know we don't have any type variables, we're done.

0 commit comments

Comments
 (0)