ソースを参照

Explorer: fix variables not cleaned up if declared before unformed (#2544)

Fix variables not being properly cleaned up if declared before an unformed variable.

### Details

Currently the following example / test
```
package ExplorerTest api;

class A {
  var i: i32;
  destructor[self: Self] {
    Print("Destructor A {0}", self.i);
  }
}

fn Main() -> i32 {
  var a0: A;
  var a1: A = {.i = 1};
  var a2: A;
  var a3: A = {.i = 3};
  return 0;
}
```

prints
```
Destructor A 3
```

instead of 

```
Destructor A 3
Destructor A 1
```

This PR fixes the issue in the `CleanUp` logic.
Adrien Leravat 3 年 前
コミット
ec683d1ab2

+ 5 - 5
explorer/interpreter/interpreter.cpp

@@ -93,8 +93,6 @@ class Interpreter {
   // State transition for object destruction.
   auto StepCleanUp() -> ErrorOr<Success>;
   auto StepDestroy() -> ErrorOr<Success>;
-  // State transition for tuple destruction.
-  auto StepCleanUpTuple() -> ErrorOr<Success>;
 
   auto CreateStruct(const std::vector<FieldInitializer>& fields,
                     const std::vector<Nonnull<const Value*>>& values)
@@ -2204,17 +2202,19 @@ auto Interpreter::StepDestroy() -> ErrorOr<Success> {
 }
 
 auto Interpreter::StepCleanUp() -> ErrorOr<Success> {
-  Action& act = todo_.CurrentAction();
-  CleanUpAction& cleanup = cast<CleanUpAction>(act);
+  const Action& act = todo_.CurrentAction();
+  const auto& cleanup = cast<CleanUpAction>(act);
   if (act.pos() < cleanup.allocations_count()) {
     auto allocation =
         act.scope()->allocations()[cleanup.allocations_count() - act.pos() - 1];
-    auto lvalue = arena_->New<LValue>(Address(allocation));
+    const auto* lvalue = arena_->New<LValue>(Address(allocation));
     SourceLocation source_loc("destructor", 1);
     auto value = heap_.Read(lvalue->address(), source_loc);
     // Step over uninitialized values
     if (value.ok()) {
       return todo_.Spawn(std::make_unique<DestroyAction>(lvalue, *value));
+    } else {
+      return todo_.RunAgain();
     }
   }
   todo_.Pop();

+ 27 - 0
explorer/testdata/unformed/destroy_formed_only.carbon

@@ -0,0 +1,27 @@
+// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
+// Exceptions. See /LICENSE for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+// AUTOUPDATE
+// RUN: %{explorer-run}
+// RUN: %{explorer-run-trace}
+// CHECK:STDOUT: Destructor A 3
+// CHECK:STDOUT: Destructor A 1
+// CHECK:STDOUT: result: 0
+
+package ExplorerTest api;
+
+class A {
+  var i: i32;
+  destructor[self: Self] {
+    Print("Destructor A {0}", self.i);
+  }
+}
+
+fn Main() -> i32 {
+  var a0: A;
+  var a1: A = {.i = 1};
+  var a2: A;
+  var a3: A = {.i = 3};
+  return 0;
+}