Skip to content

Commit

Permalink
Add diagnostic support so that we can just pass in TypeId. (#3695)
Browse files Browse the repository at this point in the history
Note we may also want to do this with NameId, maybe some other things,
but the TypeId use is pretty broad and repetitive -- I thought I'd start
with it first.
  • Loading branch information
jonmeow authored Feb 9, 2024
1 parent bdff7cc commit 1bf4dc5
Show file tree
Hide file tree
Showing 16 changed files with 168 additions and 104 deletions.
13 changes: 13 additions & 0 deletions toolchain/check/check.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,19 @@ class SemIRLocationTranslator
}
}

auto TranslateArg(DiagnosticTypeTranslation translation, llvm::Any arg) const
-> llvm::Any override {
switch (translation) {
case DiagnosticTypeTranslation::TypeId: {
auto type_id = llvm::any_cast<SemIR::TypeId>(arg);
return sem_ir_->StringifyType(type_id);
}
default:
return DiagnosticLocationTranslator<SemIRLocation>::TranslateArg(
translation, arg);
}
}

private:
auto GetLocationInFile(const SemIR::File* sem_ir,
Parse::NodeLocation node_location) const
Expand Down
42 changes: 20 additions & 22 deletions toolchain/check/convert.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -485,11 +485,10 @@ static auto ConvertStructToStructOrClass(Context& context,
CARBON_DIAGNOSTIC(StructInitMissingFieldInConversion, Error,
"Cannot convert from struct type `{0}` to `{1}`: "
"missing field `{2}` in source type.",
std::string, std::string, std::string);
SemIR::TypeId, SemIR::TypeId, std::string);
context.emitter().Emit(
value_parse_node, StructInitMissingFieldInConversion,
sem_ir.StringifyType(value.type_id()),
sem_ir.StringifyType(target.type_id),
value.type_id(), target.type_id,
sem_ir.names().GetFormatted(dest_field.name_id).str());
}
return SemIR::InstId::BuiltinError;
Expand Down Expand Up @@ -554,9 +553,9 @@ static auto ConvertStructToClass(Context& context, SemIR::StructType src_type,
CARBON_DIAGNOSTIC(ConstructionOfAbstractClass, Error,
"Cannot construct instance of abstract class. "
"Consider using `partial {0}` instead.",
std::string);
SemIR::TypeId);
context.emitter().Emit(value_id, ConstructionOfAbstractClass,
context.sem_ir().StringifyType(target.type_id));
target.type_id);
return SemIR::InstId::BuiltinError;
}
if (class_info.object_repr_id == SemIR::TypeId::Error) {
Expand Down Expand Up @@ -865,9 +864,8 @@ static auto PerformCopy(Context& context, SemIR::InstId expr_id)
// TODO: We don't yet have rules for whether and when a class type is
// copyable, or how to perform the copy.
CARBON_DIAGNOSTIC(CopyOfUncopyableType, Error,
"Cannot copy value of type `{0}`.", std::string);
context.emitter().Emit(expr_id, CopyOfUncopyableType,
context.sem_ir().StringifyType(type_id));
"Cannot copy value of type `{0}`.", SemIR::TypeId);
context.emitter().Emit(expr_id, CopyOfUncopyableType, type_id);
return SemIR::InstId::BuiltinError;
}

Expand Down Expand Up @@ -897,19 +895,20 @@ auto Convert(Context& context, Parse::NodeId parse_node, SemIR::InstId expr_id,
if (!context.TryToCompleteType(target.type_id, [&] {
CARBON_DIAGNOSTIC(IncompleteTypeInInit, Error,
"Initialization of incomplete type `{0}`.",
std::string);
SemIR::TypeId);
CARBON_DIAGNOSTIC(IncompleteTypeInValueConversion, Error,
"Forming value of incomplete type `{0}`.",
std::string);
SemIR::TypeId);
CARBON_DIAGNOSTIC(IncompleteTypeInConversion, Error,
"Invalid use of incomplete type `{0}`.", std::string);
return context.emitter().Build(
parse_node,
target.is_initializer() ? IncompleteTypeInInit
: target.kind == ConversionTarget::Value
? IncompleteTypeInValueConversion
: IncompleteTypeInConversion,
context.sem_ir().StringifyType(target.type_id));
"Invalid use of incomplete type `{0}`.",
SemIR::TypeId);
return context.emitter().Build(parse_node,
target.is_initializer()
? IncompleteTypeInInit
: target.kind == ConversionTarget::Value
? IncompleteTypeInValueConversion
: IncompleteTypeInConversion,
target.type_id);
})) {
return SemIR::InstId::BuiltinError;
}
Expand All @@ -927,17 +926,16 @@ auto Convert(Context& context, Parse::NodeId parse_node, SemIR::InstId expr_id,
if (expr.type_id() != target.type_id) {
CARBON_DIAGNOSTIC(ImplicitAsConversionFailure, Error,
"Cannot implicitly convert from `{0}` to `{1}`.",
std::string, std::string);
SemIR::TypeId, SemIR::TypeId);
CARBON_DIAGNOSTIC(ExplicitAsConversionFailure, Error,
"Cannot convert from `{0}` to `{1}` with `as`.",
std::string, std::string);
SemIR::TypeId, SemIR::TypeId);
context.emitter()
.Build(parse_node,
target.kind == ConversionTarget::ExplicitAs
? ExplicitAsConversionFailure
: ImplicitAsConversionFailure,
sem_ir.StringifyType(expr.type_id()),
sem_ir.StringifyType(target.type_id))
expr.type_id(), target.type_id)
.Emit();
return SemIR::InstId::BuiltinError;
}
Expand Down
5 changes: 2 additions & 3 deletions toolchain/check/decl_name_stack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -231,11 +231,10 @@ auto DeclNameStack::TryResolveQualifier(NameContext& name_context,
.TryAs<SemIR::ClassDecl>()) {
CARBON_DIAGNOSTIC(QualifiedDeclInIncompleteClassScope, Error,
"Cannot declare a member of incomplete class `{0}`.",
std::string);
SemIR::TypeId);
auto builder = context_->emitter().Build(
name_context.parse_node, QualifiedDeclInIncompleteClassScope,
context_->sem_ir().StringifyType(
context_->classes().Get(class_decl->class_id).self_type_id));
context_->classes().Get(class_decl->class_id).self_type_id);
context_->NoteIncompleteClass(class_decl->class_id, builder);
builder.Emit();
} else {
Expand Down
9 changes: 4 additions & 5 deletions toolchain/check/eval.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -257,11 +257,10 @@ static auto PerformAggregateIndex(Context& context, SemIR::Inst inst)
context.ints().Get(bound->int_id).ule(index_val.getZExtValue())) {
CARBON_DIAGNOSTIC(ArrayIndexOutOfBounds, Error,
"Array index `{0}` is past the end of type `{1}`.",
llvm::APSInt, std::string);
context.emitter().Emit(
index_inst.index_id, ArrayIndexOutOfBounds,
llvm::APSInt(index_val, /*isUnsigned=*/true),
context.sem_ir().StringifyType(aggregate_type_id));
llvm::APSInt, SemIR::TypeId);
context.emitter().Emit(index_inst.index_id, ArrayIndexOutOfBounds,
llvm::APSInt(index_val, /*isUnsigned=*/true),
aggregate_type_id);
return SemIR::ConstantId::Error;
}
}
Expand Down
19 changes: 9 additions & 10 deletions toolchain/check/handle_binding_pattern.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,12 +70,12 @@ auto HandleAnyBindingPattern(Context& context, Parse::NodeId parse_node,
cast_type_id = context.AsCompleteType(cast_type_id, [&] {
CARBON_DIAGNOSTIC(IncompleteTypeInVarDecl, Error,
"{0} has incomplete type `{1}`.", llvm::StringLiteral,
std::string);
return context.emitter().Build(
type_node, IncompleteTypeInVarDecl,
enclosing_class_decl ? llvm::StringLiteral("Field")
: llvm::StringLiteral("Variable"),
context.sem_ir().StringifyType(cast_type_id));
SemIR::TypeId);
return context.emitter().Build(type_node, IncompleteTypeInVarDecl,
enclosing_class_decl
? llvm::StringLiteral("Field")
: llvm::StringLiteral("Variable"),
cast_type_id);
});
if (enclosing_class_decl) {
CARBON_CHECK(context_parse_node_kind ==
Expand Down Expand Up @@ -142,10 +142,9 @@ auto HandleAnyBindingPattern(Context& context, Parse::NodeId parse_node,
cast_type_id = context.AsCompleteType(cast_type_id, [&] {
CARBON_DIAGNOSTIC(IncompleteTypeInLetDecl, Error,
"`let` binding has incomplete type `{0}`.",
std::string);
return context.emitter().Build(
type_node, IncompleteTypeInLetDecl,
context.sem_ir().StringifyType(cast_type_id));
SemIR::TypeId);
return context.emitter().Build(type_node, IncompleteTypeInLetDecl,
cast_type_id);
});
// Create the instruction, but don't add it to a block until after we've
// formed its initializer.
Expand Down
4 changes: 2 additions & 2 deletions toolchain/check/handle_call_expr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ auto HandleCallExpr(Context& context, Parse::CallExprId parse_node) -> bool {
auto callee_type_id = context.insts().Get(callee_id).type_id();
if (callee_type_id != SemIR::TypeId::Error) {
CARBON_DIAGNOSTIC(CallToNonCallable, Error,
"Value of type `{0}` is not callable.", std::string);
"Value of type `{0}` is not callable.", SemIR::TypeId);
context.emitter().Emit(call_expr_parse_node, CallToNonCallable,
context.sem_ir().StringifyType(callee_type_id));
callee_type_id);
}
context.node_stack().Push(parse_node, SemIR::InstId::BuiltinError);
return true;
Expand Down
12 changes: 5 additions & 7 deletions toolchain/check/handle_class.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -208,9 +208,8 @@ static auto DiagnoseBaseIsFinal(Context& context, Parse::NodeId parse_node,
CARBON_DIAGNOSTIC(BaseIsFinal, Error,
"Deriving from final type `{0}`. Base type must be an "
"`abstract` or `base` class.",
std::string);
context.emitter().Emit(parse_node, BaseIsFinal,
context.sem_ir().StringifyType(base_type_id));
SemIR::TypeId);
context.emitter().Emit(parse_node, BaseIsFinal, base_type_id);
}

// Checks that the specified base type is valid.
Expand All @@ -219,10 +218,9 @@ static auto CheckBaseType(Context& context, Parse::NodeId parse_node,
auto base_type_id = ExprAsType(context, parse_node, base_expr_id);
base_type_id = context.AsCompleteType(base_type_id, [&] {
CARBON_DIAGNOSTIC(IncompleteTypeInBaseDecl, Error,
"Base `{0}` is an incomplete type.", std::string);
return context.emitter().Build(
parse_node, IncompleteTypeInBaseDecl,
context.sem_ir().StringifyType(base_type_id));
"Base `{0}` is an incomplete type.", SemIR::TypeId);
return context.emitter().Build(parse_node, IncompleteTypeInBaseDecl,
base_type_id);
});

if (base_type_id == SemIR::TypeId::Error) {
Expand Down
16 changes: 8 additions & 8 deletions toolchain/check/handle_function.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,11 @@ static auto BuildFunctionDecl(Context& context,

return_type_id = context.AsCompleteType(return_type_id, [&] {
CARBON_DIAGNOSTIC(IncompleteTypeInFunctionReturnType, Error,
"Function returns incomplete type `{0}`.", std::string);
return context.emitter().Build(
return_node_and_id->first, IncompleteTypeInFunctionReturnType,
context.sem_ir().StringifyType(return_type_id));
"Function returns incomplete type `{0}`.",
SemIR::TypeId);
return context.emitter().Build(return_node_and_id->first,
IncompleteTypeInFunctionReturnType,
return_type_id);
});

if (!SemIR::GetInitRepr(context.sem_ir(), return_type_id)
Expand Down Expand Up @@ -241,10 +242,9 @@ auto HandleFunctionDefinitionStart(Context& context,
CARBON_DIAGNOSTIC(
IncompleteTypeInFunctionParam, Error,
"Parameter has incomplete type `{0}` in function definition.",
std::string);
return context.emitter().Build(
param_id, IncompleteTypeInFunctionParam,
context.sem_ir().StringifyType(param.type_id()));
SemIR::TypeId);
return context.emitter().Build(param_id, IncompleteTypeInFunctionParam,
param.type_id());
});
}

Expand Down
16 changes: 7 additions & 9 deletions toolchain/check/handle_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,10 +115,9 @@ static auto ExtendImpl(Context& context, Parse::AnyImplDeclId parse_node,
CARBON_DIAGNOSTIC(
ExtendUndefinedInterface, Error,
"`extend impl` requires a definition for interface `{0}`.",
std::string);
auto diag =
context.emitter().Build(parse_node, ExtendUndefinedInterface,
context.sem_ir().StringifyType(constraint_id));
SemIR::TypeId);
auto diag = context.emitter().Build(parse_node, ExtendUndefinedInterface,
constraint_id);
context.NoteUndefinedInterface(interface_type->interface_id, diag);
diag.Emit();
enclosing_scope.has_error = true;
Expand Down Expand Up @@ -198,14 +197,13 @@ auto HandleImplDefinitionStart(Context& context,

if (impl_info.definition_id.is_valid()) {
CARBON_DIAGNOSTIC(ImplRedefinition, Error,
"Redefinition of `impl {0} as {1}`.", std::string,
std::string);
"Redefinition of `impl {0} as {1}`.", SemIR::TypeId,
SemIR::TypeId);
CARBON_DIAGNOSTIC(ImplPreviousDefinition, Note,
"Previous definition was here.");
context.emitter()
.Build(parse_node, ImplRedefinition,
context.sem_ir().StringifyType(impl_info.self_id),
context.sem_ir().StringifyType(impl_info.constraint_id))
.Build(parse_node, ImplRedefinition, impl_info.self_id,
impl_info.constraint_id)
.Note(impl_info.definition_id, ImplPreviousDefinition)
.Emit();
} else {
Expand Down
15 changes: 7 additions & 8 deletions toolchain/check/handle_index.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,10 @@ static auto ValidateTupleIndex(Context& context, Parse::NodeId parse_node,
CARBON_DIAGNOSTIC(
TupleIndexOutOfBounds, Error,
"Tuple element index `{0}` is past the end of type `{1}`.",
llvm::APSInt, std::string);
context.emitter().Emit(
parse_node, TupleIndexOutOfBounds,
llvm::APSInt(index_val, /*isUnsigned=*/true),
context.sem_ir().StringifyType(operand_inst.type_id()));
llvm::APSInt, SemIR::TypeId);
context.emitter().Emit(parse_node, TupleIndexOutOfBounds,
llvm::APSInt(index_val, /*isUnsigned=*/true),
operand_inst.type_id());
return nullptr;
}
return &index_val;
Expand Down Expand Up @@ -110,9 +109,9 @@ auto HandleIndexExpr(Context& context, Parse::IndexExprId parse_node) -> bool {
default: {
if (operand_type_id != SemIR::TypeId::Error) {
CARBON_DIAGNOSTIC(TypeNotIndexable, Error,
"Type `{0}` does not support indexing.", std::string);
context.emitter().Emit(parse_node, TypeNotIndexable,
context.sem_ir().StringifyType(operand_type_id));
"Type `{0}` does not support indexing.",
SemIR::TypeId);
context.emitter().Emit(parse_node, TypeNotIndexable, operand_type_id);
}
context.node_stack().Push(parse_node, SemIR::InstId::BuiltinError);
return true;
Expand Down
17 changes: 8 additions & 9 deletions toolchain/check/handle_name.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,10 +121,9 @@ auto HandleMemberAccessExpr(Context& context,
if (!context.TryToCompleteType(base_type_id, [&] {
CARBON_DIAGNOSTIC(IncompleteTypeInMemberAccess, Error,
"Member access into object of incomplete type `{0}`.",
std::string);
return context.emitter().Build(
base_id, IncompleteTypeInMemberAccess,
context.sem_ir().StringifyType(base_type_id));
SemIR::TypeId);
return context.emitter().Build(base_id, IncompleteTypeInMemberAccess,
base_type_id);
})) {
context.node_stack().Push(parse_node, SemIR::InstId::BuiltinError);
return true;
Expand Down Expand Up @@ -223,10 +222,10 @@ auto HandleMemberAccessExpr(Context& context,
}
}
CARBON_DIAGNOSTIC(QualifiedExprNameNotFound, Error,
"Type `{0}` does not have a member `{1}`.", std::string,
std::string);
"Type `{0}` does not have a member `{1}`.",
SemIR::TypeId, std::string);
context.emitter().Emit(parse_node, QualifiedExprNameNotFound,
context.sem_ir().StringifyType(base_type_id),
base_type_id,
context.names().GetFormatted(name_id).str());
break;
}
Expand All @@ -237,9 +236,9 @@ auto HandleMemberAccessExpr(Context& context,
if (base_type_id != SemIR::TypeId::Error) {
CARBON_DIAGNOSTIC(QualifiedExprUnsupported, Error,
"Type `{0}` does not support qualified expressions.",
std::string);
SemIR::TypeId);
context.emitter().Emit(parse_node, QualifiedExprUnsupported,
context.sem_ir().StringifyType(base_type_id));
base_type_id);
}
break;
}
Expand Down
7 changes: 3 additions & 4 deletions toolchain/check/handle_operator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -296,10 +296,9 @@ auto HandlePrefixOperatorStar(Context& context,
} else if (type_id != SemIR::TypeId::Error) {
CARBON_DIAGNOSTIC(DerefOfNonPointer, Error,
"Cannot dereference operand of non-pointer type `{0}`.",
std::string);
auto builder =
context.emitter().Build(TokenOnly(parse_node), DerefOfNonPointer,
context.sem_ir().StringifyType(type_id));
SemIR::TypeId);
auto builder = context.emitter().Build(TokenOnly(parse_node),
DerefOfNonPointer, type_id);
// TODO: Check for any facet here, rather than only a type.
if (type_id == SemIR::TypeId::TypeType) {
CARBON_DIAGNOSTIC(
Expand Down
Loading

0 comments on commit 1bf4dc5

Please sign in to comment.