Skip to content

[6.0] Consistently treat let properties as immutable within the type checker #73664

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

DougGregor
Copy link
Member

Explanation: Rework our handling of let properties so that they are treated as rvalues uniformly except when they are being assigned to. This moves the inout/mutating checking up into the type checker, whereas it was previously handled at a later stage in Definite Initialization. This change allows overload resolution to correctly reject a call to a mutable function on a let property in an initializer, and therefore choose another option, which is a more appropriate way to model the language semantics.
Original PR: #73609
Radar/issue: rdar://127258363, a source compatibility issue with AsyncIteratorProtocol.next()'s default implementation that required this semantic improvement.
Risk: Medium-low. This changes the modeling of references to let instance properties within an initializer and uninitialized local let properties within the type checker to make them rvalues unless they're the target of an assignment (in which case they remain lvalues). The type checker, however, still creates an AST that treats them as lvalues (that are immediately loaded), because later compiler passes (SILGen and DI) expect this modeling. The overall effect is expected to be very small, and should only serve to make some ill-formed programs (where the type checker picked a mutable function on an lvalue) well-formed or diagnose in an earlier phase of the compiler.
Reviewed by: @xedin

…value

This operation determines whether a particular storage declaration,
when accessed from a particular location, is mutable or not. It has a
particular semantic that `let` declarations, when accessed from an
initializer, are considered mutable even though they can only be
assigned. There is similar logic for init accessors.

Tease apart "truly mutable" from "initializable because we're in an
initializer", introducing AbstractStorageDecl::mutability() to
represent all three states. isSettable() remains available as a thin
shim over mutability() and all clients are unchanged thus far, making
this a no-op refactoring.
Stored `let` properties of a struct, class, or actor permit
'inout' modification within the constructor body after they have been
initialized. Tentatively remove this rule, only allowing such `let`
properties to be initialized (assigned to) and not treated as `inout`.

Fixes rdar://127258363.
…nces as lvalues

As we do with references to initializable local lets, teach the type
checker to produce ASTs where member references to initializable
instance property lets (e.g., within an initializer) treat the `let`
as an lvalue and then immediately load.

This modeling addresses a source compatibility issue uncovered in
swift-syntax, where code that *technically* has a
use-before-definition on a `let` property in an initializer wasn't
diagnosed as such because the loaded value wasn't actually used for
anything.
@DougGregor DougGregor requested a review from a team as a code owner May 16, 2024 04:48
@DougGregor
Copy link
Member Author

@swift-ci please test

@DougGregor DougGregor merged commit 1c3b994 into swiftlang:release/6.0 May 16, 2024
5 checks passed
@DougGregor DougGregor deleted the instance-let-not-inout-in-initializer-6.0 branch May 16, 2024 15:50
nate-chandler added a commit to nate-chandler/swift that referenced this pull request May 31, 2024
The flag had been used in
test/SILOptimizer/definite_init_inout_super_init.swift because SILGen
generated invalid SIL which would only be diagnosed during DI.  Thanks
to swiftlang#73664 , this is diagnosed before
SILGen.

One other test case use (test/PrintAsObjC/extensions.swift) remains.
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.

2 participants