Skip to content

Add type metadata for extended existential types #42047

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

Merged
merged 5 commits into from
Mar 28, 2022

Conversation

rjmccall
Copy link
Contributor

The immediate use case is only concretely-constrained existential types, which could use a much simpler representation, but I've future-proofed the representation as much as I can; thus, the requirement signature can have arbitrary parameters and requirements, and the type can have an arbitrary type as the sub-expression. The latter is also necessary for existential metatypes.

The chief implementation complexity here is that we must be able to agree on the identity of an existential type that might be produced by substitution. Thus, for example, any P<T> when T == Int must resolve to the same type metadata as any P<Int>. To handle this, we identify the "shape" of the existential type, consisting of those parts which cannot possibly be the result of substitution, and then abstract the substitutable "holes" as an application of a generalization signature. That algorithm will come in a later patch; this patch just represents it.

Uniquing existential shapes from the requirements would be quite complex because of all the symbolic mangled names they use. This is particularly true because it's not reasonable to require translation units to agree about what portions they mangle vs. reference symbolically. Instead, we expect the compiler to do a cryptographic hash of a mangling of the shape, then use that as the unique key identifying the shape.

@rjmccall rjmccall force-pushed the extended-existential-type-metadata branch from 84e97bd to d84b32b Compare March 27, 2022 08:29
@rjmccall
Copy link
Contributor Author

@swift-ci Please test

The vast majority of generic parameters follow a simple pattern
(type parameter that defines a key argument), which we can take
advantage of to avoid actually representing them in type metadata:
if all the type arguments is the simple pattern, and there's not
more than some preset number, simply use a pre-allocated array in
the runtime.

Actually doing this for generic types will require some care around
back-deployment, as well as finding a bit to store that we've done
it.  But we can at least start doing this for new ABI, such as the
extended existential shape descriptors.
When we adopt C++17, we'll be able to do this with a fold expression,
but this will be useful in the meantime.
@rjmccall rjmccall force-pushed the extended-existential-type-metadata branch from d84b32b to 57e27d5 Compare March 27, 2022 19:33
@rjmccall
Copy link
Contributor Author

@swift-ci Please test

@rjmccall
Copy link
Contributor Author

@swift-ci Please test Windows

Some parts of the type metadata system are difficult to unit-test
because they rely on structures that contain relative references,
which the C compiler cannot generate.  We have traditionally just
relied on integration testing with the compiler.  For constrained
existentials, I wanted to do better, so I spent a few days hacking
up this little system which can generate graphs of objects with
relative references to one another.

Currently it's missing the ability to generate a lot of things
which I didn't need in order to adequately test the metadata
system for constrained existentials.
The immediate use case is only concretely-constrained existential
types, which could use a much simpler representation, but I've
future-proofed the representation as much as I can; thus, the
requirement signature can have arbitrary parameters and
requirements, and the type can have an arbitrary type as the
sub-expression.  The latter is also necessary for existential
metatypes.

The chief implementation complexity here is that we must be able
to agree on the identity of an existential type that might be
produced by substitution.  Thus, for example, `any P<T>` when
`T == Int` must resolve to the same type metadata as
`any P<Int>`.  To handle this, we identify the "shape" of the
existential type, consisting of those parts which cannot possibly
be the result of substitution, and then abstract the substitutable
"holes" as an application of a generalization signature.  That
algorithm will come in a later patch; this patch just represents
it.

Uniquing existential shapes from the requirements would be quite
complex because of all the symbolic mangled names they use.
This is particularly true because it's not reasonable to require
translation units to agree about what portions they mangle vs.
reference symbolically.  Instead, we expect the compiler to do
a cryptographic hash of a mangling of the shape, then use that
as the unique key identifying the shape.

This is just the core representation and runtime interface; other
parts of the runtime, such as dynamic casting and demangling
support, will come later.
@rjmccall rjmccall force-pushed the extended-existential-type-metadata branch from 57e27d5 to 148357f Compare March 27, 2022 22:24
@rjmccall
Copy link
Contributor Author

@swift-ci Please test

@rjmccall
Copy link
Contributor Author

@swift-ci Please test Windows

@rjmccall rjmccall merged commit c3c9b1b into swiftlang:main Mar 28, 2022
@rjmccall rjmccall deleted the extended-existential-type-metadata branch March 28, 2022 03:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant