[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
This commit is contained in:
Michael Gottesman
2023-10-23 17:41:44 -07:00
parent e1b17b9763
commit cb6ac6ca31
2 changed files with 34 additions and 4 deletions

View File

@@ -885,7 +885,6 @@ public:
// treating some of these as lookthroughs in getUnderlyingTrackedValue
// instead of as assignments
case SILInstructionKind::AddressToPointerInst:
case SILInstructionKind::BeginAccessInst:
case SILInstructionKind::CopyValueInst:
case SILInstructionKind::ConvertEscapeToNoEscapeInst:
case SILInstructionKind::ConvertFunctionInst:
@@ -1070,6 +1069,25 @@ public:
case SILInstructionKind::YieldInst: // TODO: yield should be handled
return;
// We ignore begin_access since we look through them. We look through them
// since we want to treat the use of the begin_access as the semantic giving
// instruction. Otherwise, if we have a store after a consume we will emit
// an error on the begin_access rather than allowing for the store to
// overwrite the original value. This would then cause an error.
//
// Example:
//
// %0 = alloc_stack
// store %1 to %0
// apply %transfer(%0)
// %2 = begin_access [modify] [static] %0
// store %2 to %0
//
// If we treated a begin_access as an assign, we would require %0 to not be
// transferred at %2 even though we are about to overwrite it.
case SILInstructionKind::BeginAccessInst:
return;
default:
break;
}