-
Notifications
You must be signed in to change notification settings - Fork 10.6k
[CodeComplete] Default parameter names of completed closure to internal names #36551
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
Conversation
|
I guess, at least, you need to change |
783de20 to
d977ac1
Compare
|
OK, I have done a 180º turnaround. After sleeping over it, I figured the internal names really have nothing to do in the type system because they don’t describe a function’s type. Instead, I discovered that we still keep the internal names around in the parameters |
d977ac1 to
53ea176
Compare
|
OK, 180º turnaround again to the way I was facing before. Turns out my initial implementation was nearly there and I was just confused because a whole bunch of the test suite failed on my machine, but I didn’t realize that was because it was already failing for my local setup on So, internal names are again part of the type system and are cleared when canonicalizing the type. @swift-ci Please test |
53ea176 to
65aa5a0
Compare
include/swift/AST/Types.h
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps we don't need this, thus we don't need equalsIgnoringInternalName() as well?
getPlainType()->isEqual(b.getPlainType()) compares canonical types anyway (so arg: Array<T> "equals to" arg: [T]) I think we don't need to check "identical" here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would definitely work, but I thought it’s unintuitive if the == operator silently ignores one of the properties altogether, that’s why I went with the dedicated method.
Thinking about this some more, I think we should
a) make == check for strict equality without canonicalizing types (or remove it entirely) and provide equals functions that check the various forms of equality a Param can take or
b) accept that == that the definition of == is a bit sloppy, embrace it, don’t check for InternalLabel and add a doc comment describing the catches.
I can see advantages in either approach (clearer semantics in (a) but more concise syntax in (b)). I think I tend to lean towards (a) but don’t have too strong feelings about it. Do you @rintaro?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd suggest (b) for this PR. Here's the reasoning: Considering Type::operator== is delete we probably should delete AnyFunctionType::Param::operator== as well and make isEqual which compares "canonical" forms of the values. But, that also applies to AnyFunctionType::Yield::operator==. I don't think we should do it in this PR because AnyFunctionType::Yield is unrelated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good to me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After looking into it some more, I agree that ignoring the internal name in operator== is absolutely the right choice. I wasn’t aware that we are always using canonical types in operator== for types and that it’s rather more difficult to compare the sugared types. As such, ignoring the internal name in Param::operator== follows the current paradigm.
65aa5a0 to
f796af7
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks good to me. We still need serialization support for this. Do you intend to do it in followups?
lib/AST/ASTContext.cpp
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
isGenericFunctionTypeCanonical as well?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, I didn't realize there was isGenericFunctionTypeCanonical. Added it there as well and renamed isFunctionTypeCanonical to isAnyFunctionTypeCanonical (with Any) to imply there is a generic version as well.
…al names
If have a function that takes a trailing closure as follows
```
func sort(callback: (_ left: Int, _ right: Int) -> Bool) {}
```
completing a call to `sort` and expanding the trailing closure results in
```
sort { <#Int#>, <#Int#> in
<#code#>
}
```
We should be doing a better job here and defaulting the trailing closure's to the internal names specified in the function signature. I.e. the final result should be
```
sort { left, right in
<#code#>
}
```
This commit does exactly that.
Firstly, it keeps track of the closure's internal names (as specified in the declaration of `sort`) in the closure's type through a new `InternalLabel` property in `AnyFunctionType::Param`. Once the type containing the parameter gets canonicalized, the internal label is dropped.
Secondly, it adds a new option to `ASTPrinter` to always try and print parameter labels. With this option set to true, it will always print external paramter labels and, if they are present, print the internal parameter label as `_ <internalLabel>`.
Finally, we can use this new printing mode to print the trailing closure’s type as
```
<#T##callback: (Int, Int) -> Bool##(_ left: Int, _ right: Int) -> Bool#>
```
This is already correctly expanded by code-expand to the desired result. I also added a test case for that behaviour.
f796af7 to
865e80f
Compare
|
@swift-ci Please smoke test |
I’ll look into it in a follow-up PR. |
|
@swift-ci Please smoke test |
1 similar comment
|
@swift-ci Please smoke test |
|
@swift-ci Please smoke test Windows |
|
Windows failures is unrelated. Merging. |
| // RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=CLOSURE_PARAM_WITH_INTERNAL_NAME | %FileCheck %s -check-prefix=CLOSURE_PARAM_WITH_INTERNAL_NAME | ||
| // RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=CLOSURE_PARAM_WITH_PARENS | %FileCheck %s -check-prefix=CLOSURE_PARAM_WITH_PARENS | ||
| // RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=OPTIONAL_CLOSURE_PARAM | %FileCheck %s -check-prefix=OPTIONAL_CLOSURE_PARAM | ||
| // RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=ESCAPING_OPTIONAL_CLOSURE_PARAM | %FileCheck %s -check-prefix=ESCAPING_OPTIONAL_CLOSURE_PARAM | ||
| // RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=COMPLETE_CLOSURE_PARAM_WITHOUT_INTERNAL_NAMES | %FileCheck %s -check-prefix=COMPLETE_CLOSURE_PARAM_WITHOUT_INTERNAL_NAMES | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Didn’t notice this when rebasing. Thanks. I’ve set up a PR here: #36796
If have a function that takes a trailing closure as follows
completing a call to
sortand expanding the trailing closure results inWe should be doing a better job here and defaulting the trailing closure's to the internal names specified in the function signature. I.e. the final result should be
This commit does exactly that.
Firstly, it keeps track of the closure's internal names (as specified in the declaration of
sort) in the closure's type through a newInternalLabelproperty inAnyFunctionType::Param. Once the type containing the parameter gets canonicalized, the internal label is dropped.Secondly, it adds a new option to
ASTPrinterto always try and print parameter labels. With this option set to true, it will always print external paramter labels and, if they are present, print the internal parameter label as_ <internalLabel>.Finally, we can use this new printing mode to print the trailing closure’s type as
This is already correctly expanded by code-expand to the desired result. I also added a test case for that behaviour.