Skip to content

Conversation

@hamishknight
Copy link
Contributor

@hamishknight hamishknight commented Nov 17, 2025

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

Comment on lines +212 to +215
// 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}}
Copy link
Contributor Author

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.

Copy link
Contributor

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!

@hamishknight hamishknight force-pushed the penumbra branch 2 times, most recently from 8daf900 to 9f849a5 Compare November 17, 2025 14:33
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
@hamishknight
Copy link
Contributor Author

@swift-ci please test macOS

@hamishknight
Copy link
Contributor Author

@swift-ci please test Linux

@hamishknight
Copy link
Contributor Author

swiftlang/swift-docc#1352

@swift-ci please test Windows

@hamishknight
Copy link
Contributor Author

@swift-ci please test source compatibility

Comment on lines +212 to +215
// 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}}
Copy link
Contributor

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!

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.

3 participants