-
Notifications
You must be signed in to change notification settings - Fork 10.6k
[Sema] Catch use-before-declarations in nested closures #85535
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
base: main
Are you sure you want to change the base?
Conversation
| // In principle we could allow these, but it's simpler to just reject them. | ||
| let x = z // expected-error {{use of local variable 'z' before its declaration}} | ||
| let y = { z } // expected-error {{use of local variable 'z' before its declaration}} | ||
| var z: Int { 0 } // expected-note 2{{'z' declared 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.
x here was already illegal, this change also makes y illegal. In principle we could allow forward references for computed vars, but I think it's much better to have a consistent behavior for all variables.
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 think that makes sense as well!
8daf900 to
9f849a5
Compare
Previously we would allow these in Sema and diagnose them in SILGen, but allowing them in Sema is unsound because it means the constraint system ends up kicking interface type requests for declarations that should be type-checked as part of the closure itself. Adjust the name lookup logic to look through parent closures when detecting invalid forward references. For now we don't fallback to an outer result on encountering a use-before-declaration to preserve the current behavior. I'm planning on changing that in the next commit though. rdar://74430478
If we encounter a variable declared after its use within a closure, we can fallback to using an outer result if present. This matches the behavior outside of a closure and generally seems more consistent with the behavior we have if we also find an inner result. rdar://163656720
9f849a5 to
2f0dee4
Compare
|
@swift-ci please test macOS |
|
@swift-ci please test Linux |
|
@swift-ci please test Windows |
|
@swift-ci please test source compatibility |
| // In principle we could allow these, but it's simpler to just reject them. | ||
| let x = z // expected-error {{use of local variable 'z' before its declaration}} | ||
| let y = { z } // expected-error {{use of local variable 'z' before its declaration}} | ||
| var z: Int { 0 } // expected-note 2{{'z' declared 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.
I think that makes sense as well!
Previously we would allow these in Sema and diagnose them in SILGen, but allowing them in Sema is unsound because it means the constraint system ends up kicking interface type requests for declarations that should be type-checked as part of the closure itself. Adjust the name lookup logic to look through parent closures when detecting invalid forward references. This then allows us to have consistent shadowing behavior inside and outside of closures.
Forum post: https://forums.swift.org/t/ensuring-forward-references-to-local-variables-are-consistently-rejected/83265
rdar://74430478
rdar://163656720