diff --git a/toolchain/check/context.cpp b/toolchain/check/context.cpp index 19bc9036a410..1007446c0582 100644 --- a/toolchain/check/context.cpp +++ b/toolchain/check/context.cpp @@ -214,76 +214,6 @@ auto Context::ReplaceInstPreservingConstantValue(SemIR::InstId inst_id, CARBON_CHECK(old_const_id == new_const_id); } -auto Context::DiagnoseDuplicateName(SemIRLoc dup_def, SemIRLoc prev_def) - -> void { - CARBON_DIAGNOSTIC(NameDeclDuplicate, Error, - "duplicate name being declared in the same scope"); - CARBON_DIAGNOSTIC(NameDeclPrevious, Note, "name is previously declared here"); - emitter_->Build(dup_def, NameDeclDuplicate) - .Note(prev_def, NameDeclPrevious) - .Emit(); -} - -auto Context::DiagnosePoisonedName(SemIR::LocId poisoning_loc_id, - SemIR::LocId decl_name_loc_id) -> void { - CARBON_CHECK(poisoning_loc_id.has_value(), - "Trying to diagnose poisoned name with no poisoning location"); - CARBON_DIAGNOSTIC(NameUseBeforeDecl, Error, - "name used before it was declared"); - CARBON_DIAGNOSTIC(NameUseBeforeDeclNote, Note, "declared here"); - emitter_->Build(poisoning_loc_id, NameUseBeforeDecl) - .Note(decl_name_loc_id, NameUseBeforeDeclNote) - .Emit(); -} - -auto Context::DiagnoseNameNotFound(SemIRLoc loc, SemIR::NameId name_id) - -> void { - CARBON_DIAGNOSTIC(NameNotFound, Error, "name `{0}` not found", SemIR::NameId); - emitter_->Emit(loc, NameNotFound, name_id); -} - -auto Context::NoteAbstractClass(SemIR::ClassId class_id, - DiagnosticBuilder& builder) -> void { - const auto& class_info = classes().Get(class_id); - CARBON_CHECK( - class_info.inheritance_kind == SemIR::Class::InheritanceKind::Abstract, - "Class is not abstract"); - CARBON_DIAGNOSTIC(ClassAbstractHere, Note, - "class was declared abstract here"); - builder.Note(class_info.definition_id, ClassAbstractHere); -} - -auto Context::NoteIncompleteClass(SemIR::ClassId class_id, - DiagnosticBuilder& builder) -> void { - const auto& class_info = classes().Get(class_id); - CARBON_CHECK(!class_info.is_defined(), "Class is not incomplete"); - if (class_info.has_definition_started()) { - CARBON_DIAGNOSTIC(ClassIncompleteWithinDefinition, Note, - "class is incomplete within its definition"); - builder.Note(class_info.definition_id, ClassIncompleteWithinDefinition); - } else { - CARBON_DIAGNOSTIC(ClassForwardDeclaredHere, Note, - "class was forward declared here"); - builder.Note(class_info.latest_decl_id(), ClassForwardDeclaredHere); - } -} - -auto Context::NoteUndefinedInterface(SemIR::InterfaceId interface_id, - DiagnosticBuilder& builder) -> void { - const auto& interface_info = interfaces().Get(interface_id); - CARBON_CHECK(!interface_info.is_defined(), "Interface is not incomplete"); - if (interface_info.is_being_defined()) { - CARBON_DIAGNOSTIC(InterfaceUndefinedWithinDefinition, Note, - "interface is currently being defined"); - builder.Note(interface_info.definition_id, - InterfaceUndefinedWithinDefinition); - } else { - CARBON_DIAGNOSTIC(InterfaceForwardDeclaredHere, Note, - "interface was forward declared here"); - builder.Note(interface_info.latest_decl_id(), InterfaceForwardDeclaredHere); - } -} - auto Context::Finalize() -> void { // Pop information for the file-level scope. sem_ir().set_top_inst_block_id(inst_block_stack().Pop()); diff --git a/toolchain/check/context.h b/toolchain/check/context.h index 83cd668d0ce2..bb5f50bb42cc 100644 --- a/toolchain/check/context.h +++ b/toolchain/check/context.h @@ -178,28 +178,6 @@ class Context { sem_ir().insts().SetLocId(inst_id, SemIR::LocId(node_id)); } - // Prints a diagnostic for a duplicate name. - auto DiagnoseDuplicateName(SemIRLoc dup_def, SemIRLoc prev_def) -> void; - - // Prints a diagnostic for a poisoned name when it's later declared. - auto DiagnosePoisonedName(SemIR::LocId poisoning_loc_id, - SemIR::LocId decl_name_loc_id) -> void; - - // Prints a diagnostic for a missing name. - auto DiagnoseNameNotFound(SemIRLoc loc, SemIR::NameId name_id) -> void; - - // Adds a note to a diagnostic explaining that a class is incomplete. - auto NoteIncompleteClass(SemIR::ClassId class_id, DiagnosticBuilder& builder) - -> void; - - // Adds a note to a diagnostic explaining that a class is abstract. - auto NoteAbstractClass(SemIR::ClassId class_id, DiagnosticBuilder& builder) - -> void; - - // Adds a note to a diagnostic explaining that an interface is not defined. - auto NoteUndefinedInterface(SemIR::InterfaceId interface_id, - DiagnosticBuilder& builder) -> void; - // Returns the type ID for a constant that is a type value, i.e. it is a value // of type `TypeType`. // diff --git a/toolchain/check/decl_name_stack.cpp b/toolchain/check/decl_name_stack.cpp index 08750ffa4979..f2fdf59b367b 100644 --- a/toolchain/check/decl_name_stack.cpp +++ b/toolchain/check/decl_name_stack.cpp @@ -11,6 +11,7 @@ #include "toolchain/check/merge.h" #include "toolchain/check/name_component.h" #include "toolchain/check/name_lookup.h" +#include "toolchain/check/type_completion.h" #include "toolchain/diagnostics/diagnostic.h" #include "toolchain/sem_ir/ids.h" #include "toolchain/sem_ir/name_scope.h" @@ -176,10 +177,10 @@ auto DeclNameStack::AddNameOrDiagnose(NameContext name_context, SemIR::InstId target_id, SemIR::AccessKind access_kind) -> void { if (name_context.state == DeclNameStack::NameContext::State::Poisoned) { - context_->DiagnosePoisonedName(name_context.poisoning_loc_id, - name_context.loc_id); + DiagnosePoisonedName(*context_, name_context.poisoning_loc_id, + name_context.loc_id); } else if (auto id = name_context.prev_inst_id(); id.has_value()) { - context_->DiagnoseDuplicateName(target_id, id); + DiagnoseDuplicateName(*context_, target_id, id); } else { AddName(name_context, target_id, access_kind); } @@ -299,8 +300,8 @@ static auto CheckQualifierIsResolved( case DeclNameStack::NameContext::State::Unresolved: // Because more qualifiers were found, we diagnose that the earlier // qualifier failed to resolve. - context.DiagnoseNameNotFound(name_context.loc_id, - name_context.unresolved_name_id); + DiagnoseNameNotFound(context, name_context.loc_id, + name_context.unresolved_name_id); return false; case DeclNameStack::NameContext::State::Finished: @@ -324,7 +325,7 @@ static auto DiagnoseQualifiedDeclInIncompleteClassScope(Context& context, auto builder = context.emitter().Build(loc, QualifiedDeclInIncompleteClassScope, context.classes().Get(class_id).self_type_id); - context.NoteIncompleteClass(class_id, builder); + NoteIncompleteClass(context, class_id, builder); builder.Emit(); } @@ -338,7 +339,7 @@ static auto DiagnoseQualifiedDeclInUndefinedInterfaceScope( InstIdAsType); auto builder = context.emitter().Build( loc, QualifiedDeclInUndefinedInterfaceScope, interface_inst_id); - context.NoteUndefinedInterface(interface_id, builder); + NoteUndefinedInterface(context, interface_id, builder); builder.Emit(); } diff --git a/toolchain/check/handle_class.cpp b/toolchain/check/handle_class.cpp index b902f0424a3f..50b854b47026 100644 --- a/toolchain/check/handle_class.cpp +++ b/toolchain/check/handle_class.cpp @@ -15,6 +15,7 @@ #include "toolchain/check/merge.h" #include "toolchain/check/modifiers.h" #include "toolchain/check/name_component.h" +#include "toolchain/check/name_lookup.h" #include "toolchain/check/type_completion.h" #include "toolchain/parse/node_ids.h" #include "toolchain/sem_ir/function.h" @@ -111,8 +112,8 @@ static auto MergeOrAddName(Context& context, Parse::AnyClassDeclId node_id, access_kind); if (lookup_result.is_poisoned()) { // This is a declaration of a poisoned name. - context.DiagnosePoisonedName(lookup_result.poisoning_loc_id(), - name_context.loc_id); + DiagnosePoisonedName(context, lookup_result.poisoning_loc_id(), + name_context.loc_id); return; } @@ -161,7 +162,7 @@ static auto MergeOrAddName(Context& context, Parse::AnyClassDeclId node_id, if (!prev_class_id.has_value()) { // This is a redeclaration of something other than a class. - context.DiagnoseDuplicateName(class_decl_id, prev_id); + DiagnoseDuplicateName(context, class_decl_id, prev_id); return; } diff --git a/toolchain/check/handle_export.cpp b/toolchain/check/handle_export.cpp index c12accc21941..2a3afaa7b413 100644 --- a/toolchain/check/handle_export.cpp +++ b/toolchain/check/handle_export.cpp @@ -7,6 +7,7 @@ #include "toolchain/check/handle.h" #include "toolchain/check/modifiers.h" #include "toolchain/check/name_component.h" +#include "toolchain/check/name_lookup.h" #include "toolchain/parse/typed_nodes.h" #include "toolchain/sem_ir/ids.h" #include "toolchain/sem_ir/typed_insts.h" @@ -37,7 +38,7 @@ auto HandleParseNode(Context& context, Parse::ExportDeclId node_id) -> bool { auto inst_id = name_context.prev_inst_id(); if (!inst_id.has_value()) { - context.DiagnoseNameNotFound(node_id, name_context.name_id_for_new_inst()); + DiagnoseNameNotFound(context, node_id, name_context.name_id_for_new_inst()); return true; } diff --git a/toolchain/check/handle_function.cpp b/toolchain/check/handle_function.cpp index 54cfbe7aa1f8..776c7d9ebd6a 100644 --- a/toolchain/check/handle_function.cpp +++ b/toolchain/check/handle_function.cpp @@ -18,6 +18,7 @@ #include "toolchain/check/merge.h" #include "toolchain/check/modifiers.h" #include "toolchain/check/name_component.h" +#include "toolchain/check/name_lookup.h" #include "toolchain/check/type_completion.h" #include "toolchain/sem_ir/builtin_function_kind.h" #include "toolchain/sem_ir/entry_point.h" @@ -176,7 +177,7 @@ static auto TryMergeRedecl(Context& context, Parse::AnyFunctionDeclId node_id, } if (!prev_function_id.has_value()) { - context.DiagnoseDuplicateName(function_info.latest_decl_id(), prev_id); + DiagnoseDuplicateName(context, function_info.latest_decl_id(), prev_id); return; } @@ -272,8 +273,8 @@ static auto BuildFunctionDecl(Context& context, } if (name_context.state == DeclNameStack::NameContext::State::Poisoned) { - context.DiagnosePoisonedName(name_context.poisoning_loc_id, - name_context.loc_id); + DiagnosePoisonedName(context, name_context.poisoning_loc_id, + name_context.loc_id); } else { TryMergeRedecl(context, node_id, name_context.prev_inst_id(), function_decl, function_info, is_definition); diff --git a/toolchain/check/handle_interface.cpp b/toolchain/check/handle_interface.cpp index 941f26c6ed53..991315678697 100644 --- a/toolchain/check/handle_interface.cpp +++ b/toolchain/check/handle_interface.cpp @@ -9,6 +9,7 @@ #include "toolchain/check/merge.h" #include "toolchain/check/modifiers.h" #include "toolchain/check/name_component.h" +#include "toolchain/check/name_lookup.h" #include "toolchain/sem_ir/typed_insts.h" namespace Carbon::Check { @@ -65,8 +66,8 @@ static auto BuildInterfaceDecl(Context& context, introducer.modifier_set.GetAccessKind()); if (lookup_result.is_poisoned()) { // This is a declaration of a poisoned name. - context.DiagnosePoisonedName(lookup_result.poisoning_loc_id(), - name_context.loc_id); + DiagnosePoisonedName(context, lookup_result.poisoning_loc_id(), + name_context.loc_id); } else if (lookup_result.is_found()) { SemIR::InstId existing_id = lookup_result.target_inst_id(); if (auto existing_interface_decl = @@ -102,7 +103,7 @@ static auto BuildInterfaceDecl(Context& context, } } else { // This is a redeclaration of something other than a interface. - context.DiagnoseDuplicateName(interface_decl_id, existing_id); + DiagnoseDuplicateName(context, interface_decl_id, existing_id); } } diff --git a/toolchain/check/handle_namespace.cpp b/toolchain/check/handle_namespace.cpp index 613097c1c684..08f78775d34f 100644 --- a/toolchain/check/handle_namespace.cpp +++ b/toolchain/check/handle_namespace.cpp @@ -7,6 +7,7 @@ #include "toolchain/check/handle.h" #include "toolchain/check/modifiers.h" #include "toolchain/check/name_component.h" +#include "toolchain/check/name_lookup.h" #include "toolchain/sem_ir/ids.h" #include "toolchain/sem_ir/inst.h" #include "toolchain/sem_ir/name_scope.h" @@ -46,8 +47,8 @@ auto HandleParseNode(Context& context, Parse::NamespaceId node_id) -> bool { context.decl_name_stack().LookupOrAddName(name_context, namespace_id, SemIR::AccessKind::Public); if (lookup_result.is_poisoned()) { - context.DiagnosePoisonedName(lookup_result.poisoning_loc_id(), - name_context.loc_id); + DiagnosePoisonedName(context, lookup_result.poisoning_loc_id(), + name_context.loc_id); } else if (lookup_result.is_found()) { SemIR::InstId existing_inst_id = lookup_result.target_inst_id(); if (auto existing = @@ -62,7 +63,7 @@ auto HandleParseNode(Context& context, Parse::NamespaceId node_id) -> bool { .Get(existing->name_scope_id) .is_closed_import()) { // The existing name is a package name, so this is a name conflict. - context.DiagnoseDuplicateName(namespace_id, existing_inst_id); + DiagnoseDuplicateName(context, namespace_id, existing_inst_id); // Treat this as a local namespace name from now on to avoid further // diagnostics. @@ -76,7 +77,7 @@ auto HandleParseNode(Context& context, Parse::NamespaceId node_id) -> bool { context.SetNamespaceNodeId(existing_inst_id, node_id); } } else { - context.DiagnoseDuplicateName(namespace_id, existing_inst_id); + DiagnoseDuplicateName(context, namespace_id, existing_inst_id); } } diff --git a/toolchain/check/import.cpp b/toolchain/check/import.cpp index ace91932a99f..337825a04c72 100644 --- a/toolchain/check/import.cpp +++ b/toolchain/check/import.cpp @@ -10,6 +10,7 @@ #include "toolchain/check/context.h" #include "toolchain/check/import_ref.h" #include "toolchain/check/merge.h" +#include "toolchain/check/name_lookup.h" #include "toolchain/parse/node_ids.h" #include "toolchain/sem_ir/file.h" #include "toolchain/sem_ir/ids.h" @@ -105,7 +106,7 @@ auto AddImportNamespace(Context& context, SemIR::TypeId namespace_type_id, if (diagnose_duplicate_namespace) { auto import_id = make_import_id(); CARBON_CHECK(import_id.has_value()); - context.DiagnoseDuplicateName(import_id, prev_inst_id); + DiagnoseDuplicateName(context, import_id, prev_inst_id); } return {.name_scope_id = namespace_inst->name_scope_id, .inst_id = prev_inst_id, @@ -146,7 +147,7 @@ auto AddImportNamespace(Context& context, SemIR::TypeId namespace_type_id, // may be overwriting a poisoned entry here. auto& result = parent_scope->GetEntry(entry_id).result; if (!result.is_poisoned() && !inserted) { - context.DiagnoseDuplicateName(namespace_id, result.target_inst_id()); + DiagnoseDuplicateName(context, namespace_id, result.target_inst_id()); } result = SemIR::ScopeLookupResult::MakeFound(namespace_id, SemIR::AccessKind::Public); diff --git a/toolchain/check/import_ref.cpp b/toolchain/check/import_ref.cpp index d5b3130417a8..b6cde2c5c9cb 100644 --- a/toolchain/check/import_ref.cpp +++ b/toolchain/check/import_ref.cpp @@ -9,6 +9,7 @@ #include "toolchain/check/context.h" #include "toolchain/check/eval.h" #include "toolchain/check/generic.h" +#include "toolchain/check/name_lookup.h" #include "toolchain/parse/node_ids.h" #include "toolchain/sem_ir/constant.h" #include "toolchain/sem_ir/file.h" @@ -147,7 +148,7 @@ auto VerifySameCanonicalImportIRInst(Context& context, SemIR::InstId prev_id, } auto conflict_id = AddImportRef(context, {.ir_id = new_ir_id, .inst_id = new_inst_id}); - context.DiagnoseDuplicateName(conflict_id, prev_id); + DiagnoseDuplicateName(context, conflict_id, prev_id); } // Returns an instruction that has the specified constant value. diff --git a/toolchain/check/name_lookup.cpp b/toolchain/check/name_lookup.cpp index 22482d70d5a1..deeac77226de 100644 --- a/toolchain/check/name_lookup.cpp +++ b/toolchain/check/name_lookup.cpp @@ -17,7 +17,7 @@ auto AddNameToLookup(Context& context, SemIR::NameId name_id, if (auto existing = context.scope_stack().LookupOrAddName(name_id, target_id, scope_index); existing.has_value()) { - context.DiagnoseDuplicateName(target_id, existing); + DiagnoseDuplicateName(context, target_id, existing); } } @@ -120,7 +120,7 @@ auto LookupUnqualifiedName(Context& context, Parse::NodeId node_id, // We didn't find anything at all. if (required) { - context.DiagnoseNameNotFound(node_id, name_id); + DiagnoseNameNotFound(context, node_id, name_id); } return {.specific_id = SemIR::SpecificId::None, @@ -480,4 +480,34 @@ auto LookupNameInCore(Context& context, SemIR::LocId loc_id, scope_result.target_inst_id()); } +auto DiagnoseDuplicateName(Context& context, SemIRLoc dup_def, + SemIRLoc prev_def) -> void { + CARBON_DIAGNOSTIC(NameDeclDuplicate, Error, + "duplicate name being declared in the same scope"); + CARBON_DIAGNOSTIC(NameDeclPrevious, Note, "name is previously declared here"); + context.emitter() + .Build(dup_def, NameDeclDuplicate) + .Note(prev_def, NameDeclPrevious) + .Emit(); +} + +auto DiagnosePoisonedName(Context& context, SemIR::LocId poisoning_loc_id, + SemIR::LocId decl_name_loc_id) -> void { + CARBON_CHECK(poisoning_loc_id.has_value(), + "Trying to diagnose poisoned name with no poisoning location"); + CARBON_DIAGNOSTIC(NameUseBeforeDecl, Error, + "name used before it was declared"); + CARBON_DIAGNOSTIC(NameUseBeforeDeclNote, Note, "declared here"); + context.emitter() + .Build(poisoning_loc_id, NameUseBeforeDecl) + .Note(decl_name_loc_id, NameUseBeforeDeclNote) + .Emit(); +} + +auto DiagnoseNameNotFound(Context& context, SemIRLoc loc, SemIR::NameId name_id) + -> void { + CARBON_DIAGNOSTIC(NameNotFound, Error, "name `{0}` not found", SemIR::NameId); + context.emitter().Emit(loc, NameNotFound, name_id); +} + } // namespace Carbon::Check diff --git a/toolchain/check/name_lookup.h b/toolchain/check/name_lookup.h index cf5fea39b105..4fc4ee435f89 100644 --- a/toolchain/check/name_lookup.h +++ b/toolchain/check/name_lookup.h @@ -97,6 +97,18 @@ auto LookupQualifiedName(Context& context, SemIR::LocId loc_id, auto LookupNameInCore(Context& context, SemIR::LocId loc_id, llvm::StringRef name) -> SemIR::InstId; +// Prints a diagnostic for a duplicate name. +auto DiagnoseDuplicateName(Context& context, SemIRLoc dup_def, + SemIRLoc prev_def) -> void; + +// Prints a diagnostic for a poisoned name when it's later declared. +auto DiagnosePoisonedName(Context& context, SemIR::LocId poisoning_loc_id, + SemIR::LocId decl_name_loc_id) -> void; + +// Prints a diagnostic for a missing name. +auto DiagnoseNameNotFound(Context& context, SemIRLoc loc, SemIR::NameId name_id) + -> void; + } // namespace Carbon::Check #endif // CARBON_TOOLCHAIN_CHECK_NAME_LOOKUP_H_ diff --git a/toolchain/check/type_completion.cpp b/toolchain/check/type_completion.cpp index c6345e6ffb55..4fa467e1f709 100644 --- a/toolchain/check/type_completion.cpp +++ b/toolchain/check/type_completion.cpp @@ -261,7 +261,7 @@ auto TypeCompleter::AddNestedIncompleteTypes(SemIR::Inst type_inst) -> bool { if (!class_info.is_defined()) { if (diagnoser_) { auto builder = diagnoser_(); - context_.NoteIncompleteClass(inst.class_id, builder); + NoteIncompleteClass(context_, inst.class_id, builder); builder.Emit(); } return false; @@ -497,6 +497,18 @@ auto RequireCompleteType(Context& context, SemIR::TypeId type_id, return true; } +// Adds a note to a diagnostic explaining that a class is abstract. +static auto NoteAbstractClass(Context& context, SemIR::ClassId class_id, + Context::DiagnosticBuilder& builder) -> void { + const auto& class_info = context.classes().Get(class_id); + CARBON_CHECK( + class_info.inheritance_kind == SemIR::Class::InheritanceKind::Abstract, + "Class is not abstract"); + CARBON_DIAGNOSTIC(ClassAbstractHere, Note, + "class was declared abstract here"); + builder.Note(class_info.definition_id, ClassAbstractHere); +} + auto RequireConcreteType(Context& context, SemIR::TypeId type_id, SemIR::LocId loc_id, Context::BuildDiagnosticFn diagnoser, @@ -519,7 +531,7 @@ auto RequireConcreteType(Context& context, SemIR::TypeId type_id, if (!builder) { return false; } - context.NoteAbstractClass(class_type->class_id, builder); + NoteAbstractClass(context, class_type->class_id, builder); builder.Emit(); return false; } @@ -541,7 +553,7 @@ auto RequireDefinedType(Context& context, SemIR::TypeId type_id, auto interface_id = interface.interface_id; if (!context.interfaces().Get(interface_id).is_defined()) { auto builder = diagnoser(); - context.NoteUndefinedInterface(interface_id, builder); + NoteUndefinedInterface(context, interface_id, builder); builder.Emit(); return false; } @@ -590,4 +602,35 @@ auto AsConcreteType(Context& context, SemIR::TypeId type_id, : SemIR::ErrorInst::SingletonTypeId; } +auto NoteIncompleteClass(Context& context, SemIR::ClassId class_id, + Context::DiagnosticBuilder& builder) -> void { + const auto& class_info = context.classes().Get(class_id); + CARBON_CHECK(!class_info.is_defined(), "Class is not incomplete"); + if (class_info.has_definition_started()) { + CARBON_DIAGNOSTIC(ClassIncompleteWithinDefinition, Note, + "class is incomplete within its definition"); + builder.Note(class_info.definition_id, ClassIncompleteWithinDefinition); + } else { + CARBON_DIAGNOSTIC(ClassForwardDeclaredHere, Note, + "class was forward declared here"); + builder.Note(class_info.latest_decl_id(), ClassForwardDeclaredHere); + } +} + +auto NoteUndefinedInterface(Context& context, SemIR::InterfaceId interface_id, + Context::DiagnosticBuilder& builder) -> void { + const auto& interface_info = context.interfaces().Get(interface_id); + CARBON_CHECK(!interface_info.is_defined(), "Interface is not incomplete"); + if (interface_info.is_being_defined()) { + CARBON_DIAGNOSTIC(InterfaceUndefinedWithinDefinition, Note, + "interface is currently being defined"); + builder.Note(interface_info.definition_id, + InterfaceUndefinedWithinDefinition); + } else { + CARBON_DIAGNOSTIC(InterfaceForwardDeclaredHere, Note, + "interface was forward declared here"); + builder.Note(interface_info.latest_decl_id(), InterfaceForwardDeclaredHere); + } +} + } // namespace Carbon::Check diff --git a/toolchain/check/type_completion.h b/toolchain/check/type_completion.h index 191c63d0abae..64e5d9bca09f 100644 --- a/toolchain/check/type_completion.h +++ b/toolchain/check/type_completion.h @@ -73,6 +73,14 @@ auto AsConcreteType(Context& context, SemIR::TypeId type_id, Context::BuildDiagnosticFn abstract_diagnoser) -> SemIR::TypeId; +// Adds a note to a diagnostic explaining that a class is incomplete. +auto NoteIncompleteClass(Context& context, SemIR::ClassId class_id, + Context::DiagnosticBuilder& builder) -> void; + +// Adds a note to a diagnostic explaining that an interface is not defined. +auto NoteUndefinedInterface(Context& context, SemIR::InterfaceId interface_id, + Context::DiagnosticBuilder& builder) -> void; + } // namespace Carbon::Check #endif // CARBON_TOOLCHAIN_CHECK_TYPE_COMPLETION_H_