Commit Graph

62 Commits

Author SHA1 Message Date
Joe Groff
de687db20f Disallow consuming self in a noncopyable deinit again.
The changes to allow for partial consumption unintentionally also allowed for
`self` to be consumed as a whole during `deinit`, which we don't yet want to
allow because it could lead to accidental "resurrection" and/or accidental
infinite recursion if the consuming method lets `deinit` be implicitly run
again. This makes it an error again. The experimental feature
`ConsumeSelfInDeinit` will allow it for test coverage or experimentation
purposes. rdar://132761460
2024-07-29 21:20:14 -07:00
Tim Kientzle
1d961ba22d Add #include "swift/Basic/Assertions.h" to a lot of source files
Although I don't plan to bring over new assertions wholesale
into the current qualification branch, it's entirely possible
that various minor changes in main will use the new assertions;
having this basic support in the release branch will simplify that.
(This is why I'm adding the includes as a separate pass from
rewriting the individual assertions)
2024-06-05 19:37:30 -07:00
Nate Chandler
23e7c36c5f [NoncopyablePartialConsumption] Ungate feature.
Remove all checks for the feature flag.  It's on all the time.
2024-04-19 12:37:34 -07:00
Andrew Trick
a99ea62339 Fix MoveOnlyDiagnostics, ConsumOperator...Checkers diagnostics
Emitting a note with an invalid source location is actively
harmful. It confuses users and tools, makes it impossible to write
unit tests. In this case, the note simply says "use here", so it's
completely free of information without the source location.
2024-03-27 13:42:25 -07:00
Ben Barham
ef8825bfe6 Migrate llvm::Optional to std::optional
LLVM has removed llvm::Optional, move over to std::optional. Also
clang-format to fix up all the renamed #includes.
2024-02-21 11:20:06 -08:00
Nate Chandler
da968dbd58 [MoveChecker] Ban exported partial consumption.
To avoid dialecticization based on compilation mode, ban for
non-resilient modules partial consumption of aggregates which would be
illegal were those modules instead resilient.
2024-02-15 16:25:53 -08:00
Nate Chandler
6e1410d0c6 [NFC] MoveChecker: Produce value from switch.
Rather than using a different value and doing the same thing on each
branch.
2024-02-15 09:08:53 -08:00
Michael Gottesman
a569160f21 [sil] Refactor out the variable name inferer from MoveOnlyDiagnostics.cpp -> VariableNameUtils.
I am going to reuse this for TransferNonSendable. In the process I made a few
changes to make it more amenable to both use cases and used the current set of
tests that we have for noncopyable types to validate that I didn't break
anything.
2024-02-06 13:42:35 -08:00
Nate Chandler
03f904af0c [MoveChecker] Separate partial reinit from consume 2024-01-29 18:29:40 -08:00
Nate Chandler
5441ff1d97 [MoveChecker] Distinguished scope end diagnostics.
There are several kinds of scopes at which it is required that an
address be initialized:
(1) the whole function -- for inout argument to the function
(2) the region a coroutine is active -- for an inout yielded by a
    coroutine into the function
(3) the region of a memory access -- for a `begin_access [modify]`.

The move checker enforces that they are initialized at that point by
adding instructions at which the field must be live to liveness.

Previously, all such scopes used the end of the function as the point at
which the memory had to have been reinitialized.  Here, the relevant end
of scope markers are used instead.

More importantly, here the diagnostic is made to vary--the diagnostic,
that is, that is issued in the face an address not being initialized at
the end of these different kind of scopes.
2024-01-29 11:49:30 -08:00
Nate Chandler
4ea2440bfe [NFC] MoveChecker: Merged partial mutation checks.
Simplified diagnostic emission to use a single code path.
2024-01-29 11:49:30 -08:00
Joe Groff
ba7abd0dd9 SIL: Get addressor property names for display in move checker diagnostics. 2023-12-20 16:20:48 -08:00
Joe Groff
02800046c6 Look through copy_addr and opened existentials to diagnose move-only sources. 2023-12-15 16:36:09 -08:00
Joe Groff
96c87dbf81 Move-only-check the yielded result from read coroutines when they're noncopyable.
Mark the result of starting a read coroutine to be checked by the move-only checker, and then
update the pattern matching in the move checker itself so that it recognizes code patterns
involving yielding from and receiving yields from read coroutines. Teach move only diagnostics
to get the property name for an access through a read coroutine from the referenced declaration.
2023-12-11 10:54:52 -08:00
Hamish Knight
6ee44f09b4 Introduce then statements
These allow multi-statement `if`/`switch` expression
branches that can produce a value at the end by
saying `then <expr>`. This is gated behind
`-enable-experimental-feature ThenStatements`
pending evolution discussion.
2023-09-01 14:32:14 +01:00
Michael Gottesman
37d60a08bb [move-only] Rename mark_must_check -> mark_unresolved_non_copyable_value.
I was originally hoping to reuse mark_must_check for multiple types of checkers.
In practice, this is not what happened... so giving it a name specifically to do
with non copyable types makes more sense and makes the code clearer.

Just a pure rename.
2023-08-30 22:29:30 -07:00
Kavon Farvardin
da4951b922 noncopyable diagnostics fix to correct error message wording
Turns out if you write `_ = consume s` you get different enough
SIL than `_ = s` that it fools the ad-hoc test for whether we've
mark-must-check'd a closure capture, since the former will have
a begin_access. There doesn't appear to be a simple way to reuse
the existing information or checking routine for this that was
used by the checker itself to flag this.
2023-07-25 14:10:50 -07:00
Michael Gottesman
69a03c93f9 [move-only] Ban partial reinitialization after consuming a value.
This is similar to our ban on partial consuming a value for this release. The
reason for this is that, one can achieve a similar affect as partial consumption
via a consumption of the entire value and then a partial reinitialization. Example:

```swift
struct X : ~Copyable { var i = 5, var i2 = Klass() }
var x = X()
_ = consume x
x.i = 5
```

in the case above, we now have a value that is in a partially initialized state.

We still allow for move only types to have their fields initialized as long as
there is an intervening init.

rdar://111498740
2023-07-05 20:26:26 -07:00
Michael Gottesman
7e582b0221 [move-only] Split error emission code from testing code. 2023-07-05 18:41:27 -07:00
Michael Gottesman
4591e39d02 [move-only] Fix borrowing address only no consume diagnostic to not say can't capture.
We previously were emitting a consuming partial_apply diagnostic. I had to
reformulate slightly the way we pattern match the diagnostics to make sure that
we get the proper no consume diagnostic.

rdar://111461837
2023-06-28 11:20:27 -07:00
Michael Gottesman
3dde9df468 [move-only] Emit an error if we /ever/ partially consume a noncopyable type.
The reason why I am doing this is that this was not part of the original
evolution proposal (it was called an extension) and after some discussion it was
realized that partial consumption would benefit from discussion on the forums.

rdar://111353459
2023-06-27 13:52:49 -07:00
swift-ci
0f201443ac Merge pull request #66846 from kavon/standardize-workqueue
Add a `BasicBlockWorkqueue` as a common utility.
2023-06-22 04:26:34 -07:00
Kavon Farvardin
ba885d9ec2 rewrite emitMissingConsumeInDiscardingContext to use BasicBlockWorkqueue 2023-06-21 23:40:08 -07:00
Nate Chandler
11443f26ed [move-only] Avoid loc from func decl.
It's always the first line of the function, so try to do better.
2023-06-16 21:13:09 -07:00
Kavon Farvardin
219f94fd1a tailor reinit-after-consume message for closure captures
rdar://109908383
2023-06-12 21:04:25 -07:00
Michael Gottesman
59c8cff917 [borrowing] Add support for borrowing/consuming copyable types to be a noimplicitcopy type.
rdar://108383660
2023-06-06 18:12:29 -04:00
Kavon Farvardin
bd253c602f prevent reinitialization of self after discard
The value `self` is mutable (i.e., var-bound) in
a `consuming` method. Since you're allowed to
reinitialize a var after consuming, that means
you were also naturally allowed to reinitialize
self after `discard self`. But that capability was
not intended; after you discard self you shouldn't
be reinitializing it, as that's probably a mistake.

This change makes reinitialization of `self`
reachable from a `discard self` statement an error.

rdar://106098163
2023-06-05 19:25:50 -07:00
Kavon Farvardin
88d35a00b3 emit error on implicit destruction of self in discard context
As part of SE-390, you're required to write either:

  - `consume self`
  - pass self as a `consuming` parameter to a function
  - `discard self`

before the function ends in a context that contains a
`discard self` somewhere. This prevents people from accidentally
invoking the deinit due to implicit destruction of `self` before
exiting the function.

rdar://106099027
2023-06-04 18:45:22 -07:00
Michael Gottesman
577e76b0f6 [move-only] Change closure capture diagnostic for let patterns to say that it cannot be captured by an escaping closure.
rdar://109742587
2023-05-28 13:58:59 -07:00
Joe Groff
ba67156608 Merge pull request #66091 from jckarter/debug-info-inout-move-only
Emit updated debug info when inout parameters are consumed and reinitialized.
2023-05-25 11:32:03 -07:00
Kavon Farvardin
03d2017a84 reword 'other consume here' to 'consumed again here'
this also fixes a bug where sometimes we simply emit
'consumed here' twice and other times we'd said 'other
consume here' for the same "consumed more than once"
message. so I went through and changed all of the 2nd
consumes into "consumed again".

rdar://109281444
2023-05-24 20:56:39 -07:00
Kavon Farvardin
71763a124e merge similar diagnostics together under a unified naming scheme for more consistent word tense
sil_movekillscopyablevalue_* and sil_moveonlychecker_* can share diagnostics.

rdar://109281444
2023-05-24 20:56:38 -07:00
Kavon Farvardin
667459ee75 tighten up consistency in terminology
- refer to a "consuming use" as simply a "consume", to reserve "use" for non-consuming uses.
- refer to "non-consuming uses" as just a "use".
- don't call it a "user defined deinit" and instead a "deinitializer" to match Sema
- be specific about what binding a closure is capturing that is preventing consumption.

rdar://109281444
2023-05-24 20:56:38 -07:00
Kavon Farvardin
e9e6cdaf2e remove "within a closure" since you can't consume any captured noncopyable binding
rdar://109281444
2023-05-24 20:56:38 -07:00
Kavon Farvardin
3149102fea reword "boundary use" to just "non-consuming"
rdar://109281444
2023-05-24 20:56:37 -07:00
Kavon Farvardin
d3730d896d reword diagnostics for partial consume of fields
also moves the error to the invalid partial consume.

rdar://109281444
2023-05-24 20:56:37 -07:00
Kavon Farvardin
31aa2f77e3 polish noncopyable types diagnostic wordings
- replaces "move-only" terminology with "noncopyable"
- replaces compiler jargon like "guaranteed parameters"
  and "lvalue" with corresponding language-level notions
- simplifies diagnostics about closures.

and probably more.

rdar://109281444
2023-05-24 20:56:36 -07:00
Joe Groff
9db359985d Emit updated debug info when inout parameters are consumed and reinitialized.
Change SILGen to emit the `debug_value` instruction using the original inout
parameter address, instead of the `mark_must_check` inserted for move-only
parameters, because code in the MoveOnlyAddressChecker did not expect to
find the debug_value anywhere but on the original address. Update move-only
diagnostics so that they pick up the declaration name for a memory location
from any debug_value instruction if there are more than one. rdar://109740281
2023-05-24 12:15:53 -07:00
Michael Gottesman
811824019e [move-only] Change the destructure through deinit error to lookup the deinit at the AST level rather than the SIL level.
I also added a note telling the user where the deinit is.

rdar://101651138
2023-04-13 12:49:28 -07:00
Michael Gottesman
76e93828ef [move-only] Make it an error if we attempt to destructure/partially invalidate through a field with a deinit.
If one has a type with a deinit, if one were to partially invalidate the value,
the checker will clean up the remaining parts of the value but not the actual
underlying value. This then would cause the deinit of the actual type to be
called.

rdar://101651138
2023-04-12 15:18:56 -07:00
Joe Groff
8e21bfcc47 MoveOnlyAddressChecker: Confine analysis to current formal access.
Code can only locally interact with a mutable memory location within a
formal access, and is only responsible for maintaining its invariants
during that access, so the move-only address checker does not need to,
and should not, observe operations that occur outside of the access
marked with the `mark_must_check` instruction. And for immutable
memory locations, although there are no explicit formal accesses, that's
because every access must be read-only, so although individual
accesses are not delimited, they are all compatible as far as
move-only checking is concerned. So we can back out the changes to SILGen
to re-project a memory location from its origin on every access, a
change which breaks invariants assumed by other SIL passes.
2023-04-02 16:33:57 -07:00
Andrew Trick
cbe856e53a Cleanup PrunedLiveBlocks
Use BasicBlockBitfield to record per-block liveness state. This has
been the intention since BasicBlockBitfield was first introduced.

Remove the per-field bitfield from PrunedLiveBlocks. This
(re)specializes the data structure for scalar liveness and drastically
simplifies the implementation.

This utility is fundamental to all ownership utilities. It will be on
the critical path in many areas of the compiler, including at
-Onone. It needs to be minimal and as easy as possible for compiler
engineers to understand, investigate, and debug.

This is in preparation for fixing bugs related to multi-def liveness
as used by the move checker.
2023-03-22 02:36:57 -07:00
Michael Gottesman
7d5476d3e6 Remove some optnone that snuck in. 2023-02-20 14:35:18 -08:00
Michael Gottesman
1dd896ded9 [move-only] Implement escaping closure semantics.
NOTE: A few of the test patterns need to be made better, but this patch series
is large enough, I want to get it into tree and iterate.
2023-02-20 11:04:21 -08:00
Michael Gottesman
a571357cce [move-only] Change noncopyable lets to be emitted as boxes like vars.
Some notes:

1. This ensures that if we capture them, we just capture the box by reference.

2. We are still using the old incorrect semantics for captures. I am doing this
   so I can bring this up in separate easy to understand patches all of which
   pass all of the moveonly tests.

3. Most of the test edits are due to small differences in error messages in
   between the object and address checker.

4. I had to add a little support to the move only address checker for a small
   pattern that doesn't occur with vars but do es occur for lets when we codegen
   like this, specifically around enums. The pattern is we perform a load_borrow
   and then copy_value and then use the result of the copy_value. Rather than fight
   SILGen pattern I introduced a small canonicalization into the address checker which
   transforms that pattern into a load [copy] + begin_borrow to restore the codegen
   to a pattern the checker expects.

5. I left noimplicitcopy alone for now. But we should come back around and fix
   it in a similar way. I just did not have time to do so.
2023-02-20 11:04:21 -08:00
Michael Gottesman
f4e1b2a8f2 [move-only] Update SILGen/MoveCheckers so that vars are emitted in eagerly projected box form.
This is the first slice of bringing up escaping closure support. The support is
based around introducing a new type of SILGen VarLoc: a VarLoc with a box and
without a value. Because the VarLoc only has a box, we have to in SILGen always
eagerly reproject out the address from the box. The reason why I am doing this
is that it makes it easy for the move checker to distinguish in between
different accesses to the box that we want to check separately. As such every
time that we open the box, we insert a mark_must_check
[assignable_but_not_consumable] on that project. If allocbox_to_stack manages to
determine that the box can be stack allocated, we eliminate all of the
mark_must_check and place a new mark_must_check [consumable_and_assignable] on
the alloc_stack.  The end result is that we get the old model that we had before
and also can support escaping closures.
2023-02-20 11:04:21 -08:00
Michael Gottesman
6c922af8aa [move-only] Combine the address/object checker in the same pass so that we only run cleanups once.
Otherwise, sometimes when the object checker emits a diagnostic and cleans up
the IR, some of the cleaned up copies are copies that should have been handled
by the address checker. The end result is that the address checker does not emit
diagnostics for that IR. I found this problem was exascerbated when writing code
for escaping closures.

This commit also cleans up the passes in preparation for at a future time moving
some of the transformations into the utils folder.
2023-02-19 13:55:22 -08:00
Michael Gottesman
2c137512b0 [move-only] Add an error that is emitted if the move checker misses a copy and asks to file a bug. 2023-02-17 16:04:46 -08:00
Michael Gottesman
c832b41b7b [move-only] Teach the move checker how to handle global_addr.
As part of this I also had to change how we emit global_addr in
SILGenLValue. Specifically, only for noncopyable types, we no longer emit a
single global_addr at the beginning of the function (in a sense auto-CSEing) and
instead always emit a new global_addr for each access. The reason why we do this
is that otherwise, access base visitor will consider all accesses to the global
to be for the same single access. In contrast, by always emitting the
global_addr each time, we provide a new base for each access allowing us to emit
the diagnostics that we want to.

rdar://102794400
2023-02-12 17:39:27 -08:00
Michael Gottesman
e58c45fa1e [move-only] Add support for ref_element_addr with AssignableButNotConsumable semantics.
rdar://104874497
2023-02-12 17:39:27 -08:00