Просмотр исходного кода

Remove RuntimeError / CompilationError. (#2258)

Instead, work out the prefix for an error based on whether it was produced during parsing, semantic analysis, or when running the program.
Richard Smith 3 лет назад
Родитель
Сommit
8f0f69b65f
63 измененных файлов с 254 добавлено и 264 удалено
  1. 9 24
      common/error.h
  2. 6 6
      explorer/ast/declaration.cpp
  3. 1 1
      explorer/ast/expression.cpp
  4. 6 6
      explorer/ast/static_scope.cpp
  5. 1 9
      explorer/common/error_builders.h
  6. 1 18
      explorer/common/error_builders_test.cpp
  7. 2 0
      explorer/fuzzing/fuzzer_util.cpp
  8. 1 1
      explorer/interpreter/action_stack.cpp
  9. 1 1
      explorer/interpreter/builtins.cpp
  10. 11 3
      explorer/interpreter/exec_program.cpp
  11. 6 1
      explorer/interpreter/exec_program.h
  12. 2 2
      explorer/interpreter/heap.cpp
  13. 6 7
      explorer/interpreter/impl_scope.cpp
  14. 4 4
      explorer/interpreter/interpreter.cpp
  15. 6 6
      explorer/interpreter/resolve_control_flow.cpp
  16. 4 4
      explorer/interpreter/resolve_names.cpp
  17. 1 1
      explorer/interpreter/resolve_unformed.cpp
  18. 96 101
      explorer/interpreter/type_checker.cpp
  19. 8 8
      explorer/interpreter/value.cpp
  20. 37 18
      explorer/main.cpp
  21. 1 1
      explorer/syntax/parse_and_lex_context.cpp
  22. 1 1
      explorer/testdata/addr/fail_method_me_misspelled.carbon
  23. 1 1
      explorer/testdata/assoc_const/fail_anonymous.carbon
  24. 1 1
      explorer/testdata/basic_syntax/fail_block.carbon
  25. 1 1
      explorer/testdata/basic_syntax/fail_invalid_char.carbon
  26. 1 1
      explorer/testdata/basic_syntax/fail_invalid_integer.carbon
  27. 1 1
      explorer/testdata/basic_syntax/fail_invalid_integer_type.carbon
  28. 1 1
      explorer/testdata/basic_syntax/fail_missing_var.carbon
  29. 1 1
      explorer/testdata/basic_syntax/fail_unknown_intrinsic.carbon
  30. 1 1
      explorer/testdata/basic_syntax/fail_unsupported_integer_type.carbon
  31. 1 1
      explorer/testdata/basic_syntax/fail_var_named_self.carbon
  32. 1 1
      explorer/testdata/basic_syntax/not_compare_precedence.carbon
  33. 1 1
      explorer/testdata/class/fail_class_named_self.carbon
  34. 1 1
      explorer/testdata/experimental_continuation/fail_continuation_syntax.carbon
  35. 1 1
      explorer/testdata/generic_function/fail_missing_exclam.carbon
  36. 1 1
      explorer/testdata/global_variable/fail_named_self.carbon
  37. 1 1
      explorer/testdata/impl/fail_bad_member_kind.carbon
  38. 1 1
      explorer/testdata/import/fail_order.carbon
  39. 1 1
      explorer/testdata/interface/fail_bad_member_kind.carbon
  40. 1 1
      explorer/testdata/interface/fail_use_symbolic_member.carbon
  41. 1 1
      explorer/testdata/let/fail_global_named_self.carbon
  42. 1 1
      explorer/testdata/let/fail_local_named_self.carbon
  43. 1 1
      explorer/testdata/let/fail_tuple_pattern_let_context_nested.carbon
  44. 1 1
      explorer/testdata/let/fail_tuple_pattern_let_in_var.carbon
  45. 1 1
      explorer/testdata/match/fail_not_alternative.carbon
  46. 1 1
      explorer/testdata/mixin/fail_mix_in_global.carbon
  47. 1 1
      explorer/testdata/mixin/fail_mix_in_impl.carbon
  48. 1 1
      explorer/testdata/package/fail_missing.carbon
  49. 1 1
      explorer/testdata/string/fail_block_quotes_not_on_own_line.carbon
  50. 1 1
      explorer/testdata/string/fail_hex_lower.carbon
  51. 1 1
      explorer/testdata/string/fail_hex_truncated.carbon
  52. 1 1
      explorer/testdata/string/fail_invalid_escape.carbon
  53. 1 1
      explorer/testdata/string/fail_newline.carbon
  54. 1 1
      explorer/testdata/string/fail_octal.carbon
  55. 1 1
      explorer/testdata/string/fail_raw_block_more_hash_tags_on_left.carbon
  56. 1 1
      explorer/testdata/string/fail_raw_block_more_hash_tags_on_right.carbon
  57. 1 1
      explorer/testdata/string/fail_raw_block_quotes_not_on_own_line.carbon
  58. 1 1
      explorer/testdata/string/fail_raw_block_single_line.carbon
  59. 1 1
      explorer/testdata/string/fail_raw_more_hash_tags_on_left.carbon
  60. 1 1
      explorer/testdata/string/fail_raw_more_hash_tags_on_right.carbon
  61. 1 1
      explorer/testdata/string/fail_tab.carbon
  62. 1 1
      explorer/testdata/tuple/fail_index_var.carbon
  63. 3 1
      explorer/update_checks.py

+ 9 - 24
common/error.h

@@ -23,36 +23,27 @@ struct Success {};
 class [[nodiscard]] Error {
  public:
   // Represents an error state.
-  explicit Error(llvm::Twine prefix, llvm::Twine location, llvm::Twine message)
-      : prefix_(prefix.str()),
-        location_(location.str()),
-        message_(message.str()) {
+  explicit Error(llvm::Twine location, llvm::Twine message)
+      : location_(location.str()), message_(message.str()) {
     CARBON_CHECK(!message_.empty()) << "Errors must have a message.";
   }
 
-  // Represents an error with no associated prefix or location.
+  // Represents an error with no associated location.
   // TODO: Consider using two different types.
-  explicit Error(llvm::Twine message) : Error("", "", message) {}
+  explicit Error(llvm::Twine message) : Error("", message) {}
 
   Error(Error&& other) noexcept
-      : prefix_(std::move(other.prefix_)),
-        location_(std::move(other.location_)),
+      : location_(std::move(other.location_)),
         message_(std::move(other.message_)) {}
 
   // Prints the error string.
   void Print(llvm::raw_ostream& out) const {
-    if (!prefix().empty()) {
-      out << prefix() << ": ";
-    }
     if (!location().empty()) {
       out << location() << ": ";
     }
     out << message();
   }
 
-  // Returns the prefix to prepend to the error, such as "ERROR".
-  auto prefix() const -> const std::string& { return prefix_; }
-
   // Returns a string describing the location of the error, such as
   // "file.cc:123".
   auto location() const -> const std::string& { return location_; }
@@ -61,8 +52,6 @@ class [[nodiscard]] Error {
   auto message() const -> const std::string& { return message_; }
 
  private:
-  // A prefix, indicating the kind of error.
-  std::string prefix_;
   // The location associated with the error.
   std::string location_;
   // The error message.
@@ -138,13 +127,10 @@ class [[nodiscard]] ErrorOr {
 // `Error` and `ErrorOr<T>`.
 class ErrorBuilder {
  public:
-  explicit ErrorBuilder(std::string prefix, std::string location)
-      : prefix_(std::move(prefix)),
-        location_(std::move(location)),
+  explicit ErrorBuilder(std::string location = "")
+      : location_(std::move(location)),
         out_(std::make_unique<llvm::raw_string_ostream>(message_)) {}
 
-  explicit ErrorBuilder() : ErrorBuilder("", "") {}
-
   // Accumulates string message.
   template <typename T>
   [[nodiscard]] auto operator<<(const T& message) -> ErrorBuilder& {
@@ -153,16 +139,15 @@ class ErrorBuilder {
   }
 
   // NOLINTNEXTLINE(google-explicit-constructor): Implicit cast for returns.
-  operator Error() { return Error(prefix_, location_, message_); }
+  operator Error() { return Error(location_, message_); }
 
   template <typename T>
   // NOLINTNEXTLINE(google-explicit-constructor): Implicit cast for returns.
   operator ErrorOr<T>() {
-    return Error(prefix_, location_, message_);
+    return Error(location_, message_);
   }
 
  private:
-  std::string prefix_;
   std::string location_;
   std::string message_;
   // Use a pointer to allow move construction.

+ 6 - 6
explorer/ast/declaration.cpp

@@ -262,11 +262,11 @@ auto SplitDeducedParameters(
       case AstNodeKind::BindingPattern: {
         Nonnull<BindingPattern*> binding = &cast<BindingPattern>(*param);
         if (binding->name() != "me") {
-          return CompilationError(source_loc)
+          return ProgramError(source_loc)
                  << "illegal binding pattern in implicit parameter list";
         }
         if (result.me_pattern.has_value()) {
-          return CompilationError(source_loc)
+          return ProgramError(source_loc)
                  << "parameter list cannot contain more than one `me` "
                     "parameter";
         }
@@ -278,11 +278,11 @@ auto SplitDeducedParameters(
         Nonnull<BindingPattern*> binding =
             &cast<BindingPattern>(addr_pattern->binding());
         if (binding->name() != "me") {
-          return CompilationError(source_loc)
+          return ProgramError(source_loc)
                  << "illegal binding pattern in implicit parameter list";
         }
         if (result.me_pattern.has_value()) {
-          return CompilationError(source_loc)
+          return ProgramError(source_loc)
                  << "parameter list cannot contain more than one `me` "
                     "parameter";
         }
@@ -290,7 +290,7 @@ auto SplitDeducedParameters(
         break;
       }
       default:
-        return CompilationError(source_loc)
+        return ProgramError(source_loc)
                << "illegal AST node in implicit parameter list";
     }
   }
@@ -360,7 +360,7 @@ auto ImplDeclaration::Create(Nonnull<Arena*> arena, SourceLocation source_loc,
         resolved_params.push_back(&cast<GenericBinding>(*param));
         break;
       default:
-        return CompilationError(source_loc)
+        return ProgramError(source_loc)
                << "illegal AST node in implicit parameter list of impl";
     }
   }

+ 1 - 1
explorer/ast/expression.cpp

@@ -45,7 +45,7 @@ auto IntrinsicExpression::FindIntrinsic(std::string_view name,
   name.remove_prefix(std::strlen("__intrinsic_"));
   auto it = intrinsic_map.find(name);
   if (it == intrinsic_map.end()) {
-    return CompilationError(source_loc) << "Unknown intrinsic '" << name << "'";
+    return ProgramError(source_loc) << "Unknown intrinsic '" << name << "'";
   }
   return it->second;
 }

+ 6 - 6
explorer/ast/static_scope.cpp

@@ -17,7 +17,7 @@ auto StaticScope::Add(const std::string& name, ValueNodeView entity,
   auto [it, inserted] = declared_names_.insert({name, {entity, status}});
   if (!inserted) {
     if (it->second.entity != entity) {
-      return CompilationError(entity.base().source_loc())
+      return ProgramError(entity.base().source_loc())
              << "Duplicate name `" << name << "` also found at "
              << it->second.entity.base().source_loc();
     }
@@ -48,7 +48,7 @@ auto StaticScope::Resolve(const std::string& name,
   CARBON_ASSIGN_OR_RETURN(std::optional<ValueNodeView> result,
                           TryResolve(name, source_loc));
   if (!result) {
-    return CompilationError(source_loc) << "could not resolve '" << name << "'";
+    return ProgramError(source_loc) << "could not resolve '" << name << "'";
   }
   return *result;
 }
@@ -60,10 +60,10 @@ auto StaticScope::TryResolve(const std::string& name,
   if (it != declared_names_.end()) {
     switch (it->second.status) {
       case NameStatus::KnownButNotDeclared:
-        return CompilationError(source_loc)
+        return ProgramError(source_loc)
                << "'" << name << "' has not been declared yet";
       case NameStatus::DeclaredButNotUsable:
-        return CompilationError(source_loc)
+        return ProgramError(source_loc)
                << "'" << name
                << "' is not usable until after it has been completely declared";
       case NameStatus::Usable:
@@ -76,7 +76,7 @@ auto StaticScope::TryResolve(const std::string& name,
                             parent->TryResolve(name, source_loc));
     if (parent_result.has_value() && result.has_value() &&
         *parent_result != *result) {
-      return CompilationError(source_loc)
+      return ProgramError(source_loc)
              << "'" << name << "' is ambiguous between "
              << result->base().source_loc() << " and "
              << parent_result->base().source_loc();
@@ -90,7 +90,7 @@ auto StaticScope::AddReturnedVar(ValueNodeView returned_var_def_view)
     -> ErrorOr<Success> {
   std::optional<ValueNodeView> resolved_returned_var = ResolveReturned();
   if (resolved_returned_var.has_value()) {
-    return CompilationError(returned_var_def_view.base().source_loc())
+    return ProgramError(returned_var_def_view.base().source_loc())
            << "Duplicate definition of returned var also found at "
            << resolved_returned_var->base().source_loc();
   }

+ 1 - 9
explorer/common/error_builders.h

@@ -21,16 +21,8 @@ namespace Carbon {
 // Use CHECK/FATAL for internal errors. The generic program error option is
 // provided as a fallback for cases that don't fit those classifications.
 
-inline auto CompilationError(SourceLocation loc) -> ErrorBuilder {
-  return ErrorBuilder("COMPILATION ERROR", loc.ToString());
-}
-
 inline auto ProgramError(SourceLocation loc) -> ErrorBuilder {
-  return ErrorBuilder("PROGRAM ERROR", loc.ToString());
-}
-
-inline auto RuntimeError(SourceLocation loc) -> ErrorBuilder {
-  return ErrorBuilder("RUNTIME ERROR", loc.ToString());
+  return ErrorBuilder(loc.ToString());
 }
 
 }  // namespace Carbon

+ 1 - 18
explorer/common/error_builders_test.cpp

@@ -18,28 +18,11 @@ auto ToString(const Error& err) -> std::string {
   return result;
 }
 
-TEST(ErrorBuildersTest, CompilationError) {
-  Error err = CompilationError(SourceLocation("x", 1)) << "test";
-  EXPECT_EQ(err.prefix(), "COMPILATION ERROR");
-  EXPECT_EQ(err.location(), "x:1");
-  EXPECT_EQ(err.message(), "test");
-  EXPECT_EQ(ToString(err), "COMPILATION ERROR: x:1: test");
-}
-
 TEST(ErrorBuildersTest, ProgramError) {
   Error err = ProgramError(SourceLocation("x", 1)) << "test";
-  EXPECT_EQ(err.prefix(), "PROGRAM ERROR");
-  EXPECT_EQ(err.location(), "x:1");
-  EXPECT_EQ(err.message(), "test");
-  EXPECT_EQ(ToString(err), "PROGRAM ERROR: x:1: test");
-}
-
-TEST(ErrorBuildersTest, RuntimeError) {
-  Error err = RuntimeError(SourceLocation("x", 1)) << "test";
-  EXPECT_EQ(err.prefix(), "RUNTIME ERROR");
   EXPECT_EQ(err.location(), "x:1");
   EXPECT_EQ(err.message(), "test");
-  EXPECT_EQ(ToString(err), "RUNTIME ERROR: x:1: test");
+  EXPECT_EQ(ToString(err), "x:1: test");
 }
 
 }  // namespace

+ 2 - 0
explorer/fuzzing/fuzzer_util.cpp

@@ -83,6 +83,8 @@ auto ParseAndExecute(const Fuzzing::CompilationUnit& compilation_unit)
   CARBON_CHECK(prelude_path.ok()) << prelude_path.error();
 
   AddPrelude(*prelude_path, &arena, &ast.declarations);
+  CARBON_ASSIGN_OR_RETURN(
+      ast, AnalyzeProgram(&arena, ast, /*trace_stream=*/std::nullopt));
   return ExecProgram(&arena, ast, /*trace_stream=*/std::nullopt);
 }
 

+ 1 - 1
explorer/interpreter/action_stack.cpp

@@ -91,7 +91,7 @@ auto ActionStack::ValueOfNode(ValueNodeView value_node,
     }
   }
   // TODO: Move these errors to compile time and explain them more clearly.
-  return RuntimeError(source_loc)
+  return ProgramError(source_loc)
          << "could not find `" << value_node.base() << "`";
 }
 

+ 1 - 1
explorer/interpreter/builtins.cpp

@@ -32,7 +32,7 @@ auto Builtins::Get(SourceLocation source_loc, Builtin builtin) const
   std::optional<const Declaration*> result =
       builtins_[static_cast<int>(builtin)];
   if (!result.has_value()) {
-    return CompilationError(source_loc)
+    return ProgramError(source_loc)
            << "missing declaration for builtin `" << GetName(builtin) << "`";
   }
   return result.value();

+ 11 - 3
explorer/interpreter/exec_program.cpp

@@ -18,9 +18,9 @@
 
 namespace Carbon {
 
-auto ExecProgram(Nonnull<Arena*> arena, AST ast,
-                 std::optional<Nonnull<llvm::raw_ostream*>> trace_stream)
-    -> ErrorOr<int> {
+auto AnalyzeProgram(Nonnull<Arena*> arena, AST ast,
+                    std::optional<Nonnull<llvm::raw_ostream*>> trace_stream)
+    -> ErrorOr<AST> {
   if (trace_stream) {
     **trace_stream << "********** source program **********\n";
     for (const auto decl : ast.declarations) {
@@ -54,6 +54,14 @@ auto ExecProgram(Nonnull<Arena*> arena, AST ast,
     for (const auto decl : ast.declarations) {
       **trace_stream << *decl;
     }
+  }
+  return ast;
+}
+
+auto ExecProgram(Nonnull<Arena*> arena, AST ast,
+                 std::optional<Nonnull<llvm::raw_ostream*>> trace_stream)
+    -> ErrorOr<int> {
+  if (trace_stream) {
     **trace_stream << "********** starting execution **********\n";
   }
   return InterpProgram(ast, arena, trace_stream);

+ 6 - 1
explorer/interpreter/exec_program.h

@@ -14,7 +14,12 @@
 
 namespace Carbon {
 
-// Runs the top-level declaration list.
+// Perform semantic analysis on the AST.
+auto AnalyzeProgram(Nonnull<Arena*> arena, AST ast,
+                    std::optional<Nonnull<llvm::raw_ostream*>> trace_stream)
+    -> ErrorOr<AST>;
+
+// Run the program's `Main` function.
 auto ExecProgram(Nonnull<Arena*> arena, AST ast,
                  std::optional<Nonnull<llvm::raw_ostream*>> trace_stream)
     -> ErrorOr<int>;

+ 2 - 2
explorer/interpreter/heap.cpp

@@ -49,7 +49,7 @@ auto Heap::Write(const Address& a, Nonnull<const Value*> v,
 auto Heap::CheckAlive(AllocationId allocation, SourceLocation source_loc) const
     -> ErrorOr<Success> {
   if (states_[allocation.index_] == ValueState::Dead) {
-    return RuntimeError(source_loc)
+    return ProgramError(source_loc)
            << "undefined behavior: access to dead value "
            << *values_[allocation.index_];
   }
@@ -59,7 +59,7 @@ auto Heap::CheckAlive(AllocationId allocation, SourceLocation source_loc) const
 auto Heap::CheckInit(AllocationId allocation, SourceLocation source_loc) const
     -> ErrorOr<Success> {
   if (states_[allocation.index_] == ValueState::Uninitialized) {
-    return RuntimeError(source_loc)
+    return ProgramError(source_loc)
            << "undefined behavior: access to uninitialized value "
            << *values_[allocation.index_];
   }

+ 6 - 7
explorer/interpreter/impl_scope.cpp

@@ -111,8 +111,8 @@ auto ImplScope::ResolveInterface(Nonnull<const InterfaceType*> iface_type,
       std::optional<Nonnull<const Witness*>> result,
       TryResolve(iface_type, type, source_loc, *this, type_checker));
   if (!result.has_value()) {
-    return CompilationError(source_loc) << "could not find implementation of "
-                                        << *iface_type << " for " << *type;
+    return ProgramError(source_loc) << "could not find implementation of "
+                                    << *iface_type << " for " << *type;
   }
   return *result;
 }
@@ -133,8 +133,8 @@ auto ImplScope::TryResolve(Nonnull<const InterfaceType*> iface_type,
                            type_checker));
     if (parent_result.has_value()) {
       if (result.has_value()) {
-        return CompilationError(source_loc) << "ambiguous implementations of "
-                                            << *iface_type << " for " << *type;
+        return ProgramError(source_loc) << "ambiguous implementations of "
+                                        << *iface_type << " for " << *type;
       } else {
         result = *parent_result;
       }
@@ -155,9 +155,8 @@ auto ImplScope::ResolveHere(Nonnull<const InterfaceType*> iface_type,
         *iface_type, impl_type, impl, original_scope, source_loc);
     if (m.has_value()) {
       if (result.has_value()) {
-        return CompilationError(source_loc)
-               << "ambiguous implementations of " << *iface_type << " for "
-               << *impl_type;
+        return ProgramError(source_loc) << "ambiguous implementations of "
+                                        << *iface_type << " for " << *impl_type;
       } else {
         result = *m;
       }

+ 4 - 4
explorer/interpreter/interpreter.cpp

@@ -533,7 +533,7 @@ auto Interpreter::EvalAssociatedConstant(
   if (!isa<ImplWitness>(witness)) {
     CARBON_CHECK(phase() == Phase::CompileTime)
         << "symbolic witnesses should only be formed at compile time";
-    return CompilationError(source_loc)
+    return ProgramError(source_loc)
            << "value of associated constant " << *assoc << " is not known";
   }
 
@@ -893,7 +893,7 @@ auto Interpreter::CallFunction(const CallExpression& call,
       }
     }
     default:
-      return RuntimeError(call.source_loc())
+      return ProgramError(call.source_loc())
              << "in call, expected a function, not " << *fun;
   }
 }
@@ -921,7 +921,7 @@ auto Interpreter::StepExp() -> ErrorOr<Success> {
         const auto& tuple = cast<TupleValue>(*act.results()[0]);
         int i = cast<IntValue>(*act.results()[1]).value();
         if (i < 0 || i >= static_cast<int>(tuple.elements().size())) {
-          return RuntimeError(exp.source_loc())
+          return ProgramError(exp.source_loc())
                  << "index " << i << " out of range in " << tuple;
         }
         return todo_.FinishAction(tuple.elements()[i]);
@@ -1228,7 +1228,7 @@ auto Interpreter::StepExp() -> ErrorOr<Success> {
               Nonnull<const Value*> string_value,
               Convert(args[1], arena_->New<StringType>(), exp.source_loc()));
           if (cast<BoolValue>(condition)->value() == false) {
-            return RuntimeError(exp.source_loc()) << *string_value;
+            return ProgramError(exp.source_loc()) << *string_value;
           }
           return todo_.FinishAction(TupleValue::Empty());
         }

+ 6 - 6
explorer/interpreter/resolve_control_flow.cpp

@@ -40,14 +40,14 @@ static auto ResolveControlFlow(Nonnull<Statement*> statement,
     case StatementKind::ReturnVar:
     case StatementKind::ReturnExpression: {
       if (!function.has_value()) {
-        return CompilationError(statement->source_loc())
+        return ProgramError(statement->source_loc())
                << "return is not within a function body";
       }
       const ReturnTerm& function_return =
           (*function)->declaration->return_term();
       if (function_return.is_auto()) {
         if ((*function)->saw_return_in_auto) {
-          return CompilationError(statement->source_loc())
+          return ProgramError(statement->source_loc())
                  << "Only one return is allowed in a function with an `auto` "
                     "return type.";
         }
@@ -57,7 +57,7 @@ static auto ResolveControlFlow(Nonnull<Statement*> statement,
       ret.set_function((*function)->declaration);
       if (statement->kind() == StatementKind::ReturnVar &&
           function_return.is_omitted()) {
-        return CompilationError(statement->source_loc())
+        return ProgramError(statement->source_loc())
                << *statement
                << " should not provide a return value, to match the function's "
                   "signature.";
@@ -65,7 +65,7 @@ static auto ResolveControlFlow(Nonnull<Statement*> statement,
       if (statement->kind() == StatementKind::ReturnExpression) {
         auto& ret_exp = cast<ReturnExpression>(*statement);
         if (ret_exp.is_omitted_expression() != function_return.is_omitted()) {
-          return CompilationError(ret_exp.source_loc())
+          return ProgramError(ret_exp.source_loc())
                  << ret_exp << " should"
                  << (function_return.is_omitted() ? " not" : "")
                  << " provide a return value, to match the function's "
@@ -77,14 +77,14 @@ static auto ResolveControlFlow(Nonnull<Statement*> statement,
     }
     case StatementKind::Break:
       if (!loop.has_value()) {
-        return CompilationError(statement->source_loc())
+        return ProgramError(statement->source_loc())
                << "break is not within a loop body";
       }
       cast<Break>(*statement).set_loop(*loop);
       return Success();
     case StatementKind::Continue:
       if (!loop.has_value()) {
-        return CompilationError(statement->source_loc())
+        return ProgramError(statement->source_loc())
                << "continue is not within a loop body";
       }
       cast<Continue>(*statement).set_loop(*loop);

+ 4 - 4
explorer/interpreter/resolve_names.cpp

@@ -268,7 +268,7 @@ static auto ResolveNames(Expression& expression,
     case ExpressionKind::ValueLiteral:
       break;
     case ExpressionKind::UnimplementedExpression:
-      return CompilationError(expression.source_loc()) << "Unimplemented";
+      return ProgramError(expression.source_loc()) << "Unimplemented";
   }
   return Success();
 }
@@ -395,7 +395,7 @@ static auto ResolveNames(Statement& statement, StaticScope& enclosing_scope)
       std::optional<ValueNodeView> returned_var_def_view =
           enclosing_scope.ResolveReturned();
       if (!returned_var_def_view.has_value()) {
-        return CompilationError(ret_var_stmt.source_loc())
+        return ProgramError(ret_var_stmt.source_loc())
                << "`return var` is not allowed without a returned var defined "
                   "in scope.";
       }
@@ -407,7 +407,7 @@ static auto ResolveNames(Statement& statement, StaticScope& enclosing_scope)
       std::optional<ValueNodeView> returned_var_def_view =
           enclosing_scope.ResolveReturned();
       if (returned_var_def_view.has_value()) {
-        return CompilationError(ret_exp_stmt.source_loc())
+        return ProgramError(ret_exp_stmt.source_loc())
                << "`return <expression>` is not allowed with a returned var "
                   "defined in scope: "
                << returned_var_def_view->base().source_loc();
@@ -619,7 +619,7 @@ static auto ResolveNames(Declaration& declaration, StaticScope& enclosing_scope,
         CARBON_RETURN_IF_ERROR(
             ResolveNames(alternative->signature(), choice_scope));
         if (!alternative_names.insert(alternative->name()).second) {
-          return CompilationError(alternative->source_loc())
+          return ProgramError(alternative->source_loc())
                  << "Duplicate name `" << alternative->name()
                  << "` in choice type";
         }

+ 1 - 1
explorer/interpreter/resolve_unformed.cpp

@@ -43,7 +43,7 @@ auto FlowFacts::TakeAction(Nonnull<const AstNode*> node, ActionType action,
       auto entry = facts_.find(node);
       if (entry != facts_.end() &&
           entry->second.formed_state == FormedState::Unformed) {
-        return CompilationError(source_loc)
+        return ProgramError(source_loc)
                << "use of uninitialized variable " << name;
       }
       break;

+ 96 - 101
explorer/interpreter/type_checker.cpp

@@ -55,9 +55,8 @@ struct TypeChecker::SingleStepEqualityContext : public EqualityContext {
     if (impl_witness) {
       return impl_witness;
     }
-    return CompilationError(source_loc)
-           << "value of associated constant " << *assoc
-           << " depends on a generic parameter";
+    return ProgramError(source_loc) << "value of associated constant " << *assoc
+                                    << " depends on a generic parameter";
   }
 
   // Visits the values that are equal to the given value and a single step away
@@ -139,9 +138,9 @@ auto TypeChecker::ExpectExactType(SourceLocation source_loc,
                                   const ImplScope& impl_scope) const
     -> ErrorOr<Success> {
   if (!IsSameType(expected, actual, impl_scope)) {
-    return CompilationError(source_loc) << "type error in " << context << "\n"
-                                        << "expected: " << *expected << "\n"
-                                        << "actual: " << *actual;
+    return ProgramError(source_loc) << "type error in " << context << "\n"
+                                    << "expected: " << *expected << "\n"
+                                    << "actual: " << *actual;
   }
   return Success();
 }
@@ -152,9 +151,9 @@ static auto ExpectPointerType(SourceLocation source_loc,
     -> ErrorOr<Success> {
   // TODO: Try to resolve in equality context.
   if (actual->kind() != Value::Kind::PointerType) {
-    return CompilationError(source_loc) << "type error in " << context << "\n"
-                                        << "expected a pointer type\n"
-                                        << "actual: " << *actual;
+    return ProgramError(source_loc) << "type error in " << context << "\n"
+                                    << "expected a pointer type\n"
+                                    << "actual: " << *actual;
   }
   return Success();
 }
@@ -307,8 +306,7 @@ auto TypeChecker::ExpectIsType(SourceLocation source_loc,
                                Nonnull<const Value*> value)
     -> ErrorOr<Success> {
   if (!IsType(value)) {
-    return CompilationError(source_loc)
-           << "Expected a type, but got " << *value;
+    return ProgramError(source_loc) << "Expected a type, but got " << *value;
   } else {
     return Success();
   }
@@ -324,8 +322,7 @@ auto TypeChecker::ExpectIsConcreteType(SourceLocation source_loc,
                                        Nonnull<const Value*> value)
     -> ErrorOr<Success> {
   if (!IsConcreteType(value)) {
-    return CompilationError(source_loc)
-           << "Expected a type, but got " << *value;
+    return ProgramError(source_loc) << "Expected a type, but got " << *value;
   } else {
     return Success();
   }
@@ -543,7 +540,7 @@ auto TypeChecker::ImplicitlyConvert(const std::string& context,
       BuiltinMethodCall{"Convert"});
   if (!converted.ok()) {
     // We couldn't find a matching `impl`.
-    return CompilationError(source->source_loc())
+    return ProgramError(source->source_loc())
            << "type error in " << context << ": "
            << "'" << *source_type << "' is not implicitly convertible to '"
            << *destination << "'";
@@ -555,7 +552,7 @@ auto TypeChecker::GetBuiltinInterfaceType(SourceLocation source_loc,
                                           BuiltinInterfaceName interface) const
     -> ErrorOr<Nonnull<const InterfaceType*>> {
   auto bad_builtin = [&]() -> Error {
-    return CompilationError(source_loc)
+    return ProgramError(source_loc)
            << "unsupported declaration for builtin `"
            << Builtins::GetName(interface.builtin) << "`";
   };
@@ -623,7 +620,7 @@ auto TypeChecker::ExpectType(SourceLocation source_loc,
     -> ErrorOr<Success> {
   if (!IsImplicitlyConvertible(actual, expected, impl_scope,
                                /*allow_user_defined_conversions=*/true)) {
-    return CompilationError(source_loc)
+    return ProgramError(source_loc)
            << "type error in " << context << ": "
            << "'" << *actual << "' is not implicitly convertible to '"
            << *expected << "'";
@@ -656,9 +653,9 @@ auto TypeChecker::ArgumentDeduction(
       // Parameter type contains a nested `auto` and argument type isn't the
       // same kind of type.
       // TODO: This seems like something we should be able to accept.
-      return CompilationError(source_loc) << "type error in " << context << "\n"
-                                          << "expected: " << *param << "\n"
-                                          << "actual: " << *arg;
+      return ProgramError(source_loc) << "type error in " << context << "\n"
+                                      << "expected: " << *param << "\n"
+                                      << "actual: " << *arg;
     }
     const Value* subst_param_type = Substitute(deduced, param);
     return allow_implicit_conversion
@@ -676,7 +673,7 @@ auto TypeChecker::ArgumentDeduction(
         const Value* binding_type = Substitute(deduced, &binding.static_type());
         if (!IsTypeOfType(binding_type)) {
           if (!IsImplicitlyConvertible(arg, binding_type, impl_scope, false)) {
-            return CompilationError(source_loc)
+            return ProgramError(source_loc)
                    << "cannot convert deduced value " << *arg << " for "
                    << binding.name() << " to parameter type " << *binding_type;
           }
@@ -693,7 +690,7 @@ auto TypeChecker::ArgumentDeduction(
           // should be used, and we'd need to check all pairs of types for
           // equality because our notion of equality is non-transitive.
           if (!TypeEqual(it->second, arg, std::nullopt)) {
-            return CompilationError(source_loc)
+            return ProgramError(source_loc)
                    << "deduced multiple different values for "
                    << var_type.binding() << ":\n  " << *it->second << "\n  "
                    << *arg;
@@ -711,7 +708,7 @@ auto TypeChecker::ArgumentDeduction(
       const auto& param_tup = cast<TupleValue>(*param);
       const auto& arg_tup = cast<TupleValue>(*arg);
       if (param_tup.elements().size() != arg_tup.elements().size()) {
-        return CompilationError(source_loc)
+        return ProgramError(source_loc)
                << "mismatch in tuple sizes, expected "
                << param_tup.elements().size() << " but got "
                << arg_tup.elements().size();
@@ -735,7 +732,7 @@ auto TypeChecker::ArgumentDeduction(
                                         bool missing_from_source) -> Error {
         static constexpr const char* SourceOrDestination[2] = {"source",
                                                                "destination"};
-        return CompilationError(source_loc)
+        return ProgramError(source_loc)
                << "mismatch in field names, "
                << SourceOrDestination[missing_from_source ? 1 : 0] << " field `"
                << field.name << "` not in "
@@ -758,7 +755,7 @@ auto TypeChecker::ArgumentDeduction(
           }
           arg_field = arg_struct.fields()[i];
           if (param_field.name != arg_field.name) {
-            return CompilationError(source_loc)
+            return ProgramError(source_loc)
                    << "mismatch in field names, `" << param_field.name
                    << "` != `" << arg_field.name << "`";
           }
@@ -894,9 +891,8 @@ auto TypeChecker::ArgumentDeduction(
       // TODO: Deduce within the values where possible.
       // TODO: Consider in-scope value equalities here.
       if (!ValueEqual(param, arg, std::nullopt)) {
-        return CompilationError(source_loc)
-               << "mismatch in non-type values, `" << *arg << "` != `" << *param
-               << "`";
+        return ProgramError(source_loc) << "mismatch in non-type values, `"
+                                        << *arg << "` != `" << *param << "`";
       }
       return Success();
     }
@@ -1352,7 +1348,7 @@ auto TypeChecker::DeduceCallBindings(
   llvm::ArrayRef<Nonnull<const Expression*>> args =
       cast<TupleLiteral>(call.argument()).fields();
   if (params.size() != args.size()) {
-    return CompilationError(call.source_loc())
+    return ProgramError(call.source_loc())
            << "wrong number of arguments in function call, expected "
            << params.size() << " but got " << args.size();
   }
@@ -1393,7 +1389,7 @@ auto TypeChecker::DeduceCallBindings(
     // has been added to the type checking of function signatures.
     if (auto it = generic_bindings.find(deduced_param);
         it == generic_bindings.end()) {
-      return CompilationError(call.source_loc())
+      return ProgramError(call.source_loc())
              << "could not deduce type argument for type parameter "
              << deduced_param->name() << "\n"
              << "in " << call;
@@ -1466,7 +1462,7 @@ static auto LookupInConstraint(SourceLocation source_loc,
         }
         // TODO: If we resolve to the same member either way, this
         // is not ambiguous.
-        return CompilationError(source_loc)
+        return ProgramError(source_loc)
                << "ambiguous " << lookup_kind << ", " << member_name
                << " found in " << *found->interface << " and " << iface_type;
       }
@@ -1476,10 +1472,10 @@ static auto LookupInConstraint(SourceLocation source_loc,
 
   if (!found) {
     if (isa<TypeType>(type)) {
-      return CompilationError(source_loc)
+      return ProgramError(source_loc)
              << lookup_kind << " in unconstrained type";
     }
-    return CompilationError(source_loc)
+    return ProgramError(source_loc)
            << lookup_kind << ", " << member_name << " not in " << *type;
   }
   return found.value();
@@ -1520,7 +1516,7 @@ auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e,
               InterpExp(&index.offset(), arena_, trace_stream_));
           int i = cast<IntValue>(*offset_value).value();
           if (i < 0 || i >= static_cast<int>(tuple_type.elements().size())) {
-            return CompilationError(e->source_loc())
+            return ProgramError(e->source_loc())
                    << "index " << i << " is out of range for type "
                    << tuple_type;
           }
@@ -1539,7 +1535,7 @@ auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e,
           return Success();
         }
         default:
-          return CompilationError(e->source_loc()) << "expected a tuple";
+          return ProgramError(e->source_loc()) << "expected a tuple";
       }
     }
     case ExpressionKind::TupleLiteral: {
@@ -1598,7 +1594,7 @@ auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e,
               return Success();
             }
           }
-          return CompilationError(access.source_loc())
+          return ProgramError(access.source_loc())
                  << "struct " << struct_type << " does not have a field named "
                  << access.member_name();
         }
@@ -1629,7 +1625,7 @@ auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e,
                       e->source_loc(), "method access, receiver type", me_type,
                       &access.object().static_type(), impl_scope));
                   if (access.object().value_category() != ValueCategory::Var) {
-                    return CompilationError(e->source_loc())
+                    return ProgramError(e->source_loc())
                            << "method " << access.member_name()
                            << " requires its receiver to be an lvalue";
                   }
@@ -1644,7 +1640,7 @@ auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e,
             }
             return Success();
           } else {
-            return CompilationError(e->source_loc())
+            return ProgramError(e->source_loc())
                    << "class " << t_class.declaration().name()
                    << " does not have a field named " << access.member_name();
           }
@@ -1759,7 +1755,7 @@ auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e,
                   return Success();
                 }
               }
-              return CompilationError(access.source_loc())
+              return ProgramError(access.source_loc())
                      << "struct " << *type << " does not have a field named "
                      << " does not have a field named " << access.member_name();
             }
@@ -1768,7 +1764,7 @@ auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e,
               std::optional<Nonnull<const Value*>> parameter_types =
                   choice.FindAlternative(access.member_name());
               if (!parameter_types.has_value()) {
-                return CompilationError(e->source_loc())
+                return ProgramError(e->source_loc())
                        << "choice " << choice.name()
                        << " does not have an alternative named "
                        << access.member_name();
@@ -1819,7 +1815,7 @@ auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e,
                 access.set_value_category(ValueCategory::Let);
                 return Success();
               } else {
-                return CompilationError(access.source_loc())
+                return ProgramError(access.source_loc())
                        << class_type << " does not have a member named "
                        << access.member_name();
               }
@@ -1838,12 +1834,12 @@ auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e,
               return Success();
             }
             default:
-              return CompilationError(access.source_loc())
+              return ProgramError(access.source_loc())
                      << "unsupported member access into type " << *type;
           }
         }
         default:
-          return CompilationError(e->source_loc())
+          return ProgramError(e->source_loc())
                  << "member access, unexpected " << object_type << " in " << *e;
       }
     }
@@ -1852,7 +1848,7 @@ auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e,
       CARBON_RETURN_IF_ERROR(TypeCheckExp(&access.object(), impl_scope));
       CARBON_RETURN_IF_ERROR(TypeCheckExp(&access.path(), impl_scope));
       if (!isa<TypeOfMemberName>(access.path().static_type())) {
-        return CompilationError(e->source_loc())
+        return ProgramError(e->source_loc())
                << "expected name of instance member or interface member in "
                   "compound member access, found "
                << access.path().static_type();
@@ -1961,7 +1957,7 @@ auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e,
             cast<FunctionDeclaration>(ident.value_node().base());
         if (!function.has_static_type()) {
           CARBON_CHECK(function.return_term().is_auto());
-          return CompilationError(ident.source_loc())
+          return ProgramError(ident.source_loc())
                  << "Function calls itself, but has a deduced return type";
         }
       }
@@ -2003,7 +1999,7 @@ auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e,
             BuiltinMethodCall{"Op"});
         if (!result.ok()) {
           // We couldn't find a matching `impl`.
-          return CompilationError(e->source_loc())
+          return ProgramError(e->source_loc())
                  << "type error in `" << ToString(op.op()) << "`:\n"
                  << result.error().message();
         }
@@ -2018,7 +2014,7 @@ auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e,
             BuiltinMethodCall{"Op", {op.arguments()[1]}});
         if (!result.ok()) {
           // We couldn't find a matching `impl`.
-          return CompilationError(e->source_loc())
+          return ProgramError(e->source_loc())
                  << "type error in `" << ToString(op.op()) << "`:\n"
                  << result.error().message();
         }
@@ -2049,7 +2045,7 @@ auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e,
             BuiltinMethodCall{method_name, op.arguments()[1]});
         if (!converted.ok()) {
           // We couldn't find a matching `impl`.
-          return CompilationError(e->source_loc())
+          return ProgramError(e->source_loc())
                  << *ts[0] << " is not " << operator_desc << " comparable with "
                  << *ts[1] << " (" << converted.error().message() << ")";
         }
@@ -2093,7 +2089,7 @@ auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e,
                              dyn_cast<TypeOfConstraintType>(ts[i])) {
                 constraints[i] = &constraint_type_type->constraint_type();
               } else {
-                return CompilationError(op.arguments()[i]->source_loc())
+                return ProgramError(op.arguments()[i]->source_loc())
                        << "argument to " << ToString(op.op())
                        << " should be a constraint, found `" << *ts[i] << "`";
               }
@@ -2170,7 +2166,7 @@ auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e,
           return Success();
         case Operator::AddressOf:
           if (op.arguments()[0]->value_category() != ValueCategory::Var) {
-            return CompilationError(op.arguments()[0]->source_loc())
+            return ProgramError(op.arguments()[0]->source_loc())
                    << "Argument to " << ToString(op.op())
                    << " should be an lvalue.";
           }
@@ -2189,7 +2185,7 @@ auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e,
                                      BuiltinMethodCall{"Convert"});
           if (!converted.ok()) {
             // We couldn't find a matching `impl`.
-            return CompilationError(e->source_loc())
+            return ProgramError(e->source_loc())
                    << "type error in `as`: `" << *ts[0]
                    << "` is not explicitly convertible to `" << *type << "`:\n"
                    << converted.error().message();
@@ -2292,7 +2288,7 @@ auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e,
         }
         case Value::Kind::TypeOfChoiceType:
         default: {
-          return CompilationError(e->source_loc())
+          return ProgramError(e->source_loc())
                  << "in call `" << *e
                  << "`, expected callee to be a function, found `"
                  << call.function().static_type() << "`";
@@ -2322,7 +2318,7 @@ auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e,
           // overloads. Here, that's the name Print instead of __intrinsic_print
           // in errors.
           if (args.size() < 1 || args.size() > 2) {
-            return CompilationError(e->source_loc())
+            return ProgramError(e->source_loc())
                    << "Print takes 1 or 2 arguments, received " << args.size();
           }
           CARBON_RETURN_IF_ERROR(ExpectExactType(
@@ -2338,7 +2334,7 @@ auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e,
           return Success();
         case IntrinsicExpression::Intrinsic::Assert: {
           if (args.size() != 2) {
-            return CompilationError(e->source_loc())
+            return ProgramError(e->source_loc())
                    << "__intrinsic_assert takes 2 arguments";
           }
           CARBON_RETURN_IF_ERROR(ExpectType(
@@ -2353,7 +2349,7 @@ auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e,
         }
         case IntrinsicExpression::Intrinsic::Alloc: {
           if (args.size() != 1) {
-            return CompilationError(e->source_loc())
+            return ProgramError(e->source_loc())
                    << "__intrinsic_new takes 1 argument";
           }
           auto arg_type = &args[0]->static_type();
@@ -2363,7 +2359,7 @@ auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e,
         }
         case IntrinsicExpression::Intrinsic::Dealloc: {
           if (args.size() != 1) {
-            return CompilationError(e->source_loc())
+            return ProgramError(e->source_loc())
                    << "__intrinsic_new takes 1 argument";
           }
           auto arg_type = &args[0]->static_type();
@@ -2375,7 +2371,7 @@ auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e,
         }
         case IntrinsicExpression::Intrinsic::Rand: {
           if (args.size() != 2) {
-            return CompilationError(e->source_loc())
+            return ProgramError(e->source_loc())
                    << "Rand takes 2 arguments, received " << args.size();
           }
           CARBON_RETURN_IF_ERROR(ExpectExactType(
@@ -2392,7 +2388,7 @@ auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e,
         }
         case IntrinsicExpression::Intrinsic::IntEq: {
           if (args.size() != 2) {
-            return CompilationError(e->source_loc())
+            return ProgramError(e->source_loc())
                    << "__intrinsic_int_eq takes 2 arguments";
           }
           CARBON_RETURN_IF_ERROR(ExpectExactType(
@@ -2407,7 +2403,7 @@ auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e,
         }
         case IntrinsicExpression::Intrinsic::IntCompare: {
           if (args.size() != 2) {
-            return CompilationError(e->source_loc())
+            return ProgramError(e->source_loc())
                    << "__intrinsic_int_compare takes 2 arguments";
           }
           CARBON_RETURN_IF_ERROR(ExpectExactType(
@@ -2422,7 +2418,7 @@ auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e,
         }
         case IntrinsicExpression::Intrinsic::StrEq: {
           if (args.size() != 2) {
-            return CompilationError(e->source_loc())
+            return ProgramError(e->source_loc())
                    << "__intrinsic_str_eq takes 2 arguments";
           }
           CARBON_RETURN_IF_ERROR(ExpectExactType(
@@ -2437,7 +2433,7 @@ auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e,
         }
         case IntrinsicExpression::Intrinsic::StrCompare: {
           if (args.size() != 2) {
-            return CompilationError(e->source_loc())
+            return ProgramError(e->source_loc())
                    << "__intrinsic_str_compare takes 2 arguments";
           }
           CARBON_RETURN_IF_ERROR(ExpectExactType(
@@ -2452,7 +2448,7 @@ auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e,
         }
         case IntrinsicExpression::Intrinsic::IntBitComplement:
           if (args.size() != 1) {
-            return CompilationError(e->source_loc())
+            return ProgramError(e->source_loc())
                    << intrinsic_exp.name() << " takes 1 argument";
           }
           CARBON_RETURN_IF_ERROR(ExpectExactType(
@@ -2467,7 +2463,7 @@ auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e,
         case IntrinsicExpression::Intrinsic::IntLeftShift:
         case IntrinsicExpression::Intrinsic::IntRightShift:
           if (args.size() != 2) {
-            return CompilationError(e->source_loc())
+            return ProgramError(e->source_loc())
                    << intrinsic_exp.name() << " takes 2 arguments";
           }
           CARBON_RETURN_IF_ERROR(ExpectExactType(
@@ -2531,7 +2527,7 @@ auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e,
       } else if (isa<TypeType>(base_type)) {
         // Start with an unconstrained type.
       } else {
-        return CompilationError(e->source_loc())
+        return ProgramError(e->source_loc())
                << "expected constraint as first operand of `where` expression, "
                << "found " << base_type;
       }
@@ -2567,7 +2563,7 @@ auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e,
               map[constraint_type->self_binding()] = type;
               builder.Add(cast<ConstraintType>(Substitute(map, constraint)));
             } else {
-              return CompilationError(is_clause.constraint().source_loc())
+              return ProgramError(is_clause.constraint().source_loc())
                      << "expression after `is` does not resolve to a "
                         "constraint, found value "
                      << *constraint << " of type "
@@ -2613,7 +2609,7 @@ auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e,
           Nonnull<const Value*> size_value,
           InterpExp(&array_literal.size_expression(), arena_, trace_stream_));
       if (cast<IntValue>(size_value)->value() < 0) {
-        return CompilationError(array_literal.size_expression().source_loc())
+        return ProgramError(array_literal.size_expression().source_loc())
                << "Array size cannot be negative";
       }
       array_literal.set_static_type(arena_->New<TypeType>());
@@ -2693,7 +2689,7 @@ auto TypeChecker::TypeCheckWhereClause(Nonnull<WhereClause*> clause,
       CARBON_RETURN_IF_ERROR(TypeCheckExp(&is_clause.constraint(), impl_scope));
       if (!isa<TypeOfInterfaceType, TypeOfConstraintType, TypeType>(
               is_clause.constraint().static_type())) {
-        return CompilationError(is_clause.constraint().source_loc())
+        return ProgramError(is_clause.constraint().source_loc())
                << "expression after `is` does not resolve to a constraint, "
                << "found " << is_clause.constraint().static_type();
       }
@@ -2713,7 +2709,7 @@ auto TypeChecker::TypeCheckWhereClause(Nonnull<WhereClause*> clause,
                                    /*allow_user_defined_conversions=*/false) &&
           !IsImplicitlyConvertible(rhs_type, lhs_type, impl_scope,
                                    /*allow_user_defined_conversions=*/false)) {
-        return CompilationError(clause->source_loc())
+        return ProgramError(clause->source_loc())
                << "type mismatch between values in `where LHS == RHS`\n"
                << "  LHS type: " << *lhs_type << "\n"
                << "  RHS type: " << *rhs_type;
@@ -2746,7 +2742,7 @@ auto TypeChecker::TypeCheckPattern(
       if (!VisitNestedPatterns(binding.type(), [](const Pattern& pattern) {
             return !isa<BindingPattern>(pattern);
           })) {
-        return CompilationError(binding.type().source_loc())
+        return ProgramError(binding.type().source_loc())
                << "The type of a binding pattern cannot contain bindings.";
       }
       CARBON_RETURN_IF_ERROR(TypeCheckPattern(
@@ -2764,7 +2760,7 @@ auto TypeChecker::TypeCheckPattern(
           if (!PatternMatch(type, *expected, binding.type().source_loc(),
                             std::nullopt, generic_args, trace_stream_,
                             this->arena_)) {
-            return CompilationError(binding.type().source_loc())
+            return ProgramError(binding.type().source_loc())
                    << "Type pattern '" << *type
                    << "' does not match actual type '" << **expected << "'";
           }
@@ -2787,14 +2783,14 @@ auto TypeChecker::TypeCheckPattern(
       CARBON_ASSIGN_OR_RETURN(Nonnull<const Value*> type,
                               TypeCheckTypeExp(&binding.type(), impl_scope));
       if (expected) {
-        return CompilationError(binding.type().source_loc())
+        return ProgramError(binding.type().source_loc())
                << "Generic binding may not occur in pattern with expected "
                   "type: "
                << binding;
       }
       binding.set_static_type(type);
       if (binding.named_as_type_via_dot_self() && !IsTypeOfType(type)) {
-        return CompilationError(binding.type().source_loc())
+        return ProgramError(binding.type().source_loc())
                << "`.Self` used in type of non-type binding `" << binding.name()
                << "`";
       }
@@ -2817,12 +2813,11 @@ auto TypeChecker::TypeCheckPattern(
       auto& tuple = cast<TuplePattern>(*p);
       std::vector<Nonnull<const Value*>> field_types;
       if (expected && (*expected)->kind() != Value::Kind::TupleValue) {
-        return CompilationError(p->source_loc()) << "didn't expect a tuple";
+        return ProgramError(p->source_loc()) << "didn't expect a tuple";
       }
       if (expected && tuple.fields().size() !=
                           cast<TupleValue>(**expected).elements().size()) {
-        return CompilationError(tuple.source_loc())
-               << "tuples of different length";
+        return ProgramError(tuple.source_loc()) << "tuples of different length";
       }
       for (size_t i = 0; i < tuple.fields().size(); ++i) {
         Nonnull<Pattern*> field = tuple.fields()[i];
@@ -2851,7 +2846,7 @@ auto TypeChecker::TypeCheckPattern(
           Nonnull<const Value*> type,
           InterpExp(&alternative.choice_type(), arena_, trace_stream_));
       if (!isa<ChoiceType>(type)) {
-        return CompilationError(alternative.source_loc())
+        return ProgramError(alternative.source_loc())
                << "alternative pattern does not name a choice type.";
       }
       const ChoiceType& choice_type = cast<ChoiceType>(*type);
@@ -2863,7 +2858,7 @@ auto TypeChecker::TypeCheckPattern(
       std::optional<Nonnull<const Value*>> parameter_types =
           choice_type.FindAlternative(alternative.alternative_name());
       if (parameter_types == std::nullopt) {
-        return CompilationError(alternative.source_loc())
+        return ProgramError(alternative.source_loc())
                << "'" << alternative.alternative_name()
                << "' is not an alternative of " << choice_type;
       }
@@ -2919,7 +2914,7 @@ auto TypeChecker::TypeCheckPattern(
               dyn_cast<PointerType>(&addr_pattern.binding().static_type())) {
         addr_pattern.set_static_type(&inner_binding_type->type());
       } else {
-        return CompilationError(addr_pattern.source_loc())
+        return ProgramError(addr_pattern.source_loc())
                << "Type associated with addr must be a pointer type.";
       }
       CARBON_ASSIGN_OR_RETURN(
@@ -2965,7 +2960,7 @@ auto TypeChecker::TypeCheckStmt(Nonnull<Statement*> s,
           expected_type = &clause.pattern().static_type();
         }
         if (patterns.IsRedundant({&clause.pattern()})) {
-          return CompilationError(clause.pattern().source_loc())
+          return ProgramError(clause.pattern().source_loc())
                  << "unreachable case: all values matched by this case "
                  << "are matched by earlier cases";
         }
@@ -3009,7 +3004,7 @@ auto TypeChecker::TypeCheckStmt(Nonnull<Statement*> s,
                              inner_impl_scope, ValueCategory::Var));
 
       } else {
-        return CompilationError(for_stmt.source_loc())
+        return ProgramError(for_stmt.source_loc())
                << "expected array type after in, found value of type " << rhs;
       }
 
@@ -3058,7 +3053,7 @@ auto TypeChecker::TypeCheckStmt(Nonnull<Statement*> s,
       CARBON_RETURN_IF_ERROR(TypeCheckExp(&assign.rhs(), impl_scope));
       CARBON_RETURN_IF_ERROR(TypeCheckExp(&assign.lhs(), impl_scope));
       if (assign.lhs().value_category() != ValueCategory::Var) {
-        return CompilationError(assign.source_loc())
+        return ProgramError(assign.source_loc())
                << "Cannot assign to rvalue '" << assign.lhs() << "'";
       }
       CARBON_ASSIGN_OR_RETURN(
@@ -3099,7 +3094,7 @@ auto TypeChecker::TypeCheckStmt(Nonnull<Statement*> s,
         CARBON_CHECK(IsConcreteType(&ret.value_node().static_type()));
         if (!IsSameType(&return_term.static_type(),
                         &ret.value_node().static_type(), impl_scope)) {
-          return CompilationError(ret.value_node().base().source_loc())
+          return ProgramError(ret.value_node().base().source_loc())
                  << "type of returned var `" << ret.value_node().static_type()
                  << "` does not match return type `"
                  << return_term.static_type() << "`";
@@ -3159,7 +3154,7 @@ auto TypeChecker::ExpectReturnOnAllPaths(
     std::optional<Nonnull<Statement*>> opt_stmt, SourceLocation source_loc)
     -> ErrorOr<Success> {
   if (!opt_stmt) {
-    return CompilationError(source_loc)
+    return ProgramError(source_loc)
            << "control-flow reaches end of function that provides a `->` "
               "return type without reaching a return statement";
   }
@@ -3168,7 +3163,7 @@ auto TypeChecker::ExpectReturnOnAllPaths(
     case StatementKind::Match: {
       auto& match = cast<Match>(*stmt);
       if (!IsExhaustive(match)) {
-        return CompilationError(source_loc)
+        return ProgramError(source_loc)
                << "non-exhaustive match may allow control-flow to reach the "
                   "end "
                   "of a function that provides a `->` return type";
@@ -3183,7 +3178,7 @@ auto TypeChecker::ExpectReturnOnAllPaths(
     case StatementKind::Block: {
       auto& block = cast<Block>(*stmt);
       if (block.statements().empty()) {
-        return CompilationError(stmt->source_loc())
+        return ProgramError(stmt->source_loc())
                << "control-flow reaches end of function that provides a `->` "
                   "return type without reaching a return statement";
       }
@@ -3213,7 +3208,7 @@ auto TypeChecker::ExpectReturnOnAllPaths(
     case StatementKind::Break:
     case StatementKind::Continue:
     case StatementKind::VariableDefinition:
-      return CompilationError(stmt->source_loc())
+      return ProgramError(stmt->source_loc())
              << "control-flow reaches end of function that provides a `->` "
                 "return type without reaching a return statement";
   }
@@ -3279,7 +3274,7 @@ auto TypeChecker::DeclareCallableDeclaration(Nonnull<CallableDeclaration*> f,
   } else {
     // We have to type-check the body in order to determine the return type.
     if (!f->body().has_value()) {
-      return CompilationError(f->return_term().source_loc())
+      return ProgramError(f->return_term().source_loc())
              << "Function declaration has deduced return type but no body";
     }
     CARBON_RETURN_IF_ERROR(TypeCheckStmt(*f->body(), function_scope));
@@ -3311,7 +3306,7 @@ auto TypeChecker::DeclareCallableDeclaration(Nonnull<CallableDeclaration*> f,
 
   if (f->name() == "Main") {
     if (!f->return_term().type_expression().has_value()) {
-      return CompilationError(f->return_term().source_loc())
+      return ProgramError(f->return_term().source_loc())
              << "`Main` must have an explicit return type";
     }
     CARBON_RETURN_IF_ERROR(
@@ -3368,11 +3363,11 @@ auto TypeChecker::DeclareClassDeclaration(Nonnull<ClassDeclaration*> class_decl,
   class_scope.AddParent(scope_info.innermost_scope);
 
   if (class_decl->extensibility() != ClassExtensibility::None) {
-    return CompilationError(class_decl->source_loc())
+    return ProgramError(class_decl->source_loc())
            << "Class prefixes `base` and `abstract` are not supported yet";
   }
   if (class_decl->extends()) {
-    return CompilationError(class_decl->source_loc())
+    return ProgramError(class_decl->source_loc())
            << "Class extension with `extends` is not supported yet";
   }
 
@@ -3693,7 +3688,7 @@ auto TypeChecker::CheckImplIsDeducible(
                                            impl_scope));
   for (auto* expected_deduced : deduced_bindings) {
     if (!deduced_args.count(expected_deduced)) {
-      return CompilationError(source_loc)
+      return ProgramError(source_loc)
              << "parameter `" << *expected_deduced
              << "` is not deducible from `impl " << *impl_type << " as "
              << *impl_iface << "`";
@@ -3735,7 +3730,7 @@ auto TypeChecker::CheckImplIsComplete(Nonnull<const InterfaceType*> iface_type,
       };
       impl_decl->constraint_type()->VisitEqualValues(expected, visitor);
       if (!found_any) {
-        return CompilationError(impl_decl->source_loc())
+        return ProgramError(impl_decl->source_loc())
                << "implementation missing " << *expected;
       } else if (!found_value) {
         // TODO: It's not clear what the right rule is here. Clearly
@@ -3743,11 +3738,11 @@ auto TypeChecker::CheckImplIsComplete(Nonnull<const InterfaceType*> iface_type,
         // ... is insufficient to establish a value for either X or Y.
         // But perhaps we can allow
         //   impl forall [T:! HasX] T as HasY where .Y == .X {}
-        return CompilationError(impl_decl->source_loc())
+        return ProgramError(impl_decl->source_loc())
                << "implementation doesn't provide a concrete value for "
                << *expected;
       } else if (second_value) {
-        return CompilationError(impl_decl->source_loc())
+        return ProgramError(impl_decl->source_loc())
                << "implementation provides multiple values for " << *expected
                << ": " << **found_value << " and " << **second_value;
       }
@@ -3759,7 +3754,7 @@ auto TypeChecker::CheckImplIsComplete(Nonnull<const InterfaceType*> iface_type,
       std::optional<Nonnull<const Declaration*>> mem =
           FindMember(*mem_name, impl_decl->members());
       if (!mem.has_value()) {
-        return CompilationError(impl_decl->source_loc())
+        return ProgramError(impl_decl->source_loc())
                << "implementation missing " << *mem_name;
       }
 
@@ -3823,7 +3818,7 @@ auto TypeChecker::CheckAndAddImplBindings(
           witness, *this);
     } else {
       // TODO: Add support for implementing `adapter`s.
-      return CompilationError(impl_decl->source_loc())
+      return ProgramError(impl_decl->source_loc())
              << "cannot implement a constraint whose lookup context includes "
              << *lookup.context;
     }
@@ -3870,7 +3865,7 @@ auto TypeChecker::DeclareImplDeclaration(Nonnull<ImplDeclaration*> impl_decl,
         impl_decl->interface().source_loc(), iface_type);
   }
   if (!isa<ConstraintType>(constraint_type)) {
-    return CompilationError(impl_decl->interface().source_loc())
+    return ProgramError(impl_decl->interface().source_loc())
            << "expected constraint after `as`, found value of type "
            << *constraint_type;
   }
@@ -4084,7 +4079,7 @@ auto TypeChecker::DeclareAliasDeclaration(Nonnull<AliasDeclaration*> alias,
       TypeCheckExp(&alias->target(), *scope_info.innermost_scope));
 
   if (!IsValidTypeForAliasTarget(&alias->target().static_type())) {
-    return CompilationError(alias->source_loc())
+    return ProgramError(alias->source_loc())
            << "invalid target for alias declaration";
   }
 
@@ -4164,7 +4159,7 @@ auto TypeChecker::TypeCheckDeclaration(
           dyn_cast<ExpressionPattern>(&var.binding().type());
       if (binding_type == nullptr) {
         // TODO: consider adding support for `auto`
-        return CompilationError(var.source_loc())
+        return ProgramError(var.source_loc())
                << "Type of a top-level variable must be an expression.";
       }
       if (var.has_initializer()) {
@@ -4243,7 +4238,7 @@ auto TypeChecker::DeclareDeclaration(Nonnull<Declaration*> d,
       // Associate the variable name with it's declared type in the
       // compile-time symbol table.
       if (!llvm::isa<ExpressionPattern>(var.binding().type())) {
-        return CompilationError(var.binding().type().source_loc())
+        return ProgramError(var.binding().type().source_loc())
                << "Expected expression for variable type";
       }
       Expression& type =
@@ -4349,12 +4344,12 @@ auto TypeChecker::CollectMember(Nonnull<const Declaration*> enclosing_decl,
   auto [it, inserted] = encl_members.insert({member_name.value(), member_decl});
   if (!inserted) {
     if (member_decl == it->second) {
-      return CompilationError(enclosing_decl_loc)
+      return ProgramError(enclosing_decl_loc)
              << "Member named " << member_name.value() << " (declared at "
              << member_decl->source_loc() << ")"
              << " is being mixed multiple times into " << enclosing_decl_name;
     } else {
-      return CompilationError(enclosing_decl_loc)
+      return ProgramError(enclosing_decl_loc)
              << "Member named " << member_name.value() << " (declared at "
              << member_decl->source_loc() << ") cannot be mixed into "
              << enclosing_decl_name

+ 8 - 8
explorer/interpreter/value.cpp

@@ -65,11 +65,11 @@ static auto GetMember(Nonnull<Arena*> arena, Nonnull<const Value*> v,
                                            &impl_witness->bindings());
         }
       } else {
-        return CompilationError(source_loc)
+        return ProgramError(source_loc)
                << "member " << f << " not in " << *witness;
       }
     } else {
-      return RuntimeError(source_loc)
+      return ProgramError(source_loc)
              << "member lookup for " << f << " in symbolic " << *witness;
     }
   }
@@ -78,7 +78,7 @@ static auto GetMember(Nonnull<Arena*> arena, Nonnull<const Value*> v,
       std::optional<Nonnull<const Value*>> field =
           cast<StructValue>(*v).FindField(f);
       if (field == std::nullopt) {
-        return RuntimeError(source_loc) << "member " << f << " not in " << *v;
+        return ProgramError(source_loc) << "member " << f << " not in " << *v;
       }
       return *field;
     }
@@ -99,7 +99,7 @@ static auto GetMember(Nonnull<Arena*> arena, Nonnull<const Value*> v,
         std::optional<Nonnull<const FunctionValue*>> func =
             class_type.FindFunction(f);
         if (func == std::nullopt) {
-          return RuntimeError(source_loc) << "member " << f << " not in " << *v
+          return ProgramError(source_loc) << "member " << f << " not in " << *v
                                           << " or its " << class_type;
         } else if ((*func)->declaration().is_method()) {
           // Found a method. Turn it into a bound method.
@@ -116,7 +116,7 @@ static auto GetMember(Nonnull<Arena*> arena, Nonnull<const Value*> v,
     case Value::Kind::ChoiceType: {
       const auto& choice = cast<ChoiceType>(*v);
       if (!choice.FindAlternative(f)) {
-        return RuntimeError(source_loc)
+        return ProgramError(source_loc)
                << "alternative " << f << " not in " << *v;
       }
       return arena->New<AlternativeConstructorValue>(f, choice.name());
@@ -127,7 +127,7 @@ static auto GetMember(Nonnull<Arena*> arena, Nonnull<const Value*> v,
       std::optional<Nonnull<const FunctionValue*>> fun =
           class_type.FindFunction(f);
       if (fun == std::nullopt) {
-        return RuntimeError(source_loc)
+        return ProgramError(source_loc)
                << "class function " << f << " not in " << *v;
       }
       return arena->New<FunctionValue>(&(*fun)->declaration(),
@@ -167,7 +167,7 @@ static auto SetFieldImpl(
             return element.name == (*path_begin).name();
           });
       if (it == elements.end()) {
-        return RuntimeError(source_loc)
+        return ProgramError(source_loc)
                << "field " << (*path_begin).name() << " not in " << *value;
       }
       CARBON_ASSIGN_OR_RETURN(
@@ -188,7 +188,7 @@ static auto SetFieldImpl(
       // TODO(geoffromer): update FieldPath to hold integers as well as strings.
       int index = std::stoi(std::string((*path_begin).name()));
       if (index < 0 || static_cast<size_t>(index) >= elements.size()) {
-        return RuntimeError(source_loc) << "index " << (*path_begin).name()
+        return ProgramError(source_loc) << "index " << (*path_begin).name()
                                         << " out of range in " << *value;
       }
       CARBON_ASSIGN_OR_RETURN(

+ 37 - 18
explorer/main.cpp

@@ -28,7 +28,7 @@ namespace Carbon {
 namespace cl = llvm::cl;
 
 static auto Main(llvm::StringRef default_prelude_file, int argc, char* argv[])
-    -> ErrorOr<Success> {
+    -> bool {
   llvm::setBugReportMsg(
       "Please report issues to "
       "https://github.com/carbon-language/carbon-lang/issues and include the "
@@ -63,36 +63,55 @@ static auto Main(llvm::StringRef default_prelude_file, int argc, char* argv[])
       scoped_trace_stream =
           std::make_unique<llvm::raw_fd_ostream>(trace_file_name, err);
       if (err) {
-        return Error(err.message());
+        llvm::errs() << err.message() << "\n";
+        return false;
       }
       trace_stream = scoped_trace_stream.get();
     }
   }
 
   Arena arena;
-  CARBON_ASSIGN_OR_RETURN(AST ast,
-                          Parse(&arena, input_file_name, parser_debug));
+  AST ast;
+  if (ErrorOr<AST> parse_result = Parse(&arena, input_file_name, parser_debug);
+      parse_result.ok()) {
+    ast = *std::move(parse_result);
+  } else {
+    llvm::errs() << "SYNTAX ERROR: " << parse_result.error() << "\n";
+    return false;
+  }
+
   AddPrelude(prelude_file_name, &arena, &ast.declarations);
 
-  // Typecheck and run the parsed program.
-  CARBON_ASSIGN_OR_RETURN(int return_code,
-                          ExecProgram(&arena, ast, trace_stream));
-  // Always print the return code to stdout.
-  llvm::outs() << "result: " << return_code << "\n";
-  // When there's a dedicated trace file, print the return code to it too.
-  if (scoped_trace_stream) {
-    **trace_stream << "result: " << return_code << "\n";
+  // Semantically analyze the parsed program.
+  if (ErrorOr<AST> analyze_result = AnalyzeProgram(&arena, ast, trace_stream);
+      analyze_result.ok()) {
+    ast = *std::move(analyze_result);
+  } else {
+    llvm::errs() << "COMPILATION ERROR: " << analyze_result.error() << "\n";
+    return false;
+  }
+
+  // Run the program.
+  if (ErrorOr<int> exec_result = ExecProgram(&arena, ast, trace_stream);
+      exec_result.ok()) {
+    // Print the return code to stdout.
+    llvm::outs() << "result: " << *exec_result << "\n";
+
+    // When there's a dedicated trace file, print the return code to it too.
+    if (scoped_trace_stream) {
+      **trace_stream << "result: " << *exec_result << "\n";
+    }
+  } else {
+    llvm::errs() << "RUNTIME ERROR: " << exec_result.error() << "\n";
+    return false;
   }
-  return Success();
+
+  return true;
 }
 
 auto ExplorerMain(llvm::StringRef default_prelude_file, int argc, char** argv)
     -> int {
-  if (auto result = Main(default_prelude_file, argc, argv); !result.ok()) {
-    llvm::errs() << result.error() << "\n";
-    return EXIT_FAILURE;
-  }
-  return EXIT_SUCCESS;
+  return Main(default_prelude_file, argc, argv) ? EXIT_SUCCESS : EXIT_FAILURE;
 }
 
 }  // namespace Carbon

+ 1 - 1
explorer/syntax/parse_and_lex_context.cpp

@@ -17,7 +17,7 @@ auto ParseAndLexContext::RecordSyntaxError(Error error) -> Parser::symbol_type {
 
 auto ParseAndLexContext::RecordSyntaxError(const std::string& message)
     -> Parser::symbol_type {
-  return RecordSyntaxError(CompilationError(source_loc()) << message);
+  return RecordSyntaxError(ProgramError(source_loc()) << message);
 }
 
 }  // namespace Carbon

+ 1 - 1
explorer/testdata/addr/fail_method_me_misspelled.carbon

@@ -11,7 +11,7 @@
 package ExplorerTest api;
 
 class C {
-  // CHECK: COMPILATION ERROR: {{.*}}/explorer/testdata/addr/fail_method_me_misspelled.carbon:[[@LINE+1]]: illegal binding pattern in implicit parameter list
+  // CHECK: SYNTAX ERROR: {{.*}}/explorer/testdata/addr/fail_method_me_misspelled.carbon:[[@LINE+1]]: illegal binding pattern in implicit parameter list
   fn F[addr mew: Self*]() {}
 }
 

+ 1 - 1
explorer/testdata/assoc_const/fail_anonymous.carbon

@@ -11,7 +11,7 @@
 package ExplorerTest api;
 
 interface Iface {
-  // CHECK: COMPILATION ERROR: {{.*}}/explorer/testdata/assoc_const/fail_anonymous.carbon:[[@LINE+1]]: syntax error, unexpected UNDERSCORE, expecting identifier
+  // CHECK: SYNTAX ERROR: {{.*}}/explorer/testdata/assoc_const/fail_anonymous.carbon:[[@LINE+1]]: syntax error, unexpected UNDERSCORE, expecting identifier
   let _:! Type;
 }
 

+ 1 - 1
explorer/testdata/basic_syntax/fail_block.carbon

@@ -12,7 +12,7 @@ package ExplorerTest api;
 
 fn Main() -> i32 {
   {
-    // CHECK: COMPILATION ERROR: {{.*}}/explorer/testdata/basic_syntax/fail_block.carbon:[[@LINE+1]]: syntax error, unexpected RETURN, expecting PERIOD or RIGHT_CURLY_BRACE
+    // CHECK: SYNTAX ERROR: {{.*}}/explorer/testdata/basic_syntax/fail_block.carbon:[[@LINE+1]]: syntax error, unexpected RETURN, expecting PERIOD or RIGHT_CURLY_BRACE
     return 0;
   }
 }

+ 1 - 1
explorer/testdata/basic_syntax/fail_invalid_char.carbon

@@ -8,5 +8,5 @@
 // RUN:   %{FileCheck} --match-full-lines --allow-unused-prefixes %s
 // AUTOUPDATE: %{explorer} %s
 
-// CHECK: COMPILATION ERROR: {{.*}}/explorer/testdata/basic_syntax/fail_invalid_char.carbon:[[@LINE+1]]: invalid character '\xEF' in source file.
+// CHECK: SYNTAX ERROR: {{.*}}/explorer/testdata/basic_syntax/fail_invalid_char.carbon:[[@LINE+1]]: invalid character '\xEF' in source file.

+ 1 - 1
explorer/testdata/basic_syntax/fail_invalid_integer.carbon

@@ -11,6 +11,6 @@
 package ExplorerTest api;
 
 fn Main() -> i32 {
-  // CHECK: COMPILATION ERROR: {{.*}}/explorer/testdata/basic_syntax/fail_invalid_integer.carbon:[[@LINE+1]]: Invalid integer literal: 11111111111111111111111111
+  // CHECK: SYNTAX ERROR: {{.*}}/explorer/testdata/basic_syntax/fail_invalid_integer.carbon:[[@LINE+1]]: Invalid integer literal: 11111111111111111111111111
   return 11111111111111111111111111;
 }

+ 1 - 1
explorer/testdata/basic_syntax/fail_invalid_integer_type.carbon

@@ -11,7 +11,7 @@
 package ExplorerTest api;
 
 fn Main() -> i32 {
-  // CHECK: COMPILATION ERROR: {{.*}}/explorer/testdata/basic_syntax/fail_invalid_integer_type.carbon:[[@LINE+1]]: Invalid type literal: i11111111111111111111111111
+  // CHECK: SYNTAX ERROR: {{.*}}/explorer/testdata/basic_syntax/fail_invalid_integer_type.carbon:[[@LINE+1]]: Invalid type literal: i11111111111111111111111111
   var x: i11111111111111111111111111 = 1;
   return 0;
 }

+ 1 - 1
explorer/testdata/basic_syntax/fail_missing_var.carbon

@@ -12,7 +12,7 @@ package ExplorerTest api;
 
 fn Main() -> i32 {
   // error
-  // CHECK: COMPILATION ERROR: {{.*}}/explorer/testdata/basic_syntax/fail_missing_var.carbon:[[@LINE+1]]: syntax error, unexpected COLON, expecting SLASH or binary *
+  // CHECK: SYNTAX ERROR: {{.*}}/explorer/testdata/basic_syntax/fail_missing_var.carbon:[[@LINE+1]]: syntax error, unexpected COLON, expecting SLASH or binary *
   x : i32;
   return 1;
 }

+ 1 - 1
explorer/testdata/basic_syntax/fail_unknown_intrinsic.carbon

@@ -11,6 +11,6 @@
 package ExplorerTest api;
 
 fn Main() -> i32 {
-  // CHECK: COMPILATION ERROR: {{.*}}/explorer/testdata/basic_syntax/fail_unknown_intrinsic.carbon:[[@LINE+1]]: Unknown intrinsic 'nonexistent'
+  // CHECK: SYNTAX ERROR: {{.*}}/explorer/testdata/basic_syntax/fail_unknown_intrinsic.carbon:[[@LINE+1]]: Unknown intrinsic 'nonexistent'
   return __intrinsic_nonexistent();
 }

+ 1 - 1
explorer/testdata/basic_syntax/fail_unsupported_integer_type.carbon

@@ -11,7 +11,7 @@
 package ExplorerTest api;
 
 fn Main() -> i32 {
-  // CHECK: COMPILATION ERROR: {{.*}}/explorer/testdata/basic_syntax/fail_unsupported_integer_type.carbon:[[@LINE+1]]: Only i32 is supported for now: i64
+  // CHECK: SYNTAX ERROR: {{.*}}/explorer/testdata/basic_syntax/fail_unsupported_integer_type.carbon:[[@LINE+1]]: Only i32 is supported for now: i64
   var x: i64 = 1;
   return 0;
 }

+ 1 - 1
explorer/testdata/basic_syntax/fail_var_named_self.carbon

@@ -14,7 +14,7 @@ fn Main() -> i32 {
   // Error: can't use keyword `Self` as the name of a variable.
   // TODO: Current error message is unclear, better would be to say
   // something like: unexpected `Self`, expecting identifier
-  // CHECK: COMPILATION ERROR: {{.*}}/explorer/testdata/basic_syntax/fail_var_named_self.carbon:[[@LINE+1]]: syntax error, unexpected COLON, expecting SLASH or binary *
+  // CHECK: SYNTAX ERROR: {{.*}}/explorer/testdata/basic_syntax/fail_var_named_self.carbon:[[@LINE+1]]: syntax error, unexpected COLON, expecting SLASH or binary *
   var Self : i32 = 0;
   return Self;
 }

+ 1 - 1
explorer/testdata/basic_syntax/not_compare_precedence.carbon

@@ -11,6 +11,6 @@
 package ExplorerTest api;
 
 fn CompareBools(a: bool, b: bool) -> bool {
-  // CHECK: COMPILATION ERROR: {{.*}}/explorer/testdata/basic_syntax/not_compare_precedence.carbon:[[@LINE+1]]: syntax error, unexpected EQUAL_EQUAL, expecting SEMICOLON
+  // CHECK: SYNTAX ERROR: {{.*}}/explorer/testdata/basic_syntax/not_compare_precedence.carbon:[[@LINE+1]]: syntax error, unexpected EQUAL_EQUAL, expecting SEMICOLON
   return not a == b;
 }

+ 1 - 1
explorer/testdata/class/fail_class_named_self.carbon

@@ -11,7 +11,7 @@
 package ExplorerTest api;
 
 // Error: Can't use keyword `Self` as the name of a class.
-// CHECK: COMPILATION ERROR: {{.*}}/explorer/testdata/class/fail_class_named_self.carbon:[[@LINE+1]]: syntax error, unexpected SELF, expecting identifier
+// CHECK: SYNTAX ERROR: {{.*}}/explorer/testdata/class/fail_class_named_self.carbon:[[@LINE+1]]: syntax error, unexpected SELF, expecting identifier
 class Self {
   var x: i32;
   var y: i32;

+ 1 - 1
explorer/testdata/experimental_continuation/fail_continuation_syntax.carbon

@@ -12,7 +12,7 @@ package ExplorerTest api;
 
 fn Main() -> i32 {
   var x: i32 = 0;
-  // CHECK: COMPILATION ERROR: {{.*}}/explorer/testdata/experimental_continuation/fail_continuation_syntax.carbon:[[@LINE+1]]: syntax error, unexpected identifier, expecting LEFT_CURLY_BRACE
+  // CHECK: SYNTAX ERROR: {{.*}}/explorer/testdata/experimental_continuation/fail_continuation_syntax.carbon:[[@LINE+1]]: syntax error, unexpected identifier, expecting LEFT_CURLY_BRACE
   __continuation k x = 3;
   __run k;
   return x;

+ 1 - 1
explorer/testdata/generic_function/fail_missing_exclam.carbon

@@ -10,7 +10,7 @@
 
 package ExplorerTest api;
 
-// CHECK: COMPILATION ERROR: {{.*}}/explorer/testdata/generic_function/fail_missing_exclam.carbon:[[@LINE+1]]: illegal binding pattern in implicit parameter list
+// CHECK: SYNTAX ERROR: {{.*}}/explorer/testdata/generic_function/fail_missing_exclam.carbon:[[@LINE+1]]: illegal binding pattern in implicit parameter list
 fn F[T: Type]();
 
 fn Main() -> i32 {

+ 1 - 1
explorer/testdata/global_variable/fail_named_self.carbon

@@ -11,7 +11,7 @@
 package ExplorerTest api;
 
 // Error: global variable may not be named with keyword `Self`.
-// CHECK: COMPILATION ERROR: {{.*}}/explorer/testdata/global_variable/fail_named_self.carbon:[[@LINE+1]]: syntax error, unexpected SELF, expecting identifier
+// CHECK: SYNTAX ERROR: {{.*}}/explorer/testdata/global_variable/fail_named_self.carbon:[[@LINE+1]]: syntax error, unexpected SELF, expecting identifier
 var Self: i32 = 0;
 
 fn Main() -> i32 {

+ 1 - 1
explorer/testdata/impl/fail_bad_member_kind.carbon

@@ -16,7 +16,7 @@ interface A {
 }
 
 external impl i32 as A {
-  // CHECK: COMPILATION ERROR: {{.*}}/explorer/testdata/impl/fail_bad_member_kind.carbon:[[@LINE+1]]: syntax error, unexpected CLASS, expecting ALIAS or FN or RIGHT_CURLY_BRACE
+  // CHECK: SYNTAX ERROR: {{.*}}/explorer/testdata/impl/fail_bad_member_kind.carbon:[[@LINE+1]]: syntax error, unexpected CLASS, expecting ALIAS or FN or RIGHT_CURLY_BRACE
   class T {}
 }
 

+ 1 - 1
explorer/testdata/import/fail_order.carbon

@@ -14,5 +14,5 @@ fn Main() -> i32 {
   return 0;
 }
 
-// CHECK: COMPILATION ERROR: {{.*}}/explorer/testdata/import/fail_order.carbon:[[@LINE+1]]: syntax error, unexpected IMPORT, expecting END_OF_FILE
+// CHECK: SYNTAX ERROR: {{.*}}/explorer/testdata/import/fail_order.carbon:[[@LINE+1]]: syntax error, unexpected IMPORT, expecting END_OF_FILE
 import ExplorerTest library "Nonexistent";

+ 1 - 1
explorer/testdata/interface/fail_bad_member_kind.carbon

@@ -11,7 +11,7 @@
 package ExplorerTest api;
 
 interface Bad {
-  // CHECK: COMPILATION ERROR: {{.*}}/explorer/testdata/interface/fail_bad_member_kind.carbon:[[@LINE+1]]: syntax error, unexpected VAR, expecting FN or LET or RIGHT_CURLY_BRACE
+  // CHECK: SYNTAX ERROR: {{.*}}/explorer/testdata/interface/fail_bad_member_kind.carbon:[[@LINE+1]]: syntax error, unexpected VAR, expecting FN or LET or RIGHT_CURLY_BRACE
   var V: i32;
 }
 

+ 1 - 1
explorer/testdata/interface/fail_use_symbolic_member.carbon

@@ -14,7 +14,7 @@ interface X {
   fn F() -> Type;
 }
 
-// CHECK: RUNTIME ERROR: {{.*}}/explorer/testdata/interface/fail_use_symbolic_member.carbon:[[@LINE+1]]: member lookup for F in symbolic witness for T:! X
+// CHECK: COMPILATION ERROR: {{.*}}/explorer/testdata/interface/fail_use_symbolic_member.carbon:[[@LINE+1]]: member lookup for F in symbolic witness for T:! X
 fn G[T:! X]() -> T.F() {
   return {};
 }

+ 1 - 1
explorer/testdata/let/fail_global_named_self.carbon

@@ -11,7 +11,7 @@
 package ExplorerTest api;
 
 // Error: Can't use keyword `Self` as the name of a global.
-// CHECK: COMPILATION ERROR: {{.*}}/explorer/testdata/let/fail_global_named_self.carbon:[[@LINE+1]]: syntax error, unexpected SELF, expecting identifier
+// CHECK: SYNTAX ERROR: {{.*}}/explorer/testdata/let/fail_global_named_self.carbon:[[@LINE+1]]: syntax error, unexpected SELF, expecting identifier
 let Self: i32 = 10;
 
 fn Main() -> i32 {

+ 1 - 1
explorer/testdata/let/fail_local_named_self.carbon

@@ -12,7 +12,7 @@ package ExplorerTest api;
 
 fn Main() -> i32 {
   // Error: Can't use keyword `Self` as the name of a local.
-  // CHECK: COMPILATION ERROR: {{.*}}/explorer/testdata/let/fail_local_named_self.carbon:[[@LINE+1]]: syntax error, unexpected COLON, expecting SLASH or binary *
+  // CHECK: SYNTAX ERROR: {{.*}}/explorer/testdata/let/fail_local_named_self.carbon:[[@LINE+1]]: syntax error, unexpected COLON, expecting SLASH or binary *
   let Self: auto = 10;
   return 0;
 }

+ 1 - 1
explorer/testdata/let/fail_tuple_pattern_let_context_nested.carbon

@@ -11,7 +11,7 @@
 package ExplorerTest api;
 
 fn Main() -> i32 {
-  // CHECK: COMPILATION ERROR: {{.*}}/explorer/testdata/let/fail_tuple_pattern_let_context_nested.carbon:[[@LINE+1]]: syntax error, unexpected LET
+  // CHECK: SYNTAX ERROR: {{.*}}/explorer/testdata/let/fail_tuple_pattern_let_context_nested.carbon:[[@LINE+1]]: syntax error, unexpected LET
   let (var a: auto, b: auto, c: auto, var (d: auto, let e: auto)) =
       (1, 2, 3, (4, 5));
   return 0;

+ 1 - 1
explorer/testdata/let/fail_tuple_pattern_let_in_var.carbon

@@ -11,7 +11,7 @@
 package ExplorerTest api;
 
 fn Main() -> i32 {
-  // CHECK: COMPILATION ERROR: {{.*}}/explorer/testdata/let/fail_tuple_pattern_let_in_var.carbon:[[@LINE+1]]: syntax error, unexpected LET
+  // CHECK: SYNTAX ERROR: {{.*}}/explorer/testdata/let/fail_tuple_pattern_let_in_var.carbon:[[@LINE+1]]: syntax error, unexpected LET
   var (var a: auto, b: auto, let c: auto, d: auto) = (1, 2, 3, 4);
   return 0;
 }

+ 1 - 1
explorer/testdata/match/fail_not_alternative.carbon

@@ -7,13 +7,13 @@
 // RUN: %{not} %{explorer} --parser_debug --trace_file=- %s 2>&1 | \
 // RUN:   %{FileCheck} --match-full-lines --allow-unused-prefixes %s
 // AUTOUPDATE: %{explorer} %s
-// CHECK: PROGRAM ERROR: {{.*}}/explorer/testdata/match/fail_not_alternative.carbon:17: Alternative pattern must have the form of a field access.
 
 package ExplorerTest api;
 
 fn Main() -> i32 {
   var x: i32 = 0;
   match (x) {
+    // CHECK: SYNTAX ERROR: {{.*}}/explorer/testdata/match/fail_not_alternative.carbon:[[@LINE+1]]: Alternative pattern must have the form of a field access.
     case i32(n: i32) => {
       return 1;
     }

+ 1 - 1
explorer/testdata/mixin/fail_mix_in_global.carbon

@@ -16,7 +16,7 @@ __mixin Operations {
   }
 }
 
-// CHECK: COMPILATION ERROR: {{.*}}/explorer/testdata/mixin/fail_mix_in_global.carbon:[[@LINE+1]]: syntax error, unexpected MIX, expecting END_OF_FILE
+// CHECK: SYNTAX ERROR: {{.*}}/explorer/testdata/mixin/fail_mix_in_global.carbon:[[@LINE+1]]: syntax error, unexpected MIX, expecting END_OF_FILE
 __mix Operations;
 
 class Point {

+ 1 - 1
explorer/testdata/mixin/fail_mix_in_impl.carbon

@@ -21,7 +21,7 @@ interface A {
 }
 
 external impl i32 as A {
-  // CHECK: COMPILATION ERROR: {{.*}}/explorer/testdata/mixin/fail_mix_in_impl.carbon:[[@LINE+1]]: syntax error, unexpected MIX, expecting ALIAS or FN or RIGHT_CURLY_BRACE
+  // CHECK: SYNTAX ERROR: {{.*}}/explorer/testdata/mixin/fail_mix_in_impl.carbon:[[@LINE+1]]: syntax error, unexpected MIX, expecting ALIAS or FN or RIGHT_CURLY_BRACE
   __mix Operations;
   fn F() {}
 }

+ 1 - 1
explorer/testdata/package/fail_missing.carbon

@@ -8,7 +8,7 @@
 // RUN:   %{FileCheck} --match-full-lines --allow-unused-prefixes %s
 // AUTOUPDATE: %{explorer} %s
 
-// CHECK: COMPILATION ERROR: {{.*}}/explorer/testdata/package/fail_missing.carbon:[[@LINE+1]]: syntax error, unexpected FN, expecting PACKAGE
+// CHECK: SYNTAX ERROR: {{.*}}/explorer/testdata/package/fail_missing.carbon:[[@LINE+1]]: syntax error, unexpected FN, expecting PACKAGE
 fn Main() -> i32 {
   return 0;
 }

+ 1 - 1
explorer/testdata/string/fail_block_quotes_not_on_own_line.carbon

@@ -11,7 +11,7 @@
 package ExplorerTest api;
 
 fn Main() -> i32 {
-  // CHECK: COMPILATION ERROR: {{.*}}/explorer/testdata/string/fail_block_quotes_not_on_own_line.carbon:[[@LINE+1]]: Invalid block string: Should end with triple quotes: error: closing """
+  // CHECK: SYNTAX ERROR: {{.*}}/explorer/testdata/string/fail_block_quotes_not_on_own_line.carbon:[[@LINE+1]]: Invalid block string: Should end with triple quotes: error: closing """
   var s: String = """
     error: closing """ is not on its own line.
   """;

+ 1 - 1
explorer/testdata/string/fail_hex_lower.carbon

@@ -11,7 +11,7 @@
 package ExplorerTest api;
 
 fn Main() -> i32 {
-  // CHECK: COMPILATION ERROR: {{.*}}/explorer/testdata/string/fail_hex_lower.carbon:[[@LINE+1]]: Invalid escaping in string: "str\xaa"
+  // CHECK: SYNTAX ERROR: {{.*}}/explorer/testdata/string/fail_hex_lower.carbon:[[@LINE+1]]: Invalid escaping in string: "str\xaa"
   Print("str\xaa");
   return 0;
 }

+ 1 - 1
explorer/testdata/string/fail_hex_truncated.carbon

@@ -11,7 +11,7 @@
 package ExplorerTest api;
 
 fn Main() -> i32 {
-  // CHECK: COMPILATION ERROR: {{.*}}/explorer/testdata/string/fail_hex_truncated.carbon:[[@LINE+1]]: Invalid escaping in string: "str\x"
+  // CHECK: SYNTAX ERROR: {{.*}}/explorer/testdata/string/fail_hex_truncated.carbon:[[@LINE+1]]: Invalid escaping in string: "str\x"
   Print("str\x");
   return 0;
 }

+ 1 - 1
explorer/testdata/string/fail_invalid_escape.carbon

@@ -11,7 +11,7 @@
 package ExplorerTest api;
 
 fn Main() -> i32 {
-  // CHECK: COMPILATION ERROR: {{.*}}/explorer/testdata/string/fail_invalid_escape.carbon:[[@LINE+1]]: Invalid escaping in string: "str\e"
+  // CHECK: SYNTAX ERROR: {{.*}}/explorer/testdata/string/fail_invalid_escape.carbon:[[@LINE+1]]: Invalid escaping in string: "str\e"
   Print("str\e");
   return 0;
 }

+ 1 - 1
explorer/testdata/string/fail_newline.carbon

@@ -11,7 +11,7 @@
 package ExplorerTest api;
 
 fn Main() -> i32 {
-  // CHECK: COMPILATION ERROR: {{.*}}/explorer/testdata/string/fail_newline.carbon:[[@LINE+2]]: missing closing quote in single-line string: "new
+  // CHECK: SYNTAX ERROR: {{.*}}/explorer/testdata/string/fail_newline.carbon:[[@LINE+2]]: missing closing quote in single-line string: "new
   // CHECK-EMPTY:
   Print("new
 line");

+ 1 - 1
explorer/testdata/string/fail_octal.carbon

@@ -11,7 +11,7 @@
 package ExplorerTest api;
 
 fn Main() -> i32 {
-  // CHECK: COMPILATION ERROR: {{.*}}/explorer/testdata/string/fail_octal.carbon:[[@LINE+1]]: Invalid escaping in string: "str\01"
+  // CHECK: SYNTAX ERROR: {{.*}}/explorer/testdata/string/fail_octal.carbon:[[@LINE+1]]: Invalid escaping in string: "str\01"
   Print("str\01");
   return 0;
 }

+ 1 - 1
explorer/testdata/string/fail_raw_block_more_hash_tags_on_left.carbon

@@ -11,7 +11,7 @@
 package ExplorerTest api;
 
 fn Main() -> i32 {
-  // CHECK: COMPILATION ERROR: {{.*}}/explorer/testdata/string/fail_raw_block_more_hash_tags_on_left.carbon:[[@LINE+1]]: Unexpected end of file
+  // CHECK: SYNTAX ERROR: {{.*}}/explorer/testdata/string/fail_raw_block_more_hash_tags_on_left.carbon:[[@LINE+1]]: Unexpected end of file
   var s: String = ##"""
     error: there are more #s on the left than the right.
   """#;

+ 1 - 1
explorer/testdata/string/fail_raw_block_more_hash_tags_on_right.carbon

@@ -11,7 +11,7 @@
 package ExplorerTest api;
 
 fn Main() -> i32 {
-  // CHECK: COMPILATION ERROR: {{.*}}/explorer/testdata/string/fail_raw_block_more_hash_tags_on_right.carbon:[[@LINE+1]]: invalid character '\x23' in source file.
+  // CHECK: SYNTAX ERROR: {{.*}}/explorer/testdata/string/fail_raw_block_more_hash_tags_on_right.carbon:[[@LINE+1]]: invalid character '\x23' in source file.
   var s: String = #"""
     error: there are more #s on the right than the left.
   """##;

+ 1 - 1
explorer/testdata/string/fail_raw_block_quotes_not_on_own_line.carbon

@@ -11,7 +11,7 @@
 package ExplorerTest api;
 
 fn Main() -> i32 {
-  // CHECK: COMPILATION ERROR: {{.*}}/explorer/testdata/string/fail_raw_block_quotes_not_on_own_line.carbon:[[@LINE+1]]: Invalid block string: Should end with triple quotes: error: closing """
+  // CHECK: SYNTAX ERROR: {{.*}}/explorer/testdata/string/fail_raw_block_quotes_not_on_own_line.carbon:[[@LINE+1]]: Invalid block string: Should end with triple quotes: error: closing """
   var s: String = #"""
     error: closing """# is not on its own line.
   """#;

+ 1 - 1
explorer/testdata/string/fail_raw_block_single_line.carbon

@@ -11,7 +11,7 @@
 package ExplorerTest api;
 
 fn CompareStr(s: String) -> i32 {
-  // CHECK: COMPILATION ERROR: {{.*}}/explorer/testdata/string/fail_raw_block_single_line.carbon:[[@LINE+1]]: Invalid block string: Too few lines
+  // CHECK: SYNTAX ERROR: {{.*}}/explorer/testdata/string/fail_raw_block_single_line.carbon:[[@LINE+1]]: Invalid block string: Too few lines
   if (s == #"""raw string literal starting with """#) {
     return 0;
   }

+ 1 - 1
explorer/testdata/string/fail_raw_more_hash_tags_on_left.carbon

@@ -11,7 +11,7 @@
 package ExplorerTest api;
 
 fn CompareStr(s: String) -> i32 {
-  // CHECK: COMPILATION ERROR: {{.*}}/explorer/testdata/string/fail_raw_more_hash_tags_on_left.carbon:[[@LINE+2]]: missing closing quote in single-line string: ##"str"#) {
+  // CHECK: SYNTAX ERROR: {{.*}}/explorer/testdata/string/fail_raw_more_hash_tags_on_left.carbon:[[@LINE+2]]: missing closing quote in single-line string: ##"str"#) {
   // CHECK-EMPTY:
   if (s == ##"str"#) {
     return 0;

+ 1 - 1
explorer/testdata/string/fail_raw_more_hash_tags_on_right.carbon

@@ -11,7 +11,7 @@
 package ExplorerTest api;
 
 fn CompareStr(s: String) -> i32 {
-  // CHECK: COMPILATION ERROR: {{.*}}/explorer/testdata/string/fail_raw_more_hash_tags_on_right.carbon:[[@LINE+1]]: invalid character '\x23' in source file.
+  // CHECK: SYNTAX ERROR: {{.*}}/explorer/testdata/string/fail_raw_more_hash_tags_on_right.carbon:[[@LINE+1]]: invalid character '\x23' in source file.
   if (s == "str"#) {
     return 0;
   }

+ 1 - 1
explorer/testdata/string/fail_tab.carbon

@@ -11,7 +11,7 @@
 package ExplorerTest api;
 
 fn Main() -> i32 {
-  // CHECK: COMPILATION ERROR: {{.*}}/explorer/testdata/string/fail_tab.carbon:[[@LINE+1]]: Invalid escaping in string: "new	line"
+  // CHECK: SYNTAX ERROR: {{.*}}/explorer/testdata/string/fail_tab.carbon:[[@LINE+1]]: Invalid escaping in string: "new	line"
   Print("new	line");
   return 0;
 }

+ 1 - 1
explorer/testdata/tuple/fail_index_var.carbon

@@ -13,6 +13,6 @@ package ExplorerTest api;
 fn Main() -> i32 {
   var x: auto = (0, 1);
   var index: i32 = 0;
-  // CHECK: RUNTIME ERROR: {{.*}}/explorer/testdata/tuple/fail_index_var.carbon:[[@LINE+1]]: could not find `index: i32`
+  // CHECK: COMPILATION ERROR: {{.*}}/explorer/testdata/tuple/fail_index_var.carbon:[[@LINE+1]]: could not find `index: i32`
   return x[index];
 }

+ 3 - 1
explorer/update_checks.py

@@ -27,7 +27,9 @@ _AUTOUPDATE_MARKER = "// AUTOUPDATE: "
 _NOAUTOUPDATE_MARKER = "// NOAUTOUPDATE"
 
 # A regexp matching lines that contain line number references.
-_LINE_NUMBER_RE = r"((?:COMPILATION|RUNTIME) ERROR: [^:]*:)([1-9][0-9]*)(:.*)"
+_LINE_NUMBER_RE = (
+    r"((?:SYNTAX|COMPILATION|RUNTIME) ERROR: [^:]*:)([1-9][0-9]*)(:.*)"
+)
 
 
 def _get_tests() -> Set[str]: