Skip to content

Conversation

@aschwaighofer
Copy link
Contributor

Still missing is casting from existential to concrete type (the only we will initially support) and a bigger set of types (e.g foreign types).

Allow storing struct, enum, and tuple types in an any.
We need to add a version of swift_allocBox to the embedded runtime implementation for outline storage
Code using the outline heap storage path will crash and burn because
support is incomplete. But at least inline storage existential
inhabitants should compile and run.
@aschwaighofer aschwaighofer requested review from a team, compnerd and rjmccall as code owners November 17, 2025 22:53
@aschwaighofer
Copy link
Contributor Author

@swift-ci test

@aschwaighofer
Copy link
Contributor Author

We will also need: #85426

concreteType, TypeMetadataAddress::FullMetadata));

if (Context.LangOpts.hasFeature(Feature::Embedded)) {
if (Context.LangOpts.hasFeature(Feature::Embedded) ) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unnecessary insertion of ' '


inline bool isEmbeddedWithoutEmbeddedExitentials(CanType t) {
return t->getASTContext().LangOpts.hasFeature(Feature::Embedded) &&
!t->getASTContext().LangOpts.hasFeature(Feature::EmbeddedExistentials);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's best to pull out the ASTContext only once

// reasons to continue using "generic" value witness table functions i.e the
// same once used for runtime instantiated generic metadata.
if (!IGM.Context.LangOpts.hasFeature(Feature::EmbeddedExistentials)) {
if (auto boundGenericType = dyn_cast<BoundGenericType>(abstractType)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is this code used for? It's already wrong if you have a non-generic type nested in a generic one, like

struct G<T> {
  struct Inner {}
}

Something like G<Int>.Inner is not a BGT

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is pre-existing code.

It is "safe" to fail the check on G<Int>.Inner or any type for that matter:

We can generate value witness tables for generic metadata patterns or for specialized generic metadata.

When we added the ability to generate specialized metadata initially the code would generate specialized value witnesses (i.e a value witness that knows self is e.g G<Int>).
That lead to undesired code bloat. So when we see a G<Int> the code behind that check makes it such that we lower the value witness under the assumption that self is G<T> (except for the the non-function witnesses such size, flags, stride).

When we fail that check we will use "specialized value witness functions" i.e. functions that "know" that the type is G<Int>.Inner rather than the ones we would use for the generic case (G<T>.Inner).
That comes at the cost of code size but is not incorrect.

This code path is only exercised if you compile with specialized generic metadata on (we only do this behind a flag / in the standard library).

Do you have to walk the parent chain to detect a bound generic type in the ancestry or is there an API?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TypeBase::isSpecialized() returns true if the type itself or any parent is a BGT. Do you mind fixing this and adding a test case? Subsequent PR is totally fine of course.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll take a look

IRGenFunction::emitTypeMetadataRef(CanType type,
DynamicMetadataRequest request) {
if (type->getASTContext().LangOpts.hasFeature(Feature::Embedded) &&
!type->getASTContext().LangOpts.hasFeature(Feature::EmbeddedExistentials) &&
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's better to pull the ASTContext out only once into a local variable. Also there's a third usage below you could simplify

@aschwaighofer
Copy link
Contributor Author

@swift-ci test

@aschwaighofer
Copy link
Contributor Author

@swift-ci test linux

@aschwaighofer aschwaighofer merged commit 17447a3 into swiftlang:main Nov 18, 2025
5 checks passed
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.

2 participants