Skip to content

Conversation

@calda
Copy link
Contributor

@calda calda commented Oct 16, 2022

This proof-of-concept PR adds support for defining stored properties in extensions, as long as the extension is defined in the same file as the type being extended. For example:

struct Foo {
  let bar: String
}

extension Foo {
  let baaz: Int
}

_ = Foo(bar: "bar", baaz: "baaz")

Here's a pitch thread on the Evolution forums for this change: Allow stored properties in extensions

if (isStoredPropertyInitializer())
decl = cast<NominalTypeDecl>(decl->getDeclContext());
if (isStoredPropertyInitializer()) {
if (auto extension = dyn_cast<ExtensionDecl>(decl->getDeclContext())) {
Copy link
Contributor

@slavapestov slavapestov Oct 17, 2022

Choose a reason for hiding this comment

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

decl->getDeclContext()->getSelfNominalTypeDecl()

Copy link
Contributor Author

Choose a reason for hiding this comment

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

aha very helpful, thanks!

if (isStoredPropertyInitializer() || (isPropertyWrapperBackingInitializer() &&
d->getDeclContext()->isTypeContext())) {
auto *nominal = cast<NominalTypeDecl>(d->getDeclContext());
NominalTypeDecl *nominal;
Copy link
Contributor

Choose a reason for hiding this comment

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

See above

// Stored properties in extensions within the same file are added
// as members to the defining type, so we shouldn't assert in that
// case
|| DC->getContextKind() == DeclContextKind::ExtensionDecl);
Copy link
Contributor

Choose a reason for hiding this comment

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

DC->getSelfNominalTypeDecl() == TheStruct->getAnyNominal()

// Stored properties in extensions within the same file are
// added as members to the defining type, so we shouldn't assert
// in that case
|| DC->getContextKind() == DeclContextKind::ExtensionDecl,
Copy link
Contributor

Choose a reason for hiding this comment

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

Same here

NominalTypeDecl *nominal) {
auto subs = getSubstitutionsForPropertyInitializer(dc, nominal);

// open question: is there a good "ordered set" type we could use
Copy link
Contributor

Choose a reason for hiding this comment

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

llvm::MapVector

Copy link
Contributor Author

Choose a reason for hiding this comment

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

thanks!


if (auto *structDecl = dyn_cast<StructDecl>(field->getDeclContext())) {
NominalTypeDecl *nominal;
if (auto extension = dyn_cast<ExtensionDecl>(field->getDeclContext())) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Ditto

auto *varPattern = pbd->getPattern(i);
// A type can also have stored properties that aren't direct members,
// e.g. if they were defined in an extension.
for (auto storedProperty : nominal->getStoredProperties()) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Do you still need the first loop over the members?

// Types can have stored properties that aren't included in
// `getABIMembers()`, so we have to handle those manually
for (VarDecl *VD : theType->getStoredProperties()) {
if (!visitedVarDecls.count(VD)) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Instead of using a set here, you can just skip stored properties in the first loop

@calda calda closed this Oct 24, 2022
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