diff --git a/toolchain/check/BUILD b/toolchain/check/BUILD index 9ff786751c9d..186ffbd387c9 100644 --- a/toolchain/check/BUILD +++ b/toolchain/check/BUILD @@ -91,6 +91,7 @@ cc_library( "//common:array_stack", "//common:check", "//common:map", + "//common:ostream", "//common:raw_string_ostream", "//common:set", "//common:vlog", diff --git a/toolchain/check/context.cpp b/toolchain/check/context.cpp index 26fe5c15bbb2..4ab257f3331f 100644 --- a/toolchain/check/context.cpp +++ b/toolchain/check/context.cpp @@ -4,43 +4,11 @@ #include "toolchain/check/context.h" -#include -#include -#include - #include "common/check.h" -#include "common/vlog.h" -#include "llvm/ADT/Sequence.h" -#include "toolchain/check/convert.h" -#include "toolchain/check/decl_name_stack.h" -#include "toolchain/check/eval.h" -#include "toolchain/check/generic.h" -#include "toolchain/check/generic_region_stack.h" -#include "toolchain/check/import.h" -#include "toolchain/check/import_ref.h" -#include "toolchain/check/inst_block_stack.h" -#include "toolchain/check/interface.h" -#include "toolchain/check/merge.h" -#include "toolchain/check/type_completion.h" -#include "toolchain/diagnostics/diagnostic_emitter.h" -#include "toolchain/diagnostics/format_providers.h" -#include "toolchain/lex/tokenized_buffer.h" -#include "toolchain/parse/node_ids.h" -#include "toolchain/parse/node_kind.h" -#include "toolchain/sem_ir/file.h" -#include "toolchain/sem_ir/formatter.h" -#include "toolchain/sem_ir/generic.h" -#include "toolchain/sem_ir/ids.h" -#include "toolchain/sem_ir/import_ir.h" -#include "toolchain/sem_ir/inst.h" -#include "toolchain/sem_ir/inst_kind.h" -#include "toolchain/sem_ir/name_scope.h" -#include "toolchain/sem_ir/type_info.h" -#include "toolchain/sem_ir/typed_insts.h" namespace Carbon::Check { -Context::Context(DiagnosticEmitter* emitter, +Context::Context(DiagnosticEmitter* emitter, Parse::GetTreeAndSubtreesFn tree_and_subtrees_getter, SemIR::File* sem_ir, int imported_ir_count, int total_ir_count, llvm::raw_ostream* vlog_stream) diff --git a/toolchain/check/context.h b/toolchain/check/context.h index 57094049e90a..db50476a47c5 100644 --- a/toolchain/check/context.h +++ b/toolchain/check/context.h @@ -5,12 +5,13 @@ #ifndef CARBON_TOOLCHAIN_CHECK_CONTEXT_H_ #define CARBON_TOOLCHAIN_CHECK_CONTEXT_H_ +#include + #include "common/map.h" -#include "llvm/ADT/FoldingSet.h" +#include "common/ostream.h" #include "llvm/ADT/SmallVector.h" #include "toolchain/check/decl_introducer_state.h" #include "toolchain/check/decl_name_stack.h" -#include "toolchain/check/diagnostic_helpers.h" #include "toolchain/check/full_pattern_stack.h" #include "toolchain/check/generic_region_stack.h" #include "toolchain/check/global_init.h" @@ -18,8 +19,8 @@ #include "toolchain/check/node_stack.h" #include "toolchain/check/param_and_arg_refs_stack.h" #include "toolchain/check/region_stack.h" -#include "toolchain/check/scope_index.h" #include "toolchain/check/scope_stack.h" +#include "toolchain/diagnostics/diagnostic_emitter.h" #include "toolchain/parse/node_ids.h" #include "toolchain/parse/tree.h" #include "toolchain/parse/tree_and_subtrees.h" @@ -47,16 +48,8 @@ namespace Carbon::Check { // (for example, shared with lowering). class Context { public: - using DiagnosticEmitter = Carbon::DiagnosticEmitter; - using DiagnosticBuilder = DiagnosticEmitter::DiagnosticBuilder; - - // A function that forms a diagnostic for some kind of problem. The - // DiagnosticBuilder is returned rather than emitted so that the caller can - // add contextual notes as appropriate. - using BuildDiagnosticFn = llvm::function_refDiagnosticBuilder>; - // Stores references for work. - explicit Context(DiagnosticEmitter* emitter, + explicit Context(DiagnosticEmitter* emitter, Parse::GetTreeAndSubtreesFn tree_and_subtrees_getter, SemIR::File* sem_ir, int imported_ir_count, int total_ir_count, llvm::raw_ostream* vlog_stream); @@ -75,7 +68,7 @@ class Context { return tokens().GetKind(parse_tree().node_token(node_id)); } - auto emitter() -> DiagnosticEmitter& { return *emitter_; } + auto emitter() -> DiagnosticEmitter& { return *emitter_; } auto parse_tree_and_subtrees() -> const Parse::TreeAndSubtrees& { return tree_and_subtrees_getter_(); @@ -273,7 +266,7 @@ class Context { private: // Handles diagnostics. - DiagnosticEmitter* emitter_; + DiagnosticEmitter* emitter_; // Returns a lazily constructed TreeAndSubtrees. Parse::GetTreeAndSubtreesFn tree_and_subtrees_getter_; diff --git a/toolchain/check/deduce.cpp b/toolchain/check/deduce.cpp index f1ac487b8677..98341f2b0fb1 100644 --- a/toolchain/check/deduce.cpp +++ b/toolchain/check/deduce.cpp @@ -256,7 +256,7 @@ class DeductionContext { } // namespace static auto NoteGenericHere(Context& context, SemIR::GenericId generic_id, - Context::DiagnosticBuilder& diag) -> void { + DiagnosticBuilder& diag) -> void { CARBON_DIAGNOSTIC(DeductionGenericHere, Note, "while deducing parameters of generic declared here"); diag.Note(context.generics().Get(generic_id).decl_id, DeductionGenericHere); diff --git a/toolchain/check/diagnostic_helpers.h b/toolchain/check/diagnostic_helpers.h index 0c1973d0d52f..db37acf162f5 100644 --- a/toolchain/check/diagnostic_helpers.h +++ b/toolchain/check/diagnostic_helpers.h @@ -44,6 +44,13 @@ class SemIRLoc { bool token_only_; }; +using DiagnosticBuilder = DiagnosticEmitter::DiagnosticBuilder; + +// A function that forms a diagnostic for some kind of problem. The +// DiagnosticBuilder is returned rather than emitted so that the caller +// can add contextual notes as appropriate. +using MakeDiagnosticBuilderFn = llvm::function_refDiagnosticBuilder>; + inline auto TokenOnly(SemIR::LocId loc_id) -> SemIRLoc { return SemIRLoc(loc_id, true); } diff --git a/toolchain/check/eval.cpp b/toolchain/check/eval.cpp index 1a97f526e6af..5747dcbb9e7f 100644 --- a/toolchain/check/eval.cpp +++ b/toolchain/check/eval.cpp @@ -180,7 +180,7 @@ class EvalContext { auto sem_ir() -> SemIR::File& { return context().sem_ir(); } - auto emitter() -> Context::DiagnosticEmitter& { return context().emitter(); } + auto emitter() -> DiagnosticEmitter& { return context().emitter(); } private: // The type-checking context in which we're performing evaluation. diff --git a/toolchain/check/impl.cpp b/toolchain/check/impl.cpp index 5cd024570f32..aec86c4058b9 100644 --- a/toolchain/check/impl.cpp +++ b/toolchain/check/impl.cpp @@ -25,8 +25,7 @@ namespace Carbon::Check { // Adds the location of the associated function to a diagnostic. -static auto NoteAssociatedFunction(Context& context, - Context::DiagnosticBuilder& builder, +static auto NoteAssociatedFunction(Context& context, DiagnosticBuilder& builder, SemIR::FunctionId function_id) -> void { CARBON_DIAGNOSTIC(AssociatedFunctionHere, Note, "associated function {0} declared here", SemIR::NameId); diff --git a/toolchain/check/member_access.cpp b/toolchain/check/member_access.cpp index d62925630086..fc1afe6f78ff 100644 --- a/toolchain/check/member_access.cpp +++ b/toolchain/check/member_access.cpp @@ -184,8 +184,7 @@ static auto AccessMemberOfImplWitness(Context& context, SemIR::LocId loc_id, static auto PerformImplLookup( Context& context, SemIR::LocId loc_id, SemIR::ConstantId type_const_id, SemIR::AssociatedEntityType assoc_type, SemIR::InstId member_id, - Context::BuildDiagnosticFn missing_impl_diagnoser = nullptr) - -> SemIR::InstId { + MakeDiagnosticBuilderFn missing_impl_diagnoser = nullptr) -> SemIR::InstId { auto interface_type = GetInterfaceFromFacetType(context, assoc_type.interface_type_id); if (!interface_type) { @@ -525,10 +524,11 @@ auto PerformMemberAccess(Context& context, SemIR::LocId loc_id, return member_id; } -auto PerformCompoundMemberAccess( - Context& context, SemIR::LocId loc_id, SemIR::InstId base_id, - SemIR::InstId member_expr_id, - Context::BuildDiagnosticFn missing_impl_diagnoser) -> SemIR::InstId { +auto PerformCompoundMemberAccess(Context& context, SemIR::LocId loc_id, + SemIR::InstId base_id, + SemIR::InstId member_expr_id, + MakeDiagnosticBuilderFn missing_impl_diagnoser) + -> SemIR::InstId { auto base_type_id = context.insts().Get(base_id).type_id(); auto base_type_const_id = context.types().GetConstantId(base_type_id); diff --git a/toolchain/check/member_access.h b/toolchain/check/member_access.h index 87862e1c48e9..7ab9a73d1346 100644 --- a/toolchain/check/member_access.h +++ b/toolchain/check/member_access.h @@ -23,8 +23,7 @@ auto PerformMemberAccess(Context& context, SemIR::LocId loc_id, auto PerformCompoundMemberAccess( Context& context, SemIR::LocId loc_id, SemIR::InstId base_id, SemIR::InstId member_expr_id, - Context::BuildDiagnosticFn missing_impl_diagnoser = nullptr) - -> SemIR::InstId; + MakeDiagnosticBuilderFn missing_impl_diagnoser = nullptr) -> SemIR::InstId; // Creates SemIR to perform a tuple index with base expression `tuple_inst_id` // and index expression `index_inst_id`. Returns the result of the access. diff --git a/toolchain/check/operator.cpp b/toolchain/check/operator.cpp index ab6690b83cbb..fb15f5f2eeb2 100644 --- a/toolchain/check/operator.cpp +++ b/toolchain/check/operator.cpp @@ -32,7 +32,7 @@ static auto GetOperatorOpFunction(Context& context, SemIR::LocId loc_id, auto BuildUnaryOperator(Context& context, SemIR::LocId loc_id, Operator op, SemIR::InstId operand_id, - Context::BuildDiagnosticFn missing_impl_diagnoser) + MakeDiagnosticBuilderFn missing_impl_diagnoser) -> SemIR::InstId { // Look up the operator function. auto op_fn = GetOperatorOpFunction(context, loc_id.ToImplicit(), op); @@ -50,7 +50,7 @@ auto BuildUnaryOperator(Context& context, SemIR::LocId loc_id, Operator op, auto BuildBinaryOperator(Context& context, SemIR::LocId loc_id, Operator op, SemIR::InstId lhs_id, SemIR::InstId rhs_id, - Context::BuildDiagnosticFn missing_impl_diagnoser) + MakeDiagnosticBuilderFn missing_impl_diagnoser) -> SemIR::InstId { // Look up the operator function. auto op_fn = GetOperatorOpFunction(context, loc_id.ToImplicit(), op); diff --git a/toolchain/check/operator.h b/toolchain/check/operator.h index a243e3bb14e7..5b3a7fb9aa5a 100644 --- a/toolchain/check/operator.h +++ b/toolchain/check/operator.h @@ -21,19 +21,19 @@ struct Operator { // `*operand` or `operand*`. If specified, `missing_impl_diagnoser` is used to // build a custom error diagnostic for the case where impl lookup for the // operator fails. -auto BuildUnaryOperator(Context& context, SemIR::LocId loc_id, Operator op, - SemIR::InstId operand_id, - Context::BuildDiagnosticFn missing_impl_diagnoser = - nullptr) -> SemIR::InstId; +auto BuildUnaryOperator( + Context& context, SemIR::LocId loc_id, Operator op, + SemIR::InstId operand_id, + MakeDiagnosticBuilderFn missing_impl_diagnoser = nullptr) -> SemIR::InstId; // Checks and builds SemIR for a binary operator expression. For example, // `lhs_id * rhs_id`. If specified, `missing_impl_diagnoser` is used to build a // custom error diagnostic for the case where impl lookup for the operator // fails. -auto BuildBinaryOperator(Context& context, SemIR::LocId loc_id, Operator op, - SemIR::InstId lhs_id, SemIR::InstId rhs_id, - Context::BuildDiagnosticFn missing_impl_diagnoser = - nullptr) -> SemIR::InstId; +auto BuildBinaryOperator( + Context& context, SemIR::LocId loc_id, Operator op, SemIR::InstId lhs_id, + SemIR::InstId rhs_id, + MakeDiagnosticBuilderFn missing_impl_diagnoser = nullptr) -> SemIR::InstId; } // namespace Carbon::Check diff --git a/toolchain/check/return.cpp b/toolchain/check/return.cpp index 2ab0d1de133e..f96e5a150f1c 100644 --- a/toolchain/check/return.cpp +++ b/toolchain/check/return.cpp @@ -39,7 +39,7 @@ static auto GetCurrentReturnedVar(Context& context) -> SemIR::InstId { } // Produces a note that the given function has no explicit return type. -static auto NoteNoReturnTypeProvided(Context::DiagnosticBuilder& diag, +static auto NoteNoReturnTypeProvided(DiagnosticBuilder& diag, const SemIR::Function& function) { CARBON_DIAGNOSTIC(ReturnTypeOmittedNote, Note, "there was no return type provided"); @@ -48,7 +48,7 @@ static auto NoteNoReturnTypeProvided(Context::DiagnosticBuilder& diag, // Produces a note describing the return type of the given function, which // must be a function whose definition is currently being checked. -static auto NoteReturnType(Context& context, Context::DiagnosticBuilder& diag, +static auto NoteReturnType(Context& context, DiagnosticBuilder& diag, const SemIR::Function& function) { auto out_param_pattern = context.insts().GetAs( function.return_slot_pattern_id); @@ -63,7 +63,7 @@ static auto NoteReturnType(Context& context, Context::DiagnosticBuilder& diag, } // Produces a note pointing at the currently in scope `returned var`. -static auto NoteReturnedVar(Context::DiagnosticBuilder& diag, +static auto NoteReturnedVar(DiagnosticBuilder& diag, SemIR::InstId returned_var_id) { CARBON_DIAGNOSTIC(ReturnedVarHere, Note, "`returned var` was declared here"); diag.Note(returned_var_id, ReturnedVarHere); diff --git a/toolchain/check/type_completion.cpp b/toolchain/check/type_completion.cpp index 4935907f7b9a..0cc7697cf76a 100644 --- a/toolchain/check/type_completion.cpp +++ b/toolchain/check/type_completion.cpp @@ -29,7 +29,7 @@ namespace { class TypeCompleter { public: TypeCompleter(Context& context, SemIRLoc loc, - Context::BuildDiagnosticFn diagnoser) + MakeDiagnosticBuilderFn diagnoser) : context_(context), loc_(loc), diagnoser_(diagnoser) {} // Attempts to complete the given type. Returns true if it is now complete, @@ -160,7 +160,7 @@ class TypeCompleter { Context& context_; llvm::SmallVector work_list_; SemIRLoc loc_; - Context::BuildDiagnosticFn diagnoser_; + MakeDiagnosticBuilderFn diagnoser_; }; } // namespace @@ -535,7 +535,7 @@ auto TypeCompleter::BuildInfo(SemIR::TypeId type_id, SemIR::Inst inst) const } auto TryToCompleteType(Context& context, SemIR::TypeId type_id, SemIRLoc loc, - Context::BuildDiagnosticFn diagnoser) -> bool { + MakeDiagnosticBuilderFn diagnoser) -> bool { return TypeCompleter(context, loc, diagnoser).Complete(type_id); } @@ -547,8 +547,8 @@ auto CompleteTypeOrCheckFail(Context& context, SemIR::TypeId type_id) -> void { } auto RequireCompleteType(Context& context, SemIR::TypeId type_id, - SemIR::LocId loc_id, - Context::BuildDiagnosticFn diagnoser) -> bool { + SemIR::LocId loc_id, MakeDiagnosticBuilderFn diagnoser) + -> bool { CARBON_CHECK(diagnoser); if (!TypeCompleter(context, loc_id, diagnoser).Complete(type_id)) { @@ -573,8 +573,8 @@ auto RequireCompleteType(Context& context, SemIR::TypeId type_id, // Adds a note to a diagnostic explaining that a class is abstract. static auto NoteAbstractClass(Context& context, SemIR::ClassId class_id, - bool direct_use, - Context::DiagnosticBuilder& builder) -> void { + bool direct_use, DiagnosticBuilder& builder) + -> void { const auto& class_info = context.classes().Get(class_id); CARBON_CHECK( class_info.inheritance_kind == SemIR::Class::InheritanceKind::Abstract, @@ -588,10 +588,8 @@ static auto NoteAbstractClass(Context& context, SemIR::ClassId class_id, } auto RequireConcreteType(Context& context, SemIR::TypeId type_id, - SemIR::LocId loc_id, - Context::BuildDiagnosticFn diagnoser, - Context::BuildDiagnosticFn abstract_diagnoser) - -> bool { + SemIR::LocId loc_id, MakeDiagnosticBuilderFn diagnoser, + MakeDiagnosticBuilderFn abstract_diagnoser) -> bool { // TODO: For symbolic types, should add a RequireConcreteType instruction, // like RequireCompleteType. CARBON_CHECK(abstract_diagnoser); @@ -623,7 +621,7 @@ auto RequireConcreteType(Context& context, SemIR::TypeId type_id, auto RequireCompleteFacetType(Context& context, SemIR::TypeId type_id, SemIR::LocId loc_id, const SemIR::FacetType& facet_type, - Context::BuildDiagnosticFn diagnoser) + MakeDiagnosticBuilderFn diagnoser) -> SemIR::CompleteFacetTypeId { if (!RequireCompleteType(context, type_id, loc_id, diagnoser)) { return SemIR::CompleteFacetTypeId::None; @@ -633,7 +631,7 @@ auto RequireCompleteFacetType(Context& context, SemIR::TypeId type_id, } auto AsCompleteType(Context& context, SemIR::TypeId type_id, - SemIR::LocId loc_id, Context::BuildDiagnosticFn diagnoser) + SemIR::LocId loc_id, MakeDiagnosticBuilderFn diagnoser) -> SemIR::TypeId { return RequireCompleteType(context, type_id, loc_id, diagnoser) ? type_id @@ -644,8 +642,8 @@ auto AsCompleteType(Context& context, SemIR::TypeId type_id, // incomplete or abstract type error and returns an error type. This is a // convenience wrapper around `RequireConcreteType`. auto AsConcreteType(Context& context, SemIR::TypeId type_id, - SemIR::LocId loc_id, Context::BuildDiagnosticFn diagnoser, - Context::BuildDiagnosticFn abstract_diagnoser) + SemIR::LocId loc_id, MakeDiagnosticBuilderFn diagnoser, + MakeDiagnosticBuilderFn abstract_diagnoser) -> SemIR::TypeId { return RequireConcreteType(context, type_id, loc_id, diagnoser, abstract_diagnoser) @@ -654,7 +652,7 @@ auto AsConcreteType(Context& context, SemIR::TypeId type_id, } auto NoteIncompleteClass(Context& context, SemIR::ClassId class_id, - Context::DiagnosticBuilder& builder) -> void { + 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()) { @@ -669,7 +667,7 @@ auto NoteIncompleteClass(Context& context, SemIR::ClassId class_id, } auto NoteUndefinedInterface(Context& context, SemIR::InterfaceId interface_id, - Context::DiagnosticBuilder& builder) -> void { + 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()) { diff --git a/toolchain/check/type_completion.h b/toolchain/check/type_completion.h index 3c743c054525..a169479e39bb 100644 --- a/toolchain/check/type_completion.h +++ b/toolchain/check/type_completion.h @@ -21,7 +21,7 @@ namespace Carbon::Check { // don't want to trigger a request for more monomorphization. // TODO: Remove the other call to this function. auto TryToCompleteType(Context& context, SemIR::TypeId type_id, SemIRLoc loc, - Context::BuildDiagnosticFn diagnoser = nullptr) -> bool; + MakeDiagnosticBuilderFn diagnoser = nullptr) -> bool; // Completes the type `type_id`. CHECK-fails if it can't be completed. auto CompleteTypeOrCheckFail(Context& context, SemIR::TypeId type_id) -> void; @@ -37,47 +37,46 @@ auto CompleteTypeOrCheckFail(Context& context, SemIR::TypeId type_id) -> void; // the completeness of the type will be enforced during monomorphization, and // `loc_id` is used as the location for a diagnostic produced at that time. auto RequireCompleteType(Context& context, SemIR::TypeId type_id, - SemIR::LocId loc_id, - Context::BuildDiagnosticFn diagnoser) -> bool; + SemIR::LocId loc_id, MakeDiagnosticBuilderFn diagnoser) + -> bool; // Like `RequireCompleteType`, but also require the type to not be an abstract // class type. If it is, `abstract_diagnoser` is used to diagnose the problem, // and this function returns false. auto RequireConcreteType(Context& context, SemIR::TypeId type_id, - SemIR::LocId loc_id, - Context::BuildDiagnosticFn diagnoser, - Context::BuildDiagnosticFn abstract_diagnoser) -> bool; + SemIR::LocId loc_id, MakeDiagnosticBuilderFn diagnoser, + MakeDiagnosticBuilderFn abstract_diagnoser) -> bool; // Like `RequireCompleteType`, but only for facet types. If it uses some // incomplete interface, diagnoses the problem and returns `None`. auto RequireCompleteFacetType(Context& context, SemIR::TypeId type_id, SemIR::LocId loc_id, const SemIR::FacetType& facet_type, - Context::BuildDiagnosticFn diagnoser) + MakeDiagnosticBuilderFn diagnoser) -> SemIR::CompleteFacetTypeId; // Returns the type `type_id` if it is a complete type, or produces an // incomplete type error and returns an error type. This is a convenience // wrapper around `RequireCompleteType`. auto AsCompleteType(Context& context, SemIR::TypeId type_id, - SemIR::LocId loc_id, Context::BuildDiagnosticFn diagnoser) + SemIR::LocId loc_id, MakeDiagnosticBuilderFn diagnoser) -> SemIR::TypeId; // Returns the type `type_id` if it is a concrete type, or produces an // incomplete or abstract type error and returns an error type. This is a // convenience wrapper around `RequireConcreteType`. auto AsConcreteType(Context& context, SemIR::TypeId type_id, - SemIR::LocId loc_id, Context::BuildDiagnosticFn diagnoser, - Context::BuildDiagnosticFn abstract_diagnoser) + SemIR::LocId loc_id, MakeDiagnosticBuilderFn diagnoser, + MakeDiagnosticBuilderFn 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; + 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; + DiagnosticBuilder& builder) -> void; } // namespace Carbon::Check