Commit Graph

6 Commits

Author SHA1 Message Date
Michael Gottesman
87713349d4 [move-only] Ensure that copyable borrowing parameters of resilient type used by a function in the same module can be recognized by the checker
I found this while looking at problems around library evolution for noncopyable types. Specifically:

```
+public func borrowVal(_ x: borrowing CopyableStruct) {}
```

causes an error since we do not recognize the load_borrow here:

```
+sil [ossa] @testSimpleBorrowParameter : $@convention(thin) (@in_guaranteed CopyableStruct) -> () {
+bb0(%0 : @noImplicitCopy $*CopyableStruct):
+  %1 = load_borrow %0 : $*CopyableStruct                       // users: %7, %2
+  %2 = copyable_to_moveonlywrapper [guaranteed] %1 : $CopyableStruct // user: %3
+  %3 = copy_value %2 : $@moveOnly CopyableStruct               // user: %4
+  %4 = mark_must_check [no_consume_or_assign] %3 : $@moveOnly CopyableStruct // users: %6, %5
+  debug_value %4 : $@moveOnly CopyableStruct, let, name "x", argno 1 // id: %5
+  destroy_value %4 : $@moveOnly CopyableStruct                 // id: %6
+  end_borrow %1 : $CopyableStruct                              // id: %7
+  %8 = tuple ()                                   // user: %9
+  return %8 : $()                                 // id: %9
+}
```

rdar://112028837
2023-07-10 12:09:21 -07:00
Joe Groff
359e045192 Require switch on a noncopyable-type binding to be explicitly consume-d.
Pattern matching as currently implemented is consuming, but that's not
necessarily what we want to be the default behavior when borrowing pattern
matching is implemented. When a binding of noncopyable type is pattern-matched,
require it to be annotated with the `consume` operator explicitly. That way,
when we introduce borrowing pattern matching later, we have the option to make
`switch x` do the right thing without subtly changing the behavior of existing
code. rdar://110073984
2023-06-02 18:14:37 -07:00
Michael Gottesman
7d7c929e43 [move-only] Teach the move only object checker how to handle concrete resilient guaranteed arguments.
The only difference from normal concrete guaranteed parameter emission is we
have a load_borrow on the argument before the copy_value. That is instead of:

```
bb0(%0 : @guaranteed $Type):
  %1 = copy_value %0
  %2 = mark_must_check [no_consume_or_assign] %1
```

we have,

```
bb0(%0 : $*Type): // in_guaranteed
  %1 = load_borrow %0
  %2 = copy_value %1
  %3 = mark_must_check [no_consume_or_assign] %2
```

So I just needed to update the checker to recognize that pattern.

This is tested by just making sure that the checker can handle the borrowVal in
the tests without emitting an error.

rdar://109170906
2023-05-10 14:11:56 -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
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