Procházet zdrojové kódy

Trace output filtering based on file context (#2916)

To filter based on file contexts, you can use `-trace_file_context=...`
flag along with `--trace_file=...` flag. These are the following options
you can pass to the `-trace_file_context=...` flag (you can also pass
them as list by separating them with comma).
1. `main`: Include trace output for file containing the main function.
2. `prelude`: Include trace output for prelude.
3. `import`: Include trace output for imports.
4. `include`: Include trace output for all.

If the flag isn't used or non of the options are passed, by default only
main file context is traced.

File contexts are distinguished based upon the source location by
passing the source location to `TraceStream::is_enabled(..)` as
arguments. If no arguments are passed, file context is
`FileContext::Unknown` and for now it will add the trace from unknown
file context.

Note: `import` option currently doesn't work as imports aren't supported
yet.

---------

Co-authored-by: Richard Smith <richard@metafoo.co.uk>
Prabhat Sachdeva před 2 roky
rodič
revize
c0d18a62eb

+ 26 - 15
explorer/README.md

@@ -168,24 +168,35 @@ performed during execution.
 Printing directly to the standard output using the `--trace_file` option is
 supported by passing `-` in place of a filepath (`--trace_file=-`).
 
-To customize the trace output and include specific information, you can pass the
-following list of options to `-trace_phase=...` option along with
-`--trace_file=...` option:
+Trace output can be customized by selecting program phases and file contexts for
+which tracing should be enabled. The `-trace_phase=...` option is used to select
+program phases, while the `-trace_file_context=...` option is used to select
+file contexts.
 
--   `source_program`: Include trace output for the source program phase.
--   `name_resolution`: Include trace output for the name resolution phase.
--   `control_flow_resolution`: Include trace output for the control flow
+The following options can be passed as a comma-separated list to the
+`-trace_phase=...` option to select program phases:
+
+-   `source_program`: Includes trace output for the source program phase.
+-   `name_resolution`: Includes trace output for the name resolution phase.
+-   `control_flow_resolution`: Includes trace output for the control flow
     resolution phase.
--   `type_checking`: Include trace output for the type checking phase.
--   `unformed_variables_resolution`: Include trace output for the unformed
+-   `type_checking`: Includes trace output for the type checking phase.
+-   `unformed_variables_resolution`: Includes trace output for the unformed
     variables resolution phase.
--   `declarations`: Include trace output for printing declarations.
--   `execution`: Include trace output for program execution.
--   `timing`: Include timing logs indicating the time taken by each phase.
--   `all`: Include trace output for all phases.
-
-By default, only execution trace will be added to the trace output. You can use
-combination of these options to include trace of multiple program phases.
+-   `declarations`: Includes trace output for printing declarations.
+-   `execution`: Includes trace output for program execution.
+-   `timing`: Includes timing logs indicating the time taken by each phase.
+-   `all`: Includes trace output for all phases.
+-   By default, tracing is only enabled for the `execution` phase.
+
+The following options can be passed as a comma-separated list to the
+`-trace_file_context=...` option to select file contexts:
+
+-   `main`: Includes trace output for the file containing the main function.
+-   `prelude`: Includes trace output for the prelude.
+-   `import`: Includes trace output for imports.
+-   `include`: Includes trace output for all.
+-   By default, tracing is only enabled for the `main` file context.
 
 ### State of the Program
 

+ 12 - 0
explorer/common/BUILD

@@ -54,6 +54,7 @@ cc_library(
     name = "trace_stream",
     hdrs = ["trace_stream.h"],
     deps = [
+        ":source_location",
         "//common:check",
         "//common:ostream",
         "//explorer/common:nonnull",
@@ -69,3 +70,14 @@ cc_test(
         "@com_google_googletest//:gtest",
     ],
 )
+
+cc_test(
+    name = "set_file_context_raii_test",
+    srcs = ["set_file_context_raii_test.cpp"],
+    deps = [
+        ":source_location",
+        ":trace_stream",
+        "//testing/util:gtest_main",
+        "@com_google_googletest//:gtest",
+    ],
+)

+ 47 - 0
explorer/common/set_file_context_raii_test.cpp

@@ -0,0 +1,47 @@
+// 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
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include "explorer/common/trace_stream.h"
+
+namespace Carbon::Testing {
+namespace {
+
+// TODO: write test cases to distinguish between file context of main file and
+// an import once imports are supported.
+
+TEST(SetFileContextRaiiTest, Simple) {
+  TraceStream trace_stream;
+  {
+    SetFileContext set_file_ctx(trace_stream,
+                                SourceLocation("example/main.carbon", 9));
+    EXPECT_TRUE(trace_stream.file_context() == FileContext::Main);
+  }
+
+  // Considering the file context for a trace stream is FileContext::Unknown by
+  // default, as the default value of source location in a trace stream is
+  // std::nullopt.
+  EXPECT_TRUE(trace_stream.file_context() == FileContext::Unknown);
+}
+
+TEST(SetFileContextRaiiTest, UpdateFileContext) {
+  TraceStream trace_stream;
+  {
+    SetFileContext set_file_ctx(trace_stream,
+                                SourceLocation("example/prelude.carbon", 9));
+    EXPECT_TRUE(trace_stream.file_context() == FileContext::Prelude);
+    set_file_ctx.update_source_loc(SourceLocation("example/main.carbon", 9));
+    EXPECT_TRUE(trace_stream.file_context() == FileContext::Main);
+  }
+
+  // Considering the file context for a trace stream is FileContext::Unknown by
+  // default, as the default value of source location in a trace stream is
+  // std::nullopt.
+  EXPECT_TRUE(trace_stream.file_context() == FileContext::Unknown);
+}
+
+}  // namespace
+}  // namespace Carbon::Testing

+ 2 - 0
explorer/common/source_location.h

@@ -37,6 +37,8 @@ class SourceLocation {
     return filename_ == other.filename_ && line_num_ == other.line_num_;
   }
 
+  auto filename() const -> std::string_view { return filename_; }
+
   void Print(llvm::raw_ostream& out) const {
     out << filename_ << ":" << line_num_;
   }

+ 80 - 6
explorer/common/trace_stream.h

@@ -13,6 +13,7 @@
 #include "common/check.h"
 #include "common/ostream.h"
 #include "explorer/common/nonnull.h"
+#include "explorer/common/source_location.h"
 
 namespace Carbon {
 
@@ -34,6 +35,10 @@ enum class ProgramPhase {
   Last = All                   // Last program phase indicator.
 };
 
+// Enumerates the contexts for different types of files, used for tracing and
+// controlling for which file contexts tracing should be enabled.
+enum class FileContext { Unknown, Main, Prelude, Import, All, Last = All };
+
 // Encapsulates the trace stream so that we can cleanly disable tracing while
 // the prelude is being processed. The prelude is expected to take a
 // disproprotionate amount of time to log, so we try to avoid it.
@@ -45,12 +50,32 @@ enum class ProgramPhase {
 // contexts.
 class TraceStream {
  public:
+  explicit TraceStream() { set_allowed_file_contexts({FileContext::Unknown}); }
+
+  // This method gets the file context by using filename from source location.
+  // TODO: implement a way to differentiate between the main file and imports
+  // based upon source location / filename.
+  auto file_context() const -> FileContext {
+    if (source_loc_.has_value()) {
+      auto filename =
+          llvm::StringRef(source_loc_->filename()).rsplit("/").second;
+      if (filename == "prelude.carbon") {
+        return FileContext::Prelude;
+      } else {
+        return FileContext::Main;
+      }
+    } else {
+      return FileContext::Unknown;
+    }
+  };
+
   // Returns true if tracing is currently enabled.
   // TODO: use current source location for file context based filtering instead
   // of just checking if current code context is Prelude.
   auto is_enabled() const -> bool {
     return stream_.has_value() && !in_prelude_ &&
-           allowed_phases_[static_cast<int>(current_phase_)];
+           allowed_phases_[static_cast<int>(current_phase_)] &&
+           allowed_file_contexts_[static_cast<int>(file_context())];
   }
 
   // Sets whether the prelude is being skipped.
@@ -79,6 +104,29 @@ class TraceStream {
     }
   }
 
+  auto set_allowed_file_contexts(std::vector<FileContext> contexts_list)
+      -> void {
+    if (contexts_list.empty()) {
+      allowed_file_contexts_.set(static_cast<int>(FileContext::Main));
+    } else {
+      for (auto context : contexts_list) {
+        if (context == FileContext::All) {
+          allowed_file_contexts_.set();
+        } else {
+          allowed_file_contexts_.set(static_cast<int>(context));
+        }
+      }
+    }
+  }
+
+  auto set_source_loc(std::optional<SourceLocation> source_loc) {
+    source_loc_ = source_loc;
+  }
+
+  auto source_loc() -> std::optional<SourceLocation> { return source_loc_; }
+
+  auto allowed_phases() { return allowed_phases_; }
+
   // Returns the internal stream. Requires is_enabled.
   auto stream() const -> llvm::raw_ostream& {
     CARBON_CHECK(is_enabled() && stream_.has_value());
@@ -97,13 +145,15 @@ class TraceStream {
 
  private:
   bool in_prelude_ = false;
-  std::optional<Nonnull<llvm::raw_ostream*>> stream_;
   ProgramPhase current_phase_ = ProgramPhase::Unknown;
+  std::optional<SourceLocation> source_loc_ = std::nullopt;
+  std::optional<Nonnull<llvm::raw_ostream*>> stream_;
   std::bitset<static_cast<int>(ProgramPhase::Last) + 1> allowed_phases_;
+  std::bitset<static_cast<int>(FileContext::Last) + 1> allowed_file_contexts_;
 };
 
 // This is a RAII class to set the current program phase, destructor invocation
-// restores the previous phase
+// restores the previous phase.
 class SetProgramPhase {
  public:
   explicit SetProgramPhase(TraceStream& trace_stream,
@@ -113,19 +163,43 @@ class SetProgramPhase {
     trace_stream.set_current_phase(program_phase);
   }
 
+  ~SetProgramPhase() { trace_stream_.set_current_phase(initial_phase_); }
+
   // This can be used for cases when current phase is set multiple times within
-  // the same scope
+  // the same scope.
   auto update_phase(ProgramPhase program_phase) -> void {
     trace_stream_.set_current_phase(program_phase);
   }
 
-  ~SetProgramPhase() { trace_stream_.set_current_phase(initial_phase_); }
-
  private:
   TraceStream& trace_stream_;
   ProgramPhase initial_phase_;
 };
 
+// This is a RAII class to set the source location in trace stream, destructor
+// invocation restores the initial source location.
+class SetFileContext {
+ public:
+  explicit SetFileContext(TraceStream& trace_stream,
+                          std::optional<SourceLocation> source_loc)
+      : trace_stream_(trace_stream),
+        initial_source_loc_(trace_stream.source_loc()) {
+    trace_stream_.set_source_loc(source_loc);
+  }
+
+  ~SetFileContext() { trace_stream_.set_source_loc(initial_source_loc_); }
+
+  // This can be used for cases when source location needs to be updated
+  // multiple times within the same scope.
+  auto update_source_loc(std::optional<SourceLocation> source_loc) {
+    trace_stream_.set_source_loc(source_loc);
+  }
+
+ private:
+  TraceStream& trace_stream_;
+  std::optional<SourceLocation> initial_source_loc_;
+};
+
 }  // namespace Carbon
 
 #endif  // CARBON_EXPLORER_COMMON_TRACE_STREAM_H_

+ 1 - 0
explorer/file_test.cpp

@@ -57,6 +57,7 @@ class ParseAndExecuteTestFile : public FileTestBase {
     if (trace_) {
       trace_stream.set_stream(is_trace_test ? &stdout : &trace_stream_ostream);
       trace_stream.set_allowed_phases({ProgramPhase::All});
+      trace_stream.set_allowed_file_contexts({FileContext::Main});
     }
 
     // Set the location of the prelude.

+ 27 - 12
explorer/interpreter/action.h

@@ -165,10 +165,14 @@ class Action {
     scope_ = std::move(scope);
   }
 
+  auto source_loc() -> std::optional<SourceLocation> { return source_loc_; }
+
  protected:
   // Constructs an Action. `kind` must be the enumerator corresponding to the
   // most-derived type being constructed.
-  explicit Action(Kind kind) : kind_(kind) {}
+  explicit Action(std::optional<SourceLocation> source_loc, Kind kind)
+      : source_loc_(source_loc), kind_(kind) {}
+  std::optional<SourceLocation> source_loc_;
 
  private:
   int pos_ = 0;
@@ -183,7 +187,8 @@ class Action {
 class LocationAction : public Action {
  public:
   explicit LocationAction(Nonnull<const Expression*> expression)
-      : Action(Kind::LocationAction), expression_(expression) {}
+      : Action(expression->source_loc(), Kind::LocationAction),
+        expression_(expression) {}
 
   static auto classof(const Action* action) -> bool {
     return action->kind() == Kind::LocationAction;
@@ -202,7 +207,7 @@ class ExpressionAction : public Action {
   explicit ExpressionAction(
       Nonnull<const Expression*> expression,
       std::optional<AllocationId> initialized_location = std::nullopt)
-      : Action(Kind::ExpressionAction),
+      : Action(expression->source_loc(), Kind::ExpressionAction),
         expression_(expression),
         location_received_(initialized_location) {}
 
@@ -229,7 +234,7 @@ class TypeInstantiationAction : public Action {
  public:
   explicit TypeInstantiationAction(Nonnull<const Value*> type,
                                    SourceLocation source_loc)
-      : Action(Kind::TypeInstantiationAction),
+      : Action(source_loc, Kind::TypeInstantiationAction),
         type_(type),
         source_loc_(source_loc) {}
 
@@ -249,13 +254,19 @@ class TypeInstantiationAction : public Action {
 // local context.
 class WitnessAction : public Action {
  public:
-  explicit WitnessAction(Nonnull<const Witness*> witness)
-      : Action(Kind::WitnessAction), witness_(witness) {}
+  explicit WitnessAction(Nonnull<const Witness*> witness,
+                         SourceLocation source_loc)
+      : Action(source_loc, Kind::WitnessAction), witness_(witness) {}
 
   static auto classof(const Action* action) -> bool {
     return action->kind() == Kind::WitnessAction;
   }
 
+  auto source_loc() -> SourceLocation {
+    CARBON_CHECK(source_loc_);
+    return *source_loc_;
+  }
+
   // The Witness this Action resolves.
   auto witness() const -> Nonnull<const Witness*> { return witness_; }
 
@@ -269,7 +280,7 @@ class StatementAction : public Action {
  public:
   explicit StatementAction(Nonnull<const Statement*> statement,
                            std::optional<AllocationId> location_received)
-      : Action(Kind::StatementAction),
+      : Action(statement->source_loc(), Kind::StatementAction),
         statement_(statement),
         location_received_(location_received) {}
 
@@ -306,7 +317,8 @@ class StatementAction : public Action {
 class DeclarationAction : public Action {
  public:
   explicit DeclarationAction(Nonnull<const Declaration*> declaration)
-      : Action(Kind::DeclarationAction), declaration_(declaration) {}
+      : Action(declaration->source_loc(), Kind::DeclarationAction),
+        declaration_(declaration) {}
 
   static auto classof(const Action* action) -> bool {
     return action->kind() == Kind::DeclarationAction;
@@ -323,7 +335,7 @@ class DeclarationAction : public Action {
 class CleanUpAction : public Action {
  public:
   explicit CleanUpAction(RuntimeScope scope)
-      : Action(Kind::CleanUpAction),
+      : Action(std::nullopt, Kind::CleanUpAction),
         allocations_count_(scope.allocations().size()) {
     StartScope(std::move(scope));
   }
@@ -350,7 +362,9 @@ class DestroyAction : public Action {
   //           and the value is the member of the class
   explicit DestroyAction(Nonnull<const LocationValue*> location,
                          Nonnull<const Value*> value)
-      : Action(Kind::DestroyAction), location_(location), value_(value) {}
+      : Action(std::nullopt, Kind::DestroyAction),
+        location_(location),
+        value_(value) {}
 
   static auto classof(const Action* action) -> bool {
     return action->kind() == Kind::DestroyAction;
@@ -371,7 +385,8 @@ class DestroyAction : public Action {
 // with AST nodes.
 class ScopeAction : public Action {
  public:
-  explicit ScopeAction(RuntimeScope scope) : Action(Kind::ScopeAction) {
+  explicit ScopeAction(RuntimeScope scope)
+      : Action(std::nullopt, Kind::ScopeAction) {
     StartScope(std::move(scope));
   }
 
@@ -390,7 +405,7 @@ class ScopeAction : public Action {
 // Should be avoided where possible.
 class RecursiveAction : public Action {
  public:
-  explicit RecursiveAction() : Action(Kind::RecursiveAction) {}
+  explicit RecursiveAction() : Action(std::nullopt, Kind::RecursiveAction) {}
 
   static auto classof(const Action* action) -> bool {
     return action->kind() == Kind::RecursiveAction;

+ 6 - 3
explorer/interpreter/exec_program.cpp

@@ -24,6 +24,7 @@ auto AnalyzeProgram(Nonnull<Arena*> arena, AST ast,
                     Nonnull<TraceStream*> trace_stream,
                     Nonnull<llvm::raw_ostream*> print_stream) -> ErrorOr<AST> {
   SetProgramPhase set_prog_phase(*trace_stream, ProgramPhase::SourceProgram);
+  SetFileContext set_file_ctx(*trace_stream, std::nullopt);
 
   if (trace_stream->is_enabled()) {
     *trace_stream << "********** source program **********\n";
@@ -68,9 +69,11 @@ auto AnalyzeProgram(Nonnull<Arena*> arena, AST ast,
   set_prog_phase.update_phase(ProgramPhase::Declarations);
   if (trace_stream->is_enabled()) {
     *trace_stream << "********** printing declarations **********\n";
-    for (int i = ast.num_prelude_declarations;
-         i < static_cast<int>(ast.declarations.size()); ++i) {
-      *trace_stream << *ast.declarations[i];
+    for (auto& declaration : ast.declarations) {
+      set_file_ctx.update_source_loc(declaration->source_loc());
+      if (trace_stream->is_enabled()) {
+        *trace_stream << *declaration;
+      }
     }
   }
   return ast;

+ 26 - 18
explorer/interpreter/interpreter.cpp

@@ -24,6 +24,7 @@
 #include "explorer/common/arena.h"
 #include "explorer/common/error_builders.h"
 #include "explorer/common/source_location.h"
+#include "explorer/common/trace_stream.h"
 #include "explorer/interpreter/action.h"
 #include "explorer/interpreter/action_stack.h"
 #include "explorer/interpreter/stack.h"
@@ -163,7 +164,8 @@ class Interpreter {
 
   // Instantiate a witness by replacing all type variables and impl binding
   // references that occur within it by the current values of those variables.
-  auto InstantiateWitness(Nonnull<const Witness*> witness)
+  auto InstantiateWitness(Nonnull<const Witness*> witness,
+                          SourceLocation source_loc)
       -> ErrorOr<Nonnull<const Witness*>>;
 
   // Call the function `fun` with the given `arg` and the `witnesses`
@@ -631,9 +633,9 @@ auto Interpreter::StepLocation() -> ErrorOr<Success> {
 auto Interpreter::EvalRecursively(std::unique_ptr<Action> action)
     -> ErrorOr<Nonnull<const Value*>> {
   if (trace_stream_->is_enabled()) {
-    *trace_stream_ << "--- recursive eval\n";
     TraceState();
   }
+
   todo_.BeginRecursiveAction();
   CARBON_RETURN_IF_ERROR(todo_.Spawn(std::move(action)));
   // Note that the only `RecursiveAction` we can encounter here is our own --
@@ -661,7 +663,7 @@ auto Interpreter::EvalAssociatedConstant(
   CARBON_ASSIGN_OR_RETURN(Nonnull<const Value*> interface,
                           InstantiateType(&assoc->interface(), source_loc));
   CARBON_ASSIGN_OR_RETURN(Nonnull<const Witness*> witness,
-                          InstantiateWitness(&assoc->witness()));
+                          InstantiateWitness(&assoc->witness(), source_loc));
 
   const auto* impl_witness = dyn_cast<ImplWitness>(witness);
   if (!impl_witness) {
@@ -753,8 +755,8 @@ auto Interpreter::InstantiateBindings(Nonnull<const Bindings*> bindings,
 
   ImplWitnessMap witnesses = bindings->witnesses();
   for (auto& [bind, witness] : witnesses) {
-    CARBON_ASSIGN_OR_RETURN(witness,
-                            InstantiateWitness(cast<Witness>(witness)));
+    CARBON_ASSIGN_OR_RETURN(
+        witness, InstantiateWitness(cast<Witness>(witness), source_loc));
   }
 
   if (args == bindings->args() && witnesses == bindings->witnesses()) {
@@ -763,11 +765,12 @@ auto Interpreter::InstantiateBindings(Nonnull<const Bindings*> bindings,
   return arena_->New<Bindings>(std::move(args), std::move(witnesses));
 }
 
-auto Interpreter::InstantiateWitness(Nonnull<const Witness*> witness)
+auto Interpreter::InstantiateWitness(Nonnull<const Witness*> witness,
+                                     SourceLocation source_loc)
     -> ErrorOr<Nonnull<const Witness*>> {
   CARBON_ASSIGN_OR_RETURN(
       Nonnull<const Value*> value,
-      EvalRecursively(std::make_unique<WitnessAction>(witness)));
+      EvalRecursively(std::make_unique<WitnessAction>(witness, source_loc)));
   return cast<Witness>(value);
 }
 
@@ -1406,8 +1409,8 @@ auto Interpreter::StepExp() -> ErrorOr<Success> {
             // Next, if we're accessing an interface member, evaluate the `impl`
             // expression to find the corresponding witness.
             if (impl_has_value) {
-              return todo_.Spawn(
-                  std::make_unique<WitnessAction>(access.impl().value()));
+              return todo_.Spawn(std::make_unique<WitnessAction>(
+                  access.impl().value(), access.source_loc()));
             } else {
               return todo_.RunAgain();
             }
@@ -1504,8 +1507,8 @@ auto Interpreter::StepExp() -> ErrorOr<Success> {
             if (impl_has_value) {
               // Next, if we're accessing an interface member, evaluate the
               // `impl` expression to find the corresponding witness.
-              return todo_.Spawn(
-                  std::make_unique<WitnessAction>(access.impl().value()));
+              return todo_.Spawn(std::make_unique<WitnessAction>(
+                  access.impl().value(), access.source_loc()));
             } else {
               return todo_.RunAgain();
             }
@@ -1648,8 +1651,8 @@ auto Interpreter::StepExp() -> ErrorOr<Success> {
                  act.pos() < 2 + static_cast<int>(num_witnesses)) {
         auto iter = call.witnesses().begin();
         std::advance(iter, act.pos() - 2);
-        return todo_.Spawn(
-            std::make_unique<WitnessAction>(cast<Witness>(iter->second)));
+        return todo_.Spawn(std::make_unique<WitnessAction>(
+            cast<Witness>(iter->second), call.source_loc()));
       } else if (act.pos() == 2 + static_cast<int>(num_witnesses)) {
         //    { { v2 :: v1([]) :: C, E, F} :: S, H}
         // -> { {C',E',F'} :: {C, E, F} :: S, H}
@@ -2011,8 +2014,8 @@ auto Interpreter::StepExp() -> ErrorOr<Success> {
 }
 
 auto Interpreter::StepWitness() -> ErrorOr<Success> {
-  Action& act = todo_.CurrentAction();
-  const Witness* witness = cast<WitnessAction>(act).witness();
+  auto& act = cast<WitnessAction>(todo_.CurrentAction());
+  const Witness* witness = act.witness();
   if (trace_stream_->is_enabled()) {
     *trace_stream_ << "--- step witness " << *witness << " ." << act.pos()
                    << ". --->\n";
@@ -2036,8 +2039,8 @@ auto Interpreter::StepWitness() -> ErrorOr<Success> {
       llvm::ArrayRef<Nonnull<const Witness*>> witnesses =
           cast<ConstraintWitness>(witness)->witnesses();
       if (act.pos() < static_cast<int>(witnesses.size())) {
-        return todo_.Spawn(
-            std::make_unique<WitnessAction>(witnesses[act.pos()]));
+        return todo_.Spawn(std::make_unique<WitnessAction>(witnesses[act.pos()],
+                                                           act.source_loc()));
       }
       std::vector<Nonnull<const Witness*>> new_witnesses;
       new_witnesses.reserve(witnesses.size());
@@ -2052,7 +2055,7 @@ auto Interpreter::StepWitness() -> ErrorOr<Success> {
       const auto* constraint_impl = cast<ConstraintImplWitness>(witness);
       if (act.pos() == 0) {
         return todo_.Spawn(std::make_unique<WitnessAction>(
-            constraint_impl->constraint_witness()));
+            constraint_impl->constraint_witness(), act.source_loc()));
       }
       return todo_.FinishAction(ConstraintImplWitness::Make(
           arena_, cast<Witness>(act.results()[0]), constraint_impl->index()));
@@ -2670,7 +2673,10 @@ auto InterpProgram(const AST& ast, Nonnull<Arena*> arena,
     *trace_stream << "********** initializing globals **********\n";
   }
 
+  SetFileContext set_file_ctx(*trace_stream,
+                              ast.declarations.front()->source_loc());
   for (Nonnull<Declaration*> declaration : ast.declarations) {
+    set_file_ctx.update_source_loc(declaration->source_loc());
     CARBON_RETURN_IF_ERROR(interpreter.RunAllSteps(
         std::make_unique<DeclarationAction>(declaration)));
   }
@@ -2679,6 +2685,8 @@ auto InterpProgram(const AST& ast, Nonnull<Arena*> arena,
     *trace_stream << "********** calling main function **********\n";
   }
 
+  CARBON_CHECK(ast.main_call);
+  set_file_ctx.update_source_loc(ast.main_call.value()->source_loc());
   CARBON_RETURN_IF_ERROR(interpreter.RunAllSteps(
       std::make_unique<ExpressionAction>(*ast.main_call)));
 

+ 4 - 10
explorer/interpreter/type_checker.cpp

@@ -28,6 +28,7 @@
 #include "explorer/common/error_builders.h"
 #include "explorer/common/nonnull.h"
 #include "explorer/common/source_location.h"
+#include "explorer/common/trace_stream.h"
 #include "explorer/interpreter/impl_scope.h"
 #include "explorer/interpreter/interpreter.h"
 #include "explorer/interpreter/pattern_analysis.h"
@@ -1022,6 +1023,7 @@ auto TypeChecker::ImplicitlyConvert(std::string_view context,
         ConvertToConstraintType(source->source_loc(), "implicit conversion",
                                 destination));
     destination = destination_constraint;
+
     if (trace_stream_->is_enabled()) {
       *trace_stream_ << "converting type " << *converted_value
                      << " to constraint " << *destination_constraint << " for "
@@ -6326,23 +6328,15 @@ auto TypeChecker::DeclareAliasDeclaration(Nonnull<AliasDeclaration*> alias,
 auto TypeChecker::TypeCheck(AST& ast) -> ErrorOr<Success> {
   ImplScope impl_scope;
   ScopeInfo top_level_scope_info = ScopeInfo::ForNonClassScope(&impl_scope);
+  SetFileContext set_file_ctx(*trace_stream_, std::nullopt);
 
   // Track that `impl_scope` is the top-level `ImplScope`.
   llvm::SaveAndRestore<decltype(top_level_impl_scope_)>
       set_top_level_impl_scope(top_level_impl_scope_, &impl_scope);
 
-  if (trace_stream_->is_enabled()) {
-    *trace_stream_ << "Omitting prelude type checking traces...\n";
-    trace_stream_->set_in_prelude(true);
-  }
   for (int i = 0; i < static_cast<int>(ast.declarations.size()); ++i) {
-    if (i == ast.num_prelude_declarations) {
-      trace_stream_->set_in_prelude(false);
-      if (trace_stream_->is_enabled()) {
-        *trace_stream_ << "Finished prelude, resuming traces...\n";
-      }
-    }
     auto* declaration = ast.declarations[i];
+    set_file_ctx.update_source_loc(declaration->source_loc());
     CARBON_RETURN_IF_ERROR(
         DeclareDeclaration(declaration, top_level_scope_info));
     CARBON_RETURN_IF_ERROR(

+ 11 - 11
explorer/lit_testdata/trace.carbon

@@ -6,17 +6,17 @@
 // sanity checking on --parser_debug --trace_file=- along with filter flags output.
 //
 // NOAUTOUPDATE
-// RUN: %{explorer} --parser_debug --trace_file=- | %{FileCheck-allow-unmatched} --check-prefixes=NO-SOURCE,NO-NAMES,NO-PRELUDE,NO-FLOW,NO-TYPE,NO-UNFORMED,NO-DECLS,EXEC,NO-TIMING
-// RUN: %{explorer} --parser_debug --trace_file=- -trace_phase=execution | %{FileCheck-allow-unmatched} --check-prefixes=NO-SOURCE,NO-NAMES,NO-PRELUDE,NO-FLOW,NO-TYPE,NO-UNFORMED,NO-DECLS,EXEC,NO-TIMING
-// RUN: %{explorer} --parser_debug --trace_file=- -trace_phase=source_program | %{FileCheck-allow-unmatched} --check-prefixes=SOURCE,NO-NAMES,NO-PRELUDE,NO-FLOW,NO-TYPE,NO-UNFORMED,NO-DECLS,NO-EXEC,NO-TIMING
-// RUN: %{explorer} --parser_debug --trace_file=- -trace_phase=name_resolution | %{FileCheck-allow-unmatched} --check-prefixes=NO-SOURCE,NAMES,NO-PRELUDE,NO-FLOW,NO-TYPE,NO-UNFORMED,NO-DECLS,NO-EXEC,NO-TIMING
-// RUN: %{explorer} --parser_debug --trace_file=- -trace_phase=control_flow_resolution | %{FileCheck-allow-unmatched} --check-prefixes=NO-SOURCE,NO-NAMES,NO-PRELUDE,FLOW,NO-TYPE,NO-UNFORMED,NO-DECLS,NO-EXEC,NO-TIMING
-// RUN: %{explorer} --parser_debug --trace_file=- -trace_phase=type_checking | %{FileCheck-allow-unmatched} --check-prefixes=NO-SOURCE,NO-NAMES,NO-PRELUDE,NO-FLOW,TYPE,NO-UNFORMED,NO-DECLS,NO-EXEC,NO-TIMING
-// RUN: %{explorer} --parser_debug --trace_file=- -trace_phase=unformed_variables_resolution | %{FileCheck-allow-unmatched} --check-prefixes=NO-SOURCE,NO-NAMES,NO-PRELUDE,NO-FLOW,NO-TYPE,UNFORMED,NO-DECLS,NO-EXEC,NO-TIMING
-// RUN: %{explorer} --parser_debug --trace_file=- -trace_phase=declarations | %{FileCheck-allow-unmatched} --check-prefixes=NO-SOURCE,NO-NAMES,NO-PRELUDE,NO-FLOW,NO-TYPE,NO-UNFORMED,DECLS,NO-EXEC,NO-TIMING
-// RUN: %{explorer} --parser_debug --trace_file=- -trace_phase=timing | %{FileCheck-allow-unmatched} --check-prefixes=NO-SOURCE,NO-NAMES,NO-PRELUDE,NO-FLOW,NO-TYPE,NO-UNFORMED,NO-DECLS,NO-EXEC,TIMING
-// RUN: %{explorer} --parser_debug --trace_file=- -trace_phase=all | %{FileCheck-allow-unmatched} --check-prefixes=SOURCE,NAMES,NO-PRELUDE,FLOW,TYPE,UNFORMED,DECLS,EXEC,TIMING
-// RUN: %{explorer} --parser_debug --trace_file=- -trace_phase=source_program,declarations | %{FileCheck-allow-unmatched} --check-prefixes=SOURCE,NO-NAMES,NO-PRELUDE,NO-FLOW,NO-TYPE,NO-UNFORMED,DECLS,NO-EXEC,NO-TIMING
+// RUN: %{explorer} --parser_debug --trace_file=- -trace_file_context=all | %{FileCheck-allow-unmatched} --check-prefixes=NO-SOURCE,NO-NAMES,NO-PRELUDE,NO-FLOW,NO-TYPE,NO-UNFORMED,NO-DECLS,EXEC,NO-TIMING
+// RUN: %{explorer} --parser_debug --trace_file=- -trace_file_context=all -trace_phase=execution | %{FileCheck-allow-unmatched} --check-prefixes=NO-SOURCE,NO-NAMES,NO-PRELUDE,NO-FLOW,NO-TYPE,NO-UNFORMED,NO-DECLS,EXEC,NO-TIMING
+// RUN: %{explorer} --parser_debug --trace_file=- -trace_file_context=all -trace_phase=source_program | %{FileCheck-allow-unmatched} --check-prefixes=SOURCE,NO-NAMES,NO-PRELUDE,NO-FLOW,NO-TYPE,NO-UNFORMED,NO-DECLS,NO-EXEC,NO-TIMING
+// RUN: %{explorer} --parser_debug --trace_file=- -trace_file_context=all -trace_phase=name_resolution | %{FileCheck-allow-unmatched} --check-prefixes=NO-SOURCE,NAMES,NO-PRELUDE,NO-FLOW,NO-TYPE,NO-UNFORMED,NO-DECLS,NO-EXEC,NO-TIMING
+// RUN: %{explorer} --parser_debug --trace_file=- -trace_file_context=all -trace_phase=control_flow_resolution | %{FileCheck-allow-unmatched} --check-prefixes=NO-SOURCE,NO-NAMES,NO-PRELUDE,FLOW,NO-TYPE,NO-UNFORMED,NO-DECLS,NO-EXEC,NO-TIMING
+// RUN: %{explorer} --parser_debug --trace_file=- -trace_file_context=all -trace_phase=type_checking | %{FileCheck-allow-unmatched} --check-prefixes=NO-SOURCE,NO-NAMES,NO-PRELUDE,NO-FLOW,TYPE,NO-UNFORMED,NO-DECLS,NO-EXEC,NO-TIMING
+// RUN: %{explorer} --parser_debug --trace_file=- -trace_file_context=all -trace_phase=unformed_variables_resolution | %{FileCheck-allow-unmatched} --check-prefixes=NO-SOURCE,NO-NAMES,NO-PRELUDE,NO-FLOW,NO-TYPE,UNFORMED,NO-DECLS,NO-EXEC,NO-TIMING
+// RUN: %{explorer} --parser_debug --trace_file=- -trace_file_context=all -trace_phase=declarations | %{FileCheck-allow-unmatched} --check-prefixes=NO-SOURCE,NO-NAMES,NO-PRELUDE,NO-FLOW,NO-TYPE,NO-UNFORMED,DECLS,NO-EXEC,NO-TIMING
+// RUN: %{explorer} --parser_debug --trace_file=- -trace_file_context=all -trace_phase=timing | %{FileCheck-allow-unmatched} --check-prefixes=NO-SOURCE,NO-NAMES,NO-PRELUDE,NO-FLOW,NO-TYPE,NO-UNFORMED,NO-DECLS,NO-EXEC,TIMING
+// RUN: %{explorer} --parser_debug --trace_file=- -trace_file_context=all -trace_phase=all | %{FileCheck-allow-unmatched} --check-prefixes=SOURCE,NAMES,NO-PRELUDE,FLOW,TYPE,UNFORMED,DECLS,EXEC,TIMING
+// RUN: %{explorer} --parser_debug --trace_file=- -trace_file_context=all -trace_phase=source_program,declarations | %{FileCheck-allow-unmatched} --check-prefixes=SOURCE,NO-NAMES,NO-PRELUDE,NO-FLOW,NO-TYPE,NO-UNFORMED,DECLS,NO-EXEC,NO-TIMING
 // NO-SOURCE-NOT:STDOUT: ********** source program **********
 //        SOURCE:STDOUT: ********** source program **********
 // NO-SOURCE-NOT:STDOUT: interface TestInterface {

+ 31 - 0
explorer/lit_testdata/trace_file_filters.carbon

@@ -0,0 +1,31 @@
+// 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
+//
+// A lot of output is elided: this is only checking for a few things for simple
+// sanity checking on --parser_debug --trace_file=- along with file context
+// filter flags output.
+//
+// NOAUTOUPDATE
+// RUN: %{explorer} --parser_debug --trace_file=- -trace_phase=all -trace_file_context=main | %{FileCheck-allow-unmatched} --check-prefixes=MAIN,NO-PRELUDE
+// RUN: %{explorer} --parser_debug --trace_file=- -trace_phase=all -trace_file_context=prelude | %{FileCheck-allow-unmatched} --check-prefixes=NO-MAIN,PRELUDE
+// RUN: %{explorer} --parser_debug --trace_file=- -trace_phase=all -trace_file_context=all | %{FileCheck-allow-unmatched} --check-prefixes=MAIN,PRELUDE
+// RUN: %{explorer} --parser_debug --trace_file=- -trace_phase=all -trace_file_context=main,prelude | %{FileCheck-allow-unmatched} --check-prefixes=MAIN,PRELUDE
+// NO-PRELUDE-NOT:STDOUT: ** declaring interface As
+//        PRELUDE:STDOUT: ** declaring interface As
+// NO-MAIN-NOT:STDOUT: ** declaring function Main
+//        MAIN:STDOUT: ** declaring function Main
+// NO-PRELUDE-NOT:STDOUT: interface As {
+//        PRELUDE:STDOUT: interface As {
+// NO-MAIN-NOT:STDOUT: fn Main ()-> i32 {
+//        MAIN:STDOUT: fn Main ()-> i32 {
+// NO-MAIN-NOT:STDOUT: --- step exp Main() .0. (<Main()>:0) --->
+//        MAIN:STDOUT: --- step exp Main() .0. (<Main()>:0) --->
+
+package ExplorerTest api;
+
+interface TestInterface {}
+
+fn Main() -> i32 {
+  return 0;
+}

+ 17 - 0
explorer/main.cpp

@@ -81,6 +81,22 @@ auto ExplorerMain(int argc, char** argv, void* static_for_main_addr,
                      "Include trace output for all phases.")),
       cl::CommaSeparated);
 
+  cl::list<FileContext> allowed_file_contexts(
+      "trace_file_context",
+      cl::desc("Select file contexts for which you want to include the trace "
+               "output"),
+      cl::values(
+          clEnumValN(
+              FileContext::Main, "main",
+              "Include trace output for file containing the main function"),
+          clEnumValN(FileContext::Prelude, "prelude",
+                     "Include trace output for prelude"),
+          clEnumValN(FileContext::Import, "import",
+                     "Include trace output for imports"),
+          clEnumValN(FileContext::All, "all",
+                     "Include trace output for all files")),
+      cl::CommaSeparated);
+
   // Use the executable path as a base for the relative prelude path.
   std::string exe =
       llvm::sys::fs::getMainExecutable(argv[0], static_for_main_addr);
@@ -102,6 +118,7 @@ auto ExplorerMain(int argc, char** argv, void* static_for_main_addr,
   if (!trace_file_name.empty()) {
     // Adding allowed phases in the trace_stream
     trace_stream.set_allowed_phases(allowed_program_phases);
+    trace_stream.set_allowed_file_contexts(allowed_file_contexts);
     if (trace_file_name == "-") {
       trace_stream.set_stream(&llvm::outs());
     } else {

+ 2 - 1139
explorer/trace_testdata/full_trace.carbon

@@ -15,8 +15,6 @@
 // CHECK:STDOUT: ********** resolving names **********
 // CHECK:STDOUT: ********** resolving control flow **********
 // CHECK:STDOUT: ********** type checking **********
-// CHECK:STDOUT: Omitting prelude type checking traces...
-// CHECK:STDOUT: Finished prelude, resuming traces...
 // CHECK:STDOUT: ** declaring interface TestInterface
 // CHECK:STDOUT: ** finished declaring interface TestInterface
 // CHECK:STDOUT: checking InterfaceDeclaration
@@ -37,7 +35,7 @@ package ExplorerTest api;
 
 interface TestInterface {}
 
-// CHECK:STDOUT: --- step exp i32 .0. (full_trace.carbon:[[@LINE+1184]]) --->
+// CHECK:STDOUT: --- step exp i32 .0. (full_trace.carbon:[[@LINE+49]]) --->
 // CHECK:STDOUT: {
 // CHECK:STDOUT: stack:{{ }}
 // CHECK:STDOUT: memory:{{ }}
@@ -75,1144 +73,9 @@ interface TestInterface {}
 // CHECK:STDOUT: ********** initializing globals **********
 // CHECK:STDOUT: {
 // CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl interface As .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl interface ImplicitAs .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl interface __EqualConverter .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl fn __EqualConvert .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl impl forall [U:! type] U as __EqualConverter where .T = U .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl match_first .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl impl forall [U1:! type, T1:! As(U1)] (T1) as As((U1)) .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl impl forall [U1:! type, U2:! type, T1:! As(U1), T2:! As(U2)] (T1, T2) as As((U1, U2)) .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl impl forall [U1:! type, U2:! type, U3:! type, T1:! As(U1), T2:! As(U2), T3:! As(U3)] (T1, T2, T3) as As((U1, U2, U3)) .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl interface EqWith .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl constraint Eq .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl impl forall [T2:! type, U2:! type, T1:! EqWith(T2), U1:! EqWith(U2)] (T1, U1) as EqWith((T2, U2)) .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl impl bool as EqWith(Self) .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl impl i32 as EqWith(Self) .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl impl String as EqWith(Self) .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl choice Ordering .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl interface CompareWith .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl constraint Ordered .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl impl i32 as CompareWith(Self) .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl impl String as CompareWith(Self) .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl interface LessWith .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl interface LessEqWith .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl interface GreaterWith .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl interface GreaterEqWith .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl impl i32 as LessWith(Self) .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl impl String as LessWith(Self) .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl impl i32 as LessEqWith(Self) .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl impl String as LessEqWith(Self) .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl impl i32 as GreaterWith(Self) .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl impl String as GreaterWith(Self) .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl impl i32 as GreaterEqWith(Self) .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl impl String as GreaterEqWith(Self) .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl interface Negate .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl interface AddWith .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl constraint Add .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl interface SubWith .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl constraint Sub .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl interface MulWith .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl constraint Mul .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl interface DivWith .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl constraint Div .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl interface ModWith .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl constraint Mod .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl impl i32 as Negate where .Result = i32 .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl impl i32 as AddWith(i32) where .Result = i32 .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl impl i32 as SubWith(i32) where .Result = i32 .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl impl i32 as MulWith(i32) where .Result = i32 .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl impl i32 as DivWith(i32) where .Result = i32 .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl impl i32 as ModWith(i32) where .Result = i32 .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl interface BitComplement .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl interface BitAndWith .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl constraint BitAnd .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl interface BitOrWith .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl constraint BitOr .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl interface BitXorWith .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl constraint BitXor .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl interface LeftShiftWith .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl constraint LeftShift .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl interface RightShiftWith .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl constraint RightShift .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl impl i32 as BitComplement where .Result = i32 .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl impl i32 as BitAndWith(i32) where .Result = i32 .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl impl i32 as BitOrWith(i32) where .Result = i32 .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl impl i32 as BitXorWith(i32) where .Result = i32 .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl impl i32 as LeftShiftWith(i32) where .Result = i32 .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl impl i32 as RightShiftWith(i32) where .Result = i32 .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl interface AssignWith .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl constraint Assign .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl interface AddAssignWith .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl constraint AddAssign .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl interface SubAssignWith .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl constraint SubAssign .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl interface MulAssignWith .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl constraint MulAssign .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl interface DivAssignWith .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl constraint DivAssign .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl interface ModAssignWith .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl constraint ModAssign .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl interface BitAndAssignWith .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl constraint BitAssignAnd .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl interface BitOrAssignWith .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl constraint BitAssignOr .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl interface BitXorAssignWith .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl constraint BitAssignXor .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl interface LeftShiftAssignWith .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl constraint LeftShiftAssign .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl interface RightShiftAssignWith .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl constraint RightShiftAssign .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl impl forall [T:! type, U:! ImplicitAs(T)] T as AssignWith(U) .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl impl forall [U:! type, T:! AddWith(U) where .Self impls AssignWith(.Self.Result)] T as AddAssignWith(U) .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl impl forall [U:! type, T:! SubWith(U) where .Self impls AssignWith(.Self.Result)] T as SubAssignWith(U) .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl impl forall [U:! type, T:! MulWith(U) where .Self impls AssignWith(.Self.Result)] T as MulAssignWith(U) .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl impl forall [U:! type, T:! DivWith(U) where .Self impls AssignWith(.Self.Result)] T as DivAssignWith(U) .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl impl forall [U:! type, T:! ModWith(U) where .Self impls AssignWith(.Self.Result)] T as ModAssignWith(U) .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl impl forall [U:! type, T:! BitAndWith(U) where .Self impls AssignWith(.Self.Result)] T as BitAndAssignWith(U) .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl impl forall [U:! type, T:! BitOrWith(U) where .Self impls AssignWith(.Self.Result)] T as BitOrAssignWith(U) .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl impl forall [U:! type, T:! BitXorWith(U) where .Self impls AssignWith(.Self.Result)] T as BitXorAssignWith(U) .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl impl forall [U:! type, T:! LeftShiftWith(U) where .Self impls AssignWith(.Self.Result)] T as LeftShiftAssignWith(U) .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl impl forall [U:! type, T:! RightShiftWith(U) where .Self impls AssignWith(.Self.Result)] T as RightShiftAssignWith(U) .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl interface Inc .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl interface Dec .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl impl i32 as Inc .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl impl i32 as Dec .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl fn Assert .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl fn Rand .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl choice OptionalElement .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl class Optional .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl class Heap .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl var heap: Heap .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack: {}.(interface ImplicitAs(T = class Heap).Convert)() .0. ## var heap: Heap = {}.(interface ImplicitAs(T = class Heap).Convert)();
-// CHECK:STDOUT:  .1.
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step exp {}.(interface ImplicitAs(T = class Heap).Convert)() .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack: {}.(interface ImplicitAs(T = class Heap).Convert) .0. ## {}.(interface ImplicitAs(T = class Heap).Convert)() .1. ## var heap: Heap = {}.(interface ImplicitAs(T = class Heap).Convert)();
-// CHECK:STDOUT:  .1.
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step exp {}.(interface ImplicitAs(T = class Heap).Convert) .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack: {} .0. ## {}.(interface ImplicitAs(T = class Heap).Convert) .1. ## {}.(interface ImplicitAs(T = class Heap).Convert)() .1. ## var heap: Heap = {}.(interface ImplicitAs(T = class Heap).Convert)();
-// CHECK:STDOUT:  .1.
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step exp {} .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack: {}.(interface ImplicitAs(T = class Heap).Convert) .1. {{[[][[]}}{}]] ## {}.(interface ImplicitAs(T = class Heap).Convert)() .1. ## var heap: Heap = {}.(interface ImplicitAs(T = class Heap).Convert)();
-// CHECK:STDOUT:  .1.
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step exp {}.(interface ImplicitAs(T = class Heap).Convert) .1. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack: witness for impl T as ImplicitAs(U) .0. ## {}.(interface ImplicitAs(T = class Heap).Convert) .2. {{[[][[]}}{}]] ## {}.(interface ImplicitAs(T = class Heap).Convert)() .1. ## var heap: Heap = {}.(interface ImplicitAs(T = class Heap).Convert)();
-// CHECK:STDOUT:  .1.
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step witness witness for impl T as ImplicitAs(U) .0. --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack: {}.(interface ImplicitAs(T = class Heap).Convert) .2. {{[[][[]}}{}, witness for impl T as ImplicitAs(U)]] ## {}.(interface ImplicitAs(T = class Heap).Convert)() .1. ## var heap: Heap = {}.(interface ImplicitAs(T = class Heap).Convert)();
-// CHECK:STDOUT:  .1.
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step exp {}.(interface ImplicitAs(T = class Heap).Convert) .2. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack: interface As(T = class Heap) .0. ## {}.(interface ImplicitAs(T = class Heap).Convert) .3. {{[[][[]}}{}, witness for impl T as ImplicitAs(U)]] ## {}.(interface ImplicitAs(T = class Heap).Convert)() .1. ## var heap: Heap = {}.(interface ImplicitAs(T = class Heap).Convert)();
-// CHECK:STDOUT:  .1.
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack: {}.(interface ImplicitAs(T = class Heap).Convert) .3. {{[[][[]}}{}, witness for impl T as ImplicitAs(U), interface As(T = class Heap)]] ## {}.(interface ImplicitAs(T = class Heap).Convert)() .1. ## var heap: Heap = {}.(interface ImplicitAs(T = class Heap).Convert)();
-// CHECK:STDOUT:  .1.
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step exp {}.(interface ImplicitAs(T = class Heap).Convert) .3. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack: {}.(interface ImplicitAs(T = class Heap).Convert) .4. {{[[][[]}}{}, witness for impl T as ImplicitAs(U), interface As(T = class Heap)]] ## {}.(interface ImplicitAs(T = class Heap).Convert)() .1. ## var heap: Heap = {}.(interface ImplicitAs(T = class Heap).Convert)();
-// CHECK:STDOUT:  .1.
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step exp {}.(interface ImplicitAs(T = class Heap).Convert) .4. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack: {}.(interface ImplicitAs(T = class Heap).Convert)() .1. {{[[][[]}}bound_method<Convert>]] ## var heap: Heap = {}.(interface ImplicitAs(T = class Heap).Convert)();
-// CHECK:STDOUT:  .1.
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step exp {}.(interface ImplicitAs(T = class Heap).Convert)() .1. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack: () .0. ## {}.(interface ImplicitAs(T = class Heap).Convert)() .2. {{[[][[]}}bound_method<Convert>]] ## var heap: Heap = {}.(interface ImplicitAs(T = class Heap).Convert)();
-// CHECK:STDOUT:  .1.
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step exp () .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack: {}.(interface ImplicitAs(T = class Heap).Convert)() .2. {{[[][[]}}bound_method<Convert>, ()]] ## var heap: Heap = {}.(interface ImplicitAs(T = class Heap).Convert)();
-// CHECK:STDOUT:  .1.
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step exp {}.(interface ImplicitAs(T = class Heap).Convert)() .2. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: calling function: bound_method<Convert>
-// CHECK:STDOUT: match pattern ()
-// CHECK:STDOUT: from value expression with value ()
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack: {return __intrinsic_implicit_as_convert(self, U);} .0. ## .0. {self: Self: {}} ## {}.(interface ImplicitAs(T = class Heap).Convert)() .3. {{[[][[]}}bound_method<Convert>, ()]] {} ## var heap: Heap = {}.(interface ImplicitAs(T = class Heap).Convert)();
-// CHECK:STDOUT:  .1.
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step stmt {return __intrinsic_implicit_as_convert(self, U);} .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack: return __intrinsic_implicit_as_convert(self, U); .0. ## {return __intrinsic_implicit_as_convert(self, U);} .1. {} ## .0. {self: Self: {}} ## {}.(interface ImplicitAs(T = class Heap).Convert)() .3. {{[[][[]}}bound_method<Convert>, ()]] {} ## var heap: Heap = {}.(interface ImplicitAs(T = class Heap).Convert)();
-// CHECK:STDOUT:  .1.
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step stmt return __intrinsic_implicit_as_convert(self, U); .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack: __intrinsic_implicit_as_convert(self, U) .0. ## return __intrinsic_implicit_as_convert(self, U); .1. ## {return __intrinsic_implicit_as_convert(self, U);} .1. {} ## .0. {self: Self: {}} ## {}.(interface ImplicitAs(T = class Heap).Convert)() .3. {{[[][[]}}bound_method<Convert>, ()]] {} ## var heap: Heap = {}.(interface ImplicitAs(T = class Heap).Convert)();
-// CHECK:STDOUT:  .1.
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step exp __intrinsic_implicit_as_convert(self, U) .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack: self .0. ## return __intrinsic_implicit_as_convert(self, U); .1. ## {return __intrinsic_implicit_as_convert(self, U);} .1. {} ## .0. {self: Self: {}} ## {}.(interface ImplicitAs(T = class Heap).Convert)() .3. {{[[][[]}}bound_method<Convert>, ()]] {} ## var heap: Heap = {}.(interface ImplicitAs(T = class Heap).Convert)();
-// CHECK:STDOUT:  .1.
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step exp self .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack: self .0. ## self .1. ## return __intrinsic_implicit_as_convert(self, U); .1. ## {return __intrinsic_implicit_as_convert(self, U);} .1. {} ## .0. {self: Self: {}} ## {}.(interface ImplicitAs(T = class Heap).Convert)() .3. {{[[][[]}}bound_method<Convert>, ()]] {} ## var heap: Heap = {}.(interface ImplicitAs(T = class Heap).Convert)();
-// CHECK:STDOUT:  .1.
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step exp self .0. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack: self .1. {{[[][[]}}{}]] ## return __intrinsic_implicit_as_convert(self, U); .1. ## {return __intrinsic_implicit_as_convert(self, U);} .1. {} ## .0. {self: Self: {}} ## {}.(interface ImplicitAs(T = class Heap).Convert)() .3. {{[[][[]}}bound_method<Convert>, ()]] {} ## var heap: Heap = {}.(interface ImplicitAs(T = class Heap).Convert)();
-// CHECK:STDOUT:  .1.
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step exp self .1. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack: class Heap .0. ## self .2. {{[[][[]}}{}]] ## return __intrinsic_implicit_as_convert(self, U); .1. ## {return __intrinsic_implicit_as_convert(self, U);} .1. {} ## .0. {self: Self: {}} ## {}.(interface ImplicitAs(T = class Heap).Convert)() .3. {{[[][[]}}bound_method<Convert>, ()]] {} ## var heap: Heap = {}.(interface ImplicitAs(T = class Heap).Convert)();
-// CHECK:STDOUT:  .1.
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack: self .2. {{[[][[]}}{}, class Heap]] ## return __intrinsic_implicit_as_convert(self, U); .1. ## {return __intrinsic_implicit_as_convert(self, U);} .1. {} ## .0. {self: Self: {}} ## {}.(interface ImplicitAs(T = class Heap).Convert)() .3. {{[[][[]}}bound_method<Convert>, ()]] {} ## var heap: Heap = {}.(interface ImplicitAs(T = class Heap).Convert)();
-// CHECK:STDOUT:  .1.
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step exp self .2. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack: return __intrinsic_implicit_as_convert(self, U); .1. {{[[][[]}}Heap{}]] ## {return __intrinsic_implicit_as_convert(self, U);} .1. {} ## .0. {self: Self: {}} ## {}.(interface ImplicitAs(T = class Heap).Convert)() .3. {{[[][[]}}bound_method<Convert>, ()]] {} ## var heap: Heap = {}.(interface ImplicitAs(T = class Heap).Convert)();
-// CHECK:STDOUT:  .1.
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step stmt return __intrinsic_implicit_as_convert(self, U); .1. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack: clean up.0. {} ## clean up.0. {self: Self: {}} ## {}.(interface ImplicitAs(T = class Heap).Convert)() .3. {{[[][[]}}bound_method<Convert>, (), Heap{}]] {} ## var heap: Heap = {}.(interface ImplicitAs(T = class Heap).Convert)();
-// CHECK:STDOUT:  .1.
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack: clean up.0. {self: Self: {}} ## {}.(interface ImplicitAs(T = class Heap).Convert)() .3. {{[[][[]}}bound_method<Convert>, (), Heap{}]] {} ## var heap: Heap = {}.(interface ImplicitAs(T = class Heap).Convert)();
-// CHECK:STDOUT:  .1.
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack: {}.(interface ImplicitAs(T = class Heap).Convert)() .3. {{[[][[]}}bound_method<Convert>, (), Heap{}]] {} ## var heap: Heap = {}.(interface ImplicitAs(T = class Heap).Convert)();
-// CHECK:STDOUT:  .1.
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step exp {}.(interface ImplicitAs(T = class Heap).Convert)() .3. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack: clean up.0. {} ## var heap: Heap = {}.(interface ImplicitAs(T = class Heap).Convert)();
-// CHECK:STDOUT:  .1. {{[[][[]}}Heap{}]]
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack: var heap: Heap = {}.(interface ImplicitAs(T = class Heap).Convert)();
-// CHECK:STDOUT:  .1. {{[[][[]}}Heap{}]]
-// CHECK:STDOUT: memory:{{ }}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl var heap: Heap .1. ({{.*}}/explorer/data/prelude.carbon:{{.*}}) --->
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
-// CHECK:STDOUT: memory: 0: Heap{}
-// CHECK:STDOUT: }
-// CHECK:STDOUT: {
-// CHECK:STDOUT: stack:{{ }}
 // CHECK:STDOUT: memory: 0: Heap{}
 // CHECK:STDOUT: }
-// CHECK:STDOUT: --- step decl interface TestInterface .0. (full_trace.carbon:[[@LINE-1177]]) --->
+// CHECK:STDOUT: --- step decl interface TestInterface .0. (full_trace.carbon:[[@LINE-42]]) --->
 // CHECK:STDOUT: {
 // CHECK:STDOUT: stack:{{ }}
 // CHECK:STDOUT: memory: 0: Heap{}