mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-09-24 21:30:12 +01:00
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.
This commit is contained in:
+9
-24
@@ -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.
|
||||
|
||||
@@ -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";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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() << "`";
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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>;
|
||||
|
||||
@@ -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_];
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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";
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
return Success();
|
||||
|
||||
// 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 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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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.
|
||||
�
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
"""#;
|
||||
|
||||
@@ -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.
|
||||
"""##;
|
||||
|
||||
@@ -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.
|
||||
"""#;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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
@@ -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];
|
||||
}
|
||||
|
||||
@@ -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]:
|
||||
|
||||
Reference in New Issue
Block a user