Skip to content

[awaiting evolution] Allow convenience initializers to reassign self. #19311

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

Closed

Conversation

jckarter
Copy link
Contributor

@jckarter jckarter commented Sep 14, 2018

Now that convenience initializers are implemented exactly the same as value type delegating initializers, it's straightforward to allow them to assign self to an existing object reference instead of only allowing them to chain to other initializers. Because convenience inits can be inherited, the formal type of self is still the dynamic Self type, however. This was handled unsoundly in Swift 4 mode, and unfortunately we can't fix it without breaking source in Swift 4 mode, so enable this feature only in Swift 5 mode.

Making self inout inside convenience inits also changes the code generation of loads from self, so we need to tweak DI's special handling of type(of: self) slightly so that it also recognizes this new pattern.

Proposal: swiftlang/swift-evolution#910

@jckarter
Copy link
Contributor Author

@swift-ci Please test

@swift-ci
Copy link
Contributor

Build failed
Swift Test OS X Platform
Git Sha - 12a5139bd4ebbfa2c5aeedf9d3c4341e94491c07

@@ -3098,7 +3098,7 @@ AnyFunctionType::Param swift::computeSelfParam(AbstractFunctionDecl *AFD,

if (auto *FD = dyn_cast<FuncDecl>(AFD)) {
isStatic = FD->isStatic();
isMutating = FD->isMutating();
isMutating = FD->isMutating() && !containerTy->hasReferenceSemantics();
Copy link
Contributor

Choose a reason for hiding this comment

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

This is unnecessary because isMutating() will never be true for a class method.

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 change it to an assertion.

if (!containerTy->hasReferenceSemantics()) {
isMutating = true;
} else if (Ctx.LangOpts.isSwiftVersionAtLeast(5)
&& !CD->isDesignatedInit()) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Would it be clearer to say CD->isConvenienceInit()?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If we ever expose factory inits as a user facing feature, they’d have the same behavior, wouldn’t they?

isInout = true;
// The `self` parameter of convenience initializers is considered 'inout'
// for semantic purposes in the AST, but at the ABI level is always
// passed by value in and returned out.
Copy link
Contributor

Choose a reason for hiding this comment

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

We'd only end up here when computing the lowered initializing entry point type right? In which case this check should not matter since we only do this for designated inits.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Convenience inits still have initializing entry points for ObjC interop. This is necessary so that the lowering for the ObjC thunk still works.

@swift-ci
Copy link
Contributor

Build failed
Swift Test Linux Platform
Git Sha - 12a5139bd4ebbfa2c5aeedf9d3c4341e94491c07

Now that convenience initializers are implemented exactly the same as value type delegating initializers, it's straightforward to allow them to assign self to an existing object reference instead of only allowing them to chain to other initializers. Because convenience inits can be inherited, the formal type of self is still the dynamic Self type, however. This was handled unsoundly in Swift 4 mode, and unfortunately we can't fix it without breaking source in Swift 4 mode, so enable this feature only in Swift 5 mode.

Making `self` inout inside convenience inits also changes the code generation of loads from self, so we need to tweak DI's special handling of type(of: self) slightly so that it also recognizes this new pattern.
@jckarter jckarter force-pushed the assigning-convenience-inits branch from 12a5139 to 26349dc Compare September 17, 2018 17:49
@CodaFi CodaFi added the swift evolution pending discussion Flag → feature: A feature that has a Swift evolution proposal currently in review label Nov 18, 2019
@CodaFi
Copy link
Contributor

CodaFi commented Nov 18, 2019

@jckarter I noticed you closed the evolution PR. Do you want this open too?

@jckarter
Copy link
Contributor Author

Sure, we can reopen it when we start actively working on it again.

@jckarter jckarter closed this Nov 18, 2019
ktoso added a commit to ktoso/swift that referenced this pull request Mar 16, 2021
ktoso added a commit to ktoso/swift that referenced this pull request Mar 20, 2021
@realityworks
Copy link

So, is this a dead evolution? There's plenty of people still waiting for this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
swift evolution pending discussion Flag → feature: A feature that has a Swift evolution proposal currently in review
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants