Skip to content

ASTPrinter: Mutability fixes for protocol stubs #24277

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 2 commits into from
Oct 25, 2019

Conversation

AnthonyLatsis
Copy link
Collaborator

@AnthonyLatsis AnthonyLatsis commented Apr 25, 2019

  • Don't print mutating in protocol stubs inside classes (this did happen to stubs for mutating requirements when the protocol and conformer were in different modules).
  • Print nonmutating for non-mutating setters in structs.

The AST printer would benefit from a better distinction between attributes and modifiers, but I think it is fine to implement it this way, for now :)

@AnthonyLatsis AnthonyLatsis force-pushed the mutability-proto-stubs branch from cfc0148 to b7d4f61 Compare April 25, 2019 19:32
@AnthonyLatsis
Copy link
Collaborator Author

cc @jrose-apple

@jrose-apple
Copy link
Contributor

This seems wrong: we do want to print mutating on stubs by default, because usually they don't have a sensible non-mutating implementation.

@AnthonyLatsis
Copy link
Collaborator Author

AnthonyLatsis commented Apr 25, 2019

I see, that makes sense. I got too carried away reasoning from a different perspective: that mutating (or, say, throws) on stubs could give the impression of being a mandatory modifier, when such requirements are often(«sometimes» is probably more accurate) expected to be understood as optional (spare flexibility). On the other hand, mutating methods with proper names should speak for themselves.

I will enable it on structs in a moment.

@jrose-apple
Copy link
Contributor

Enums too; it's classes that are special.

I think the stubs are supposed to be "a reasonable default", but I could see how they could be interpreted as "the minimum set of requirements".

@AnthonyLatsis AnthonyLatsis force-pushed the mutability-proto-stubs branch 2 times, most recently from d77dbf7 to 0173e1e Compare April 26, 2019 13:43
@AnthonyLatsis
Copy link
Collaborator Author

@jrose, do you approve?

Copy link
Contributor

@jrose-apple jrose-apple left a comment

Choose a reason for hiding this comment

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

Thanks for working on this!

if (isClass)
Options.ExcludeAttrList.push_back(DAK_Mutating);
// Struct methods are non-mutating be default.
if (isClass || !isa<AbstractStorageDecl>(Requirement))
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think this qualification is necessary. You're not allowed to write nonmutating on a non-accessor anyway. May as well just put both conditions under isClass.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

You're not allowed to write nonmutating on a non-accessor anyway

Am I? nonmutating is allowed on protocol method requirements, which makes sense, but it appears we can also write it on value type methods in Swift 5, which is obviously redundant.

Copy link
Contributor

Choose a reason for hiding this comment

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

Um. It doesn't even make sense for protocol requirements, but you're right that it's not rejected. I did not realize that.

Copy link
Collaborator Author

@AnthonyLatsis AnthonyLatsis May 4, 2019

Choose a reason for hiding this comment

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

It doesn't even make sense for protocol requirements

Oh, right, of course.

@@ -2657,6 +2657,16 @@ printRequirementStub(ValueDecl *Requirement, DeclContext *Adopter,
Options.FunctionDefinitions = true;
Options.PrintAccessorBodiesInProtocols = true;

bool isClass = AdopterTy->is<ClassType>();
Copy link
Contributor

Choose a reason for hiding this comment

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

This will only be true for non-generic classes. A simpler way to check is AdopterTy->getSelfClassDecl() != nullptr.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Oops, ClassType is indeed misleading, thanks!

@@ -0,0 +1,4 @@
public protocol ExternalMutabilityProto {
mutating func foo()
subscript() -> Int { get nonmutating set }
Copy link
Contributor

Choose a reason for hiding this comment

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

If you want to be extra thorough, you could check how mutating get prints as well.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I also noticed that we never print accessors for property requirements, even when the getter is required to be mutating or the setter - non-mutating. Imagine how confusing a conformance error can be in the non-mutating case.

Copy link
Contributor

Choose a reason for hiding this comment

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

The getter can't be required to be mutating, just allowed to be mutating. But the setter case would force you into a computed property, and so the stubs for that could include the computed property structure. Let's save that for another PR, though.

@@ -2768,7 +2768,7 @@ void PrintAST::visitFuncDecl(FuncDecl *decl) {
if (!Options.SkipIntroducerKeywords) {
if (decl->isStatic() && Options.PrintStaticKeyword)
printStaticKeyword(decl->getCorrectStaticSpelling());
if (decl->isMutating() && !decl->getAttrs().hasAttribute<MutatingAttr>()) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this part not relevant? I assumed it kept mutating from being printed twice in some cases.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Not anymore I believe, since I chose to skip mutability modifiers in printAttributes.

Copy link
Contributor

Choose a reason for hiding this comment

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

FYI this caused interface generation to print mutating mutating for explicitly mutating functions, because the changes made to printAttributes only applied to implicit attributes. Fixed: #30183

@jrose-apple
Copy link
Contributor

@swift-ci Please test

@swift-ci
Copy link
Contributor

swift-ci commented May 6, 2019

Build failed
Swift Test Linux Platform
Git Sha - 0173e1edb017d6038e5ec48129237cf275b3b434

@swift-ci
Copy link
Contributor

swift-ci commented May 6, 2019

Build failed
Swift Test OS X Platform
Git Sha - 0173e1edb017d6038e5ec48129237cf275b3b434

@jrose-apple
Copy link
Contributor

:-( Looks like the duplicate mutating was a problem after all.

@AnthonyLatsis AnthonyLatsis force-pushed the mutability-proto-stubs branch from 589d66a to 6f119b0 Compare October 25, 2019 15:31
@AnthonyLatsis
Copy link
Collaborator Author

Not anymore I believe, since I chose to skip mutability modifiers in printAttributes.

@jrose Turns out I forgot to skip them for functions as well. I don't know which tests failed now that the job is gone, though. Let's see if the duplication is still present?

@theblixguy
Copy link
Collaborator

@swift-ci please test

@jrose-apple
Copy link
Contributor

jrose-apple commented Oct 25, 2019

Looks pretty good now. Are there already tests for mutating get in a requirement, which…could probably go either way.

@AnthonyLatsis
Copy link
Collaborator Author

AnthonyLatsis commented Oct 25, 2019

Yes, though I do print mutating for both getters and methods, because they are both "allowed to be mutating" in that case.

@swift-ci
Copy link
Contributor

Build failed
Swift Test OS X Platform
Git Sha - 6f119b0

@jrose-apple
Copy link
Contributor

That LLDB test was recently disabled, let's go again.

@swift-ci Please smoke test macOS

@AnthonyLatsis
Copy link
Collaborator Author

AnthonyLatsis commented Mar 3, 2020

Fix double-printing mutating on interface generation: #30011
Sorry about that :-/

@AnthonyLatsis AnthonyLatsis deleted the mutability-proto-stubs branch February 17, 2022 21:01
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.

5 participants