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
[SR-13100] Improved diagnostics for type errors around mutating methods #55546
Comments
This is a great suggestion! I can see how this could be confusing. [Guesswork follows, possibly incorrect suggestion] Perhaps we could special-case the situation of "cannot assign value of type |
@swift-ci create |
[Note: In case you want to mark this as a StarterBug, let's have a discussion on the wording before marking it as such.] |
Comment by Nikhil (JIRA) theindigamer (JIRA User) I would like to take the plunge myself to fix it as you would suggest (with the wording and all) This is my first time, so please guide me with the starting steps. Thanks. |
You can start by installing Xcode 12 beta (if you are on macOS) or the appropriate dependencies (if you are on Linux) and building the project over the weekend. You can see the project README for detailed instructions. Some other things to do in the meantime would be to:
cc @hborla – can you suggest next steps? I can't tell how we could obtain the contextual information needed to emit this specialized diagnostic. |
Comment by Nikhil (JIRA) theindigamer (JIRA User) Thank you. Will work on the steps provided. |
Comment by Nikhil (JIRA) I have been working on build, I have cloned master and did update checkout on my macOS 10.15.5. EDIT: Build is successful.There is no scheme "swift" in the list, will check. Also, I have narrowed down the code which is emitting our diagnostic in question to class ContextualFailure::diagnoseAsError() in CSDiagnostics.cpp. |
Comment by Nikhil (JIRA) I have debugged the issue and narrowed it down to IgnoreAssignmentDestinationType::diagnose Will try to guess something for I can't tell how we could obtain the contextual information needed to emit this specialized diagnostic. |
Yeah, the schemes have changed slightly around since that talk. There should be a |
Comment by Nikhil (JIRA) theindigamer (JIRA User) this is itching me for sometime now. I have tried various ways to narrow the “from type” to a mutating method like trying out (crude?) things like getting method parameters, checking for curriedself parameter etc. |
I think the current diagnostic is okay. "Mutating functions don't return their types" is not correct, because a mutating function can return any type. For example, this is valid: struct S {
var value = 0
mutating func foo() -> Self { // returns a value of type 'S'
value = 1
return self
}
} |
Although, maybe we can reword the diagnostic, something like It's a lot more verbose though, but perhaps more beginner friendly. |
Anyhow, to answer your original question - a mutating function has a |
I agree with the point in the Jira that the current diagnostic is not okay. Especially if you are coming from C, C++ or ObjC, where you are not used to void being inhabited (but Swift's Void has 1 inhabitant). Moreover, Swift allows you to omit func f(_ s: inout String) {
let newString = s.append("AAA"); // warning: constant 'newString' inferred to have type '()', which may be unexpected
} This warning appears when the value being assigned to does not have a user-annotated type. Given that, I think the special case to go for here would be: if the RHS has a call to a Void-returning mutating method and the LHS does not have a user-annotated type of 1. emit a special case diagnostic, perhaps something like 2. emit a fix-it removing the assignment operation altogether. The fix-it would also fire in cases like the warning example above. |
Hmm, okay. I was thinking more generally, but I think your suggested special-case diagnostic would be good to add! Should there be some special case fix-its too for common standard library mutating methods? For example, |
I think it would be really nice to map standard library mutating methods to their functional/nonmutating variants to provide a second Fix-It to call the nonmutating one instead! However, I think that's outside the scope of a starter bug, so perhaps we should file a separate issue for that. As for the new error message, I think this warrants two tailored messages. I think saying str = str.appending("in Swift!")
^
error: cannot assign result of Void-returning [function/method] to type 'String'
str = str.appending("in Swift!")
^
note: 'appending' is a mutating method on 'String'; it does not return a new 'String' with the Fix-Its attached to the note? |
Comment by Nikhil (JIRA) I think @hborla 's approach covers all the three well:
Shall we lock this? |
Yeah, I think the combination of tweaked error message + note would be nice! And we could create a new ticket to track adding fix-it to suggest changing from calling mutating to non-mutating variant of the functions... |
hassaneldesouky (JIRA User) looks like this is available to work on! |
Comment by Hassan ElDesouky (JIRA) @hborla Thank you, I'll take a look at it. |
Comment by Hassan ElDesouky (JIRA) saidhon (JIRA User) You can take this if you want, I have a tight schedule so I haven't started in it, yet. |
Additional Detail from JIRA
md5: 3f46935b710dffa0229fe32db2afcdf0
Issue Description:
While working with mutating methods like append(), we get a less than obvious diagnostic
For example,
For the second line, compiler throws an error:
cannot assign value of type '()' to type 'String'
This is confusing for beginners like me. The error diagnostic can be something like
"Mutating functions don't return their types"
Or something better.
Thanks,
Nikhil.
The text was updated successfully, but these errors were encountered: