-
Notifications
You must be signed in to change notification settings - Fork 10.5k
SE-0309: Covariant erasure for dependent member types #39492
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
3206f5a
427190d
b2fe028
f90120e
756bf30
b3ee4b0
8e0e414
c47f99a
24c19d4
57e8064
60c85b0
e849375
6a25198
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -513,13 +513,13 @@ class alignas(1 << TypeAlignInBits) TypeBase | |
TypeBase *getWithoutSyntaxSugar(); | ||
|
||
/// getASTContext - Return the ASTContext that this type belongs to. | ||
ASTContext &getASTContext(); | ||
ASTContext &getASTContext() const; | ||
|
||
/// isEqual - Return true if these two types are equal, ignoring sugar. | ||
/// | ||
/// To compare sugar, check for pointer equality of the underlying TypeBase * | ||
/// values, obtained by calling getPointer(). | ||
bool isEqual(Type Other); | ||
bool isEqual(Type Other) const; | ||
|
||
/// getDesugaredType - If this type is a sugared type, remove all levels of | ||
/// sugar until we get down to a non-sugar type. | ||
|
@@ -621,7 +621,7 @@ class alignas(1 << TypeAlignInBits) TypeBase | |
|
||
/// Determine whether the type involves the given opened existential | ||
/// archetype. | ||
bool hasOpenedExistential(OpenedArchetypeType *opened); | ||
bool hasOpenedExistentialWithRoot(const OpenedArchetypeType *root) const; | ||
|
||
/// Determine whether the type involves an opaque type. | ||
bool hasOpaqueArchetype() const { | ||
|
@@ -637,13 +637,13 @@ class alignas(1 << TypeAlignInBits) TypeBase | |
/// Determine whether the type is an opened existential type with Error inside | ||
bool isOpenedExistentialWithError(); | ||
|
||
/// Retrieve the set of opened existential archetypes that occur | ||
/// within this type. | ||
void getOpenedExistentials(SmallVectorImpl<OpenedArchetypeType *> &opened); | ||
/// Retrieve the set of root opened archetypes that occur within this type. | ||
void getRootOpenedExistentials( | ||
SmallVectorImpl<OpenedArchetypeType *> &rootOpenedArchetypes) const; | ||
|
||
/// Erase the given opened existential type by replacing it with its | ||
/// existential type throughout the given type. | ||
Type eraseOpenedExistential(OpenedArchetypeType *opened); | ||
/// Replace opened archetypes with the given root with their most | ||
/// specific non-dependent upper bounds throughout this type. | ||
Type typeEraseOpenedArchetypesWithRoot(const OpenedArchetypeType *root) const; | ||
|
||
/// Given a declaration context, returns a function type with the 'self' | ||
/// type curried as the input if the declaration context describes a type. | ||
|
@@ -5536,7 +5536,8 @@ class ArchetypeType : public SubstitutableType, | |
/// primary archetype. | ||
ArchetypeType *getParent() const; | ||
|
||
/// Return the root archetype parent of this archetype. | ||
/// Return the archetype that represents the root generic parameter of its | ||
/// interface type. | ||
ArchetypeType *getRoot() const; | ||
|
||
/// Determine whether this is a root archetype within the environment. | ||
|
@@ -5773,6 +5774,12 @@ class OpenedArchetypeType final : public ArchetypeType, | |
/// Retrieve the opened existential type | ||
Type getOpenedExistentialType() const; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This function is a bit of a footgun, because even on a nested opened archetype it still returns the top-level existential type, rather than the erased type for this particular archetype. We probably want to do a quick audit of clients to ensure that they are only using this on the root archetype, and consider renaming the API ( There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Noticed this too; I will explore your suggestions in a follow-up. |
||
|
||
/// Return the archetype that represents the root generic parameter of its | ||
/// interface type. | ||
OpenedArchetypeType *getRoot() const { | ||
return cast<OpenedArchetypeType>(ArchetypeType::getRoot()); | ||
} | ||
|
||
static bool classof(const TypeBase *T) { | ||
return T->getKind() == TypeKind::OpenedArchetype; | ||
} | ||
|
@@ -6287,7 +6294,7 @@ BEGIN_CAN_TYPE_WRAPPER(PackExpansionType, Type) | |
END_CAN_TYPE_WRAPPER(PackExpansionType, Type) | ||
|
||
/// getASTContext - Return the ASTContext that this type belongs to. | ||
inline ASTContext &TypeBase::getASTContext() { | ||
inline ASTContext &TypeBase::getASTContext() const { | ||
// If this type is canonical, it has the ASTContext in it. | ||
if (isCanonical()) | ||
return *const_cast<ASTContext*>(Context); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was looking at this recently, and wondering whether the
GenericEnvironment
itself is a better discriminator than the root archetype for the long term. Right now, any opened existential always has a single generic parameter at the top level, but it's not inconceivable that we would want to allow matching existentials to structural types with type parameters, e.g.,x as <T, U>(T, U)
to open something as a 2-tuple. In such cases, the root no longer uniquely identifies the opened existential. We don't have to make this change to useGenericEnvironment
---your change here makes sure clients are properly reasoning about the roots so they handle nested archetypes properly, which is a huge step forward.