Commit Graph

54 Commits

Author SHA1 Message Date
Michael Gottesman
cff835e061 [region-isolation] Perform checking of non-Sendable results using rbi rather than Sema.
In terms of the test suite the only difference is that we allow for non-Sendable
types to be returned from nonisolated functions. This is safe due to the rules
of rbi. We do still error when we return non-Sendable functions across isolation
boundaries though.

The reason that I am doing this now is that I am implementing a prototype that
allows for nonisolated functions to inherit isolation from their caller. This
would have required me to implement support both in Sema for results and
arguments in SIL. Rather than implement results in Sema, I just finished the
work of transitioning the result checking out of Sema and into SIL. The actual
prototype will land in a subsequent change.

rdar://127477211
2024-12-02 16:54:12 -05:00
Michael Gottesman
d94e4c4434 [region-isolation] Using the print method from the previous commit, ensure that we dump out SentNeverSendable, InOutSendingNotDisconnectedAtExit, AssignNeverSendableIntoSendingResult earlier when we initially detect them.
This just improves the ability to quickly triage bugs in SendNonSendable. It
used to be this way, but in the process of doing some refactoring, I moved the
logging too late by mistake.
2024-11-19 12:48:30 -08:00
Michael Gottesman
d33f819038 [region-isolation] Move freeform logging on the specific error we are emitting into a method on the error itself.
I am doing this since I discovered that we are not printing certain errors as
early as we used to (due to the refactoring I did here), which makes it harder
to see the errors that we are emitting while processing individual instructions
and before we run the actual dataflow.

A nice side-effect of this is that it will make it easy to dump the error in the
debugger rather than having to wait until the point in the code where the normal
logging takes place.
2024-11-19 12:48:30 -08:00
Michael Gottesman
32b4de60a9 Rename transfer -> send.
Accomplished using clangd's rename functionality.
2024-11-04 15:17:51 -08:00
Michael Gottesman
0a56827073 [region-isolation] Rename TransferNonSendable.cpp -> SendNonSendable.cpp.
Just beginning the elimination of the word transferred from the code base.
2024-11-02 16:58:17 -07:00
Michael Gottesman
0bad8f9b67 [region-isolation] Rename SendNonSendable.cpp -> TransferNonSendable.cpp. 2023-10-26 12:01:44 -07:00
Michael Gottesman
c10c4fc10f Merge pull request #69387 from gottesmm/more-region-stuff
[region-isolation] Fix actor region propagation and some other smaller issues.
2023-10-25 11:46:19 -07:00
Michael Gottesman
0b27c5ca16 [region-based-isolation] Rather than lazily translating while we visit all blocks during the dataflow... just do the translation when we initialize block state.
We are going to visit all of the blocks anyways... so it makes sense to just run
them as part of the initializing of the block state. Otherwise, the logic is
buried in the dataflow which makes it harder for someone who is not familiar
with the pass to reason about it.
2023-10-24 16:36:02 -07:00
Michael Gottesman
cb6ac6ca31 [region-isolation] Make sure to look through begin_access and don't treat it like an assignment.
If we treat a begin_access as an assignment then in cases like below we assume
that a value was used before we reassign.

```
  func testVarReassignStopActorDerived() async {
    var closure = {}
    await transferToMain(closure)

    // This re-assignment shouldn't error.
    closure = {}  // (1)
  }
```

rdar://117437299
2023-10-24 16:36:01 -07:00
Michael Gottesman
e1b17b9763 [region-isolation] Rather than cache a separate vector of argument ids, just cache the function entry partition.
We only ever used this cache of IDs to construct the function arg
partition. Since a Partition involves using memory, it makes sense to just cache
the Partition itself and eliminate the unnecessary second cache.
2023-10-24 16:35:01 -07:00
Michael Gottesman
7fff6cd037 [region-isolation] Only perform merge assignment if we capture an address in a partial_apply rather than if we send it to any function apply.
Semantically these are the only cases where we would want to force an address to
be merged. Some notes:

1. When we have a box, the project_box is considered to come from the box and is
considered non uniquely identified.

2. The only place this was really triggering was when we created temporary
partial applies to pass to a function when using address only types. Since this
temporaries are never reassigned to, there isn't any reason to require them to
be merged.

3. In the case where we have an alloc_stack grabbed by a partial_apply, we still
appropriately merge.
2023-10-24 16:35:01 -07:00
Michael Gottesman
9dfc9b6a2d [region-isolation] Track if a non-Sendable value was derived from an actor and treat its region as being within an actor's isolation domain.
Importantly, we determine at the error stage if a specific value that is
transferred is within the same region of a value that is Actor derived. This
means that we can in a flow insensitive manner determine the values that are
actor derived and then via propagating those values into various regions
determine the issue... using our region analysis to handle the flow sensitivity.

One important case to reason about here is that since we are relying on the
region propagation for flow sensitivity is that this solves the var case for
us. A var when declared is never marked as actor derived. Var uses only become
actor derived if the var was merged into a region that contain is actor
derived. That means that re-assigning to a non-actor derived value, eliminates
the actor derived bit.

As part of this, I also discovered I could just get rid of the captured uniquely
identified array in favor of just passing in an actor derived flag.

rdar://115656589
2023-10-24 16:35:00 -07:00
Michael Gottesman
d069169c0d Fix some typos. 2023-10-24 12:47:11 -07:00
Michael Gottesman
926b4b1bb3 [region-isolation] Change TransferredReason to use a std::multimap.
In a future commit, I think I am going to change this to use a
SmallFrozenMultiMap so we can avoid the heap cost in most cases. For now though
I am just changing it to a std::multimap to make it cleaner and avoid having to
reason about when to freeze the SmallFrozenMultiMap.
2023-10-24 12:47:11 -07:00
Michael Gottesman
81a20e8609 [region-isolation] Convert some if(!condition) { assert(false) } -> assert(condition). 2023-10-24 12:47:11 -07:00
Michael Gottesman
2c0efe6b8b [region-isolation] Go through the implementation again changing Consume -> Transfer.
I just missed these.
2023-10-23 13:52:14 -07:00
Michael Gottesman
01b1475d62 [region-isolation] Emit errors directly in ConsumeRequireAccumulator rather than passing in callbacks.
This indirection is premature abstraction since the only two places we actually
use these callbacks is to print the accumulated output and to emit our
errors. With this change, I was able to simplify how print works and inline in
the actual diagnostic emission making it easier to understand the code.

Additionally, in a subsequent commit I am going to need to ensure that we do not
emit an error here if the source cause of our error is due to an actor. To
implement that I would need to change tryDiagnoseAsCallsite to signal to the
machinery that it needs to not emit requires and then fail further up as
well. Given that there really wasn't a need for this abstraction in the first
place and the amount of munging needed to express this, I decided to just make
this change and make it easier. If we truly need this flexibility, we can always
add it back later.
2023-10-23 12:24:17 -07:00
Michael Gottesman
cbc12410b3 [region-isolation] Eliminate unnecessary helper.
SILValues always have a SILType... so just use getType().isAddress().
2023-10-23 12:24:17 -07:00
Michael Gottesman
a8886e7619 Delete an incorrect assert
If we consume a value in a block and then reinitialize it before the end of the
block, this assert will always fail.
2023-10-23 12:24:17 -07:00
Michael Gottesman
d598da596a [sil] Implement SILType::isActor().
Just a helper that calls getASTType()->isActorType().

I also updated the two places in SNS that we use this.
2023-10-23 12:24:17 -07:00
Michael Gottesman
8d46cc8c08 [isolation-regions] Rename Consume to Transfer.
Transfer is the terminology that we are using for something be transferred
across an isolation boundary, not consume. This also eliminates confusion with
consume which is a term being used around ownership.
2023-09-22 16:21:46 -05:00
Michael Gottesman
a9e8baa3b7 [isolation-regions] Eliminate last temporary std::vector usage from the non-error path. 2023-09-22 16:21:46 -05:00
Michael Gottesman
63db040a1d [isolation-regions] Eliminate all heap allocations from the main translation loop.
I did this by introducing a builder construct that has a SmallVector within it
that we append into instead of returning std::vector. I also used some passed in
SmallVectors in other places as well with large enough sizes that most times we
will not allocate.
2023-09-22 16:21:46 -05:00
Michael Gottesman
e5e0941e8b Remove clang optimize off that snuck into tree. 2023-09-13 12:59:02 -05:00
Michael Gottesman
4dcee7183a [send-non-sendable] Warn if a non-final field of an actor is transferred.
rdar://115132118
2023-09-12 14:12:54 -05:00
Michael Gottesman
82fbde0e04 [send-non-sendable] Ensure that we properly warn if a field of a final actor is transferred.
Previously, we were not recognizing that a ref_element_addr from an actor object
is equivalent to the actor object and we shouldn't allow for it to be consumed.

rdar://115132118
2023-09-12 12:46:37 -05:00
Michael Gottesman
3382352a62 [send-non-sendable] Make sure that we translate project_box into the pseudo-IR.
This is a case of an instruction that we missed translating into the pseudo-IR.
This was easy to do since we are not yet performing an exhaustive switch over
all instruction kinds when translating. Earlier I did the first part of the
translation by switching from doing conditional is<INST> to switch but haven't
yet eliminated the default yet from the switch. I am fixing this now since with
my load [copy] change from earlier causes us to crash in the earlier unorganized
tests.

rdar://115367810
2023-09-12 12:15:52 -05:00
Michael Gottesman
3a377a3e51 [send-non-sendable] When logging the pseudo-ir dump out the root representative value associated with pseudo-ir ids.
Really, we should just be using representative values here in general since it
serves the same purpose and makes it easier to trace back values. But this in
the short term makes the output easier to reason about.
2023-09-12 12:11:44 -05:00
Michael Gottesman
acd1063c95 [send-non-sendable] Convert some llvm::Optional -> std::optional. 2023-09-12 12:11:44 -05:00
Michael Gottesman
969477acea [send-non-sendable] Eliminate another pass by value of a std::vector. 2023-09-12 12:11:44 -05:00
Michael Gottesman
cd7213e3a2 [send-non-sendable] Eliminate a bunch of temporary heap allocations caused by using std::vector temporaries.
Just making small improvements as I go.
2023-09-12 12:11:44 -05:00
Michael Gottesman
42df9c4c72 [send-non-sendable] Cleanup logging a little.
Specifically:

1. Converted llvm::errs() -> llvm::dbgs() when using LLVM_DEBUG.
2. Converted a dump method on errs to be a print method on dbgs that is called from dump with print(llvm::dbgs()).
2023-09-12 12:11:44 -05:00
Michael Gottesman
336ed714ce [send-non-sendable] Convert SILInstruction translation to use an exhaustive switch.
This ensures that we actually handle all instructions. I already found that we
are not handling ~106 cases... but to make this just a refactoring patch, I just
put in a default + a break + left in the error.

rdar://115367810
2023-09-12 12:11:39 -05:00
Michael Gottesman
a1daf817f3 [send-non-sendable] Remove ASCII color from log output.
Not everyone uses color output and having to remove the ASCII color support is
annoying.
2023-09-11 09:07:29 -05:00
Michael Gottesman
68564f12dc [sendable-non-sendable] When tracking values flow sensitive properties, map a SILValue to the state rather than including the state in the mapping.
Otherwise, we can potentially map the same SILValue twice if its Key state is
slightly different.
2023-08-28 18:39:52 -07:00
Michael Gottesman
c68a976c9f [send-non-sendable] Change a set::set to be an llvm::DenseSet. 2023-08-25 12:17:18 -07:00
Michael Gottesman
74c71b871c [send-non-sendable] Make TrackableSILValue a POD value.
Previously before this patch, the logic for constructing TrackableSILValue was
split inbetween TrackableSILValue and the PartitionOpTranslator. A lot of
routines were also just utility routines that did not depend on the state in
either of the constructs.

With that in mind in this patch I:

1. Moved the utility functions that did not depend on internal state of those
functions into utility functions in the utility section.

2. Moved the logic in TrackableSILValue's constructor that depended on state
inside PartitionOpTranslator into PartitionOpTranslator itself.

3. Made TrackableSILValue a simple POD type used for storing state.

4. I changed capturedUIValues to just store within it a SILValue. It actually
does not care about isAliased or isSendable... it is just used as a way to check
if we have a uniquely identified value. In a forthcoming patch, I am going to
try to do similar things with the other maps that use TrackableSILValues since
by making the TrackableSILValues our keys/sets it allows for us to potentially
store multiple versions of the same TrackableSILValues if their aliased/sendable
state differ... which would lead to bugs.
2023-08-25 12:05:19 -07:00
Michael Gottesman
4f20b5ddbb [send-non-sendable] Move utility functions into a utility section.
I also used a more general way to check for apply insts that are not builtins
(ApplySite).
2023-08-25 11:59:12 -07:00
Michael Gottesman
bfb204643f [send-non-sendable] Cleanup the main SILFunctionTransform. 2023-08-25 11:58:16 -07:00
Michael Gottesman
373a007efa [send-not-sendable] Eliminate relative includes and add a file header.
Specifically, the two routines we were importing relatively were:

1. TypeChecker::conformsToProtocol. I moved this onto a helper routine on
SILType.

2. swift::findOriginalValueType(Expr *). This routine just looks through various
implicit conversions to find the original underlying type. I moved it to a
helper method on Expr.
2023-08-23 14:38:30 -07:00
jturcotti
bb2f3c011e rename DeferredSendableChecking pass to SendNonSendable pass, handle more instructions such as try_apply and begin_apply, and fix bugs 2023-07-27 16:45:29 -07:00
jturcotti
853ef7cf3c fix bugs that present themselves when handling multiarg and varargs functions, including adding better debug dump methods 2023-07-20 14:01:08 -07:00
jturcotti
a83d7aa39c improve diagnostics about data races; highlight the individual expressions being sent and accessed as precisely as possible, and include information about specific non-sendable types and isolation crossings 2023-07-19 17:27:16 -07:00
jturcotti
55e8f9f2ed improve debug output, finalize explicit constructor refactor, and begin improving diagnostic messages 2023-07-18 15:58:56 -07:00
jturcotti
5f42a142df handle tuple creation 2023-07-18 14:32:12 -07:00
jturcotti
3868f1dc27 perform refactor to use named types as elements and regions in partitions, and ensure that all SILValues are converted once to TrackableSILValues in the SendNonSendable analysis pass 2023-07-18 13:32:43 -07:00
jturcotti
34113c4c0f implement searching for a ConsumeReason instead of just diagnosing accesses to consumed values 2023-07-14 16:12:52 -07:00
jturcotti
1d130390be add more comprehensive cases to tests, and fix many bugs, relying on much more potent resolution of addresses 2023-07-14 09:28:27 -07:00
jturcotti
1a716d82cf replace use of internal "projections" tracking map with usage of memutils' AccessStorage utilities 2023-07-14 09:28:26 -07:00
jturcotti
65fa6fd966 use LLVM_DEBUG instead of static DEBUG constant 2023-07-12 09:36:21 -07:00