From efea072be340202cde763a3e40d1549a192f0ec7 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Mon, 15 Jul 2024 16:59:23 -0700 Subject: [PATCH] Compute specific constant values. (#4128) When forming a specific (previously called a generic instance), evaluate the eval block of the generic to determine the values of any constants used in that specific. The majority of the work here is updating eval.cpp so that it can use the results of prior evaluations in the same block when computing later values. Include the computed results in the formatted SemIR output. --------- Co-authored-by: Jon Ross-Perkins --- toolchain/check/eval.cpp | 465 ++++++++++++------ toolchain/check/eval.h | 10 +- toolchain/check/generic.cpp | 30 +- .../check/testdata/array/generic_empty.carbon | 5 + .../testdata/basics/no_prelude/raw_ir.carbon | 19 +- .../builtins/int/make_type_signed.carbon | 6 + .../builtins/int/make_type_unsigned.carbon | 6 + .../testdata/class/fail_generic_method.carbon | 20 +- .../check/testdata/class/generic/basic.carbon | 25 +- .../check/testdata/class/generic/call.carbon | 48 +- .../class/generic/fail_todo_use.carbon | 24 +- .../check/testdata/class/generic/field.carbon | 40 +- .../testdata/class/generic/import.carbon | 74 ++- .../class/generic/member_inline.carbon | 12 +- .../class/generic/member_out_of_line.carbon | 86 +++- .../testdata/class/generic/redeclare.carbon | 72 ++- .../check/testdata/class/generic/self.carbon | 26 +- .../testdata/class/generic_method.carbon | 17 +- .../check/testdata/eval/fail_symbolic.carbon | 5 + toolchain/check/testdata/eval/symbolic.carbon | 5 + .../testdata/function/builtin/method.carbon | 5 + .../no_prelude/call_from_operator.carbon | 5 + .../generic/fail_todo_param_in_type.carbon | 5 + .../fail_type_param_mismatch.carbon | 6 + .../no_prelude/indirect_generic_type.carbon | 7 + .../generic/no_prelude/type_param.carbon | 5 + .../no_prelude/type_param_scope.carbon | 5 + .../function/generic/redeclare.carbon | 48 ++ toolchain/check/testdata/impl/compound.carbon | 9 + .../check/testdata/impl/extend_impl.carbon | 4 + .../testdata/impl/fail_call_invalid.carbon | 5 + .../impl/fail_extend_impl_forall.carbon | 17 +- ..._extend_partially_defined_interface.carbon | 4 + .../testdata/impl/fail_impl_as_scope.carbon | 4 + .../impl/fail_impl_bad_assoc_fn.carbon | 18 + toolchain/check/testdata/impl/impl_as.carbon | 4 + .../check/testdata/impl/impl_forall.carbon | 8 + .../check/testdata/impl/lookup/alias.carbon | 4 + .../lookup/fail_alias_impl_not_found.carbon | 4 + .../lookup/fail_todo_undefined_impl.carbon | 4 + .../check/testdata/impl/lookup/import.carbon | 4 + .../impl/lookup/instance_method.carbon | 5 + .../impl/lookup/no_prelude/import.carbon | 4 + .../testdata/impl/no_prelude/basic.carbon | 4 + .../impl/no_prelude/import_self.carbon | 5 + .../impl/no_prelude/self_in_class.carbon | 5 + .../impl/no_prelude/self_in_signature.carbon | 14 + .../fail_todo_define_default_fn_inline.carbon | 8 + ..._todo_define_default_fn_out_of_line.carbon | 8 + .../no_prelude/as_type_of_type.carbon | 5 + .../interface/no_prelude/basic.carbon | 4 + .../interface/no_prelude/default_fn.carbon | 4 + .../fail_add_member_outside_definition.carbon | 12 + .../fail_generic_redeclaration.carbon | 24 +- .../no_prelude/fail_lookup_undefined.carbon | 8 + .../no_prelude/fail_member_lookup.carbon | 4 + .../no_prelude/fail_redeclare_member.carbon | 8 + .../no_prelude/fail_todo_facet_lookup.carbon | 14 + .../fail_todo_generic_default_fn.carbon | 32 +- .../no_prelude/fail_todo_modifiers.carbon | 8 + .../interface/no_prelude/generic.carbon | 79 ++- .../generic_binding_after_assoc_const.carbon | 10 + .../no_prelude/generic_import.carbon | 19 +- .../interface/no_prelude/import.carbon | 8 + .../testdata/interface/no_prelude/self.carbon | 5 + .../interface/todo_define_not_default.carbon | 8 + .../testdata/namespace/fail_params.carbon | 5 + .../no_prelude/fail_export_name_params.carbon | 20 +- .../testdata/return/fail_let_in_type.carbon | 5 + toolchain/check/testdata/struct/import.carbon | 42 +- toolchain/check/testdata/tuples/import.carbon | 42 +- toolchain/sem_ir/formatter.cpp | 72 ++- toolchain/sem_ir/generic.h | 40 +- 73 files changed, 1429 insertions(+), 272 deletions(-) diff --git a/toolchain/check/eval.cpp b/toolchain/check/eval.cpp index dd98b5252f9b..bac7023ee73f 100644 --- a/toolchain/check/eval.cpp +++ b/toolchain/check/eval.cpp @@ -17,6 +17,104 @@ namespace Carbon::Check { +namespace { +// Information about an eval block of a specific that we are currently building. +struct SpecificEvalInfo { + // The region within the specific whose eval block we are building. + SemIR::GenericInstIndex::Region region; + // The work-in-progress contents of the eval block. + llvm::ArrayRef values; +}; + +// Information about the context within which we are performing evaluation. +struct EvalContext { + // Given a constant value from the SemIR we're evaluating, finds the + // corresponding constant value to use in the context of this evaluation. + // This can be different if the original SemIR is for a generic and we are + // evaluating with specific arguments for the generic parameters. + auto GetInContext(SemIR::ConstantId const_id) -> SemIR::ConstantId { + if (!const_id.is_symbolic()) { + return const_id; + } + + // While resolving a specific, map from previous instructions in the eval + // block into their evaluated values. These values won't be present on the + // instance itself yet, so `GetConstantInInstance` won't be able to find + // them. + if (specific_eval_info) { + const auto& symbolic_info = + context.constant_values().GetSymbolicConstant(const_id); + if (symbolic_info.index.is_valid() && + symbolic_info.generic_id == + context.generic_instances().Get(specific_id).generic_id && + symbolic_info.index.region() == specific_eval_info->region) { + auto inst_id = specific_eval_info->values[symbolic_info.index.index()]; + CARBON_CHECK(inst_id.is_valid()) + << "Forward reference in eval block: index " + << symbolic_info.index.index() << " referenced before evaluation"; + return context.constant_values().Get(inst_id); + } + } + + // Map from a specific constant value to the canonical value. + return GetConstantInInstance(context.sem_ir(), specific_id, const_id); + } + + // Gets the constant value of the specified instruction in this context. + auto GetConstantValue(SemIR::InstId inst_id) -> SemIR::ConstantId { + return GetInContext(context.constant_values().Get(inst_id)); + } + + // Gets the constant value of the specified type in this context. + auto GetConstantValue(SemIR::TypeId type_id) -> SemIR::ConstantId { + return GetInContext(context.types().GetConstantId(type_id)); + } + + // Gets the instruction describing the constant value of the specified type in + // this context. + auto GetConstantValueAsInst(SemIR::TypeId id) -> SemIR::Inst { + return insts().Get( + context.constant_values().GetInstId(GetConstantValue(id))); + } + + auto ints() -> CanonicalValueStore& { return sem_ir().ints(); } + auto floats() -> FloatValueStore& { return sem_ir().floats(); } + auto bind_names() -> SemIR::BindNameStore& { return sem_ir().bind_names(); } + auto functions() -> const ValueStore& { + return sem_ir().functions(); + } + auto classes() -> const ValueStore& { + return sem_ir().classes(); + } + auto interfaces() -> const ValueStore& { + return sem_ir().interfaces(); + } + auto generic_instances() -> const SemIR::GenericInstanceStore& { + return sem_ir().generic_instances(); + } + auto types() -> const SemIR::TypeStore& { return sem_ir().types(); } + auto type_blocks() -> SemIR::BlockValueStore& { + return sem_ir().type_blocks(); + } + auto insts() -> const SemIR::InstStore& { return sem_ir().insts(); } + auto inst_blocks() -> SemIR::InstBlockStore& { + return sem_ir().inst_blocks(); + } + + auto sem_ir() -> SemIR::File& { return context.sem_ir(); } + + auto emitter() -> Context::DiagnosticEmitter& { return context.emitter(); } + + // The type-checking context in which we're performing evaluation. + Context& context; + // The specific that we are evaluating within. + SemIR::GenericInstanceId specific_id; + // If we are currently evaluating an eval block for `specific_id`, information + // about that evaluation. + std::optional specific_eval_info; +}; +} // namespace + namespace { // The evaluation phase for an expression, computed by evaluation. These are // ordered so that the phase of an expression is the numerically highest phase @@ -56,9 +154,10 @@ static auto GetPhase(SemIR::ConstantId constant_id) -> Phase { // type of a constant is effectively treated as an operand of that constant when // determining its phase. For example, an empty struct with a symbolic type is a // symbolic constant, not a template constant. -static auto GetTypePhase(Context& context, SemIR::TypeId type_id) -> Phase { +static auto GetTypePhase(EvalContext& eval_context, SemIR::TypeId type_id) + -> Phase { CARBON_CHECK(type_id.is_valid()); - return GetPhase(context.types().GetConstantId(type_id)); + return GetPhase(eval_context.GetConstantValue(type_id)); } // Returns the later of two phases. @@ -121,32 +220,33 @@ static auto MakeFloatResult(Context& context, SemIR::TypeId type_id, // Overloads are provided for different kinds of ID. // If the given instruction is constant, returns its constant value. -static auto GetConstantValue(Context& context, SemIR::InstId inst_id, +static auto GetConstantValue(EvalContext& eval_context, SemIR::InstId inst_id, Phase* phase) -> SemIR::InstId { - auto const_id = context.constant_values().Get(inst_id); + auto const_id = eval_context.GetConstantValue(inst_id); *phase = LatestPhase(*phase, GetPhase(const_id)); - return context.constant_values().GetInstId(const_id); + return eval_context.context.constant_values().GetInstId(const_id); } // A type is always constant, but we still need to extract its phase. -static auto GetConstantValue(Context& context, SemIR::TypeId type_id, +static auto GetConstantValue(EvalContext& eval_context, SemIR::TypeId type_id, Phase* phase) -> SemIR::TypeId { - auto const_id = context.types().GetConstantId(type_id); + auto const_id = eval_context.GetConstantValue(type_id); *phase = LatestPhase(*phase, GetPhase(const_id)); return type_id; } // If the given instruction block contains only constants, returns a // corresponding block of those values. -static auto GetConstantValue(Context& context, SemIR::InstBlockId inst_block_id, - Phase* phase) -> SemIR::InstBlockId { +static auto GetConstantValue(EvalContext& eval_context, + SemIR::InstBlockId inst_block_id, Phase* phase) + -> SemIR::InstBlockId { if (!inst_block_id.is_valid()) { return SemIR::InstBlockId::Invalid; } - auto insts = context.inst_blocks().Get(inst_block_id); + auto insts = eval_context.inst_blocks().Get(inst_block_id); llvm::SmallVector const_insts; for (auto inst_id : insts) { - auto const_inst_id = GetConstantValue(context, inst_id, phase); + auto const_inst_id = GetConstantValue(eval_context, inst_id, phase); if (!const_inst_id.is_valid()) { return SemIR::InstBlockId::Invalid; } @@ -162,34 +262,35 @@ static auto GetConstantValue(Context& context, SemIR::InstBlockId inst_block_id, } // TODO: If the new block is identical to the original block, and we know the // old ID was canonical, return the original ID. - return context.inst_blocks().AddCanonical(const_insts); + return eval_context.inst_blocks().AddCanonical(const_insts); } // The constant value of a type block is that type block, but we still need to // extract its phase. -static auto GetConstantValue(Context& context, SemIR::TypeBlockId type_block_id, - Phase* phase) -> SemIR::TypeBlockId { +static auto GetConstantValue(EvalContext& eval_context, + SemIR::TypeBlockId type_block_id, Phase* phase) + -> SemIR::TypeBlockId { if (!type_block_id.is_valid()) { return SemIR::TypeBlockId::Invalid; } - auto types = context.type_blocks().Get(type_block_id); + auto types = eval_context.type_blocks().Get(type_block_id); for (auto type_id : types) { - GetConstantValue(context, type_id, phase); + GetConstantValue(eval_context, type_id, phase); } return type_block_id; } // The constant value of a generic instance is the generic instance with the // corresponding constant values for its arguments. -static auto GetConstantValue(Context& context, +static auto GetConstantValue(EvalContext& eval_context, SemIR::GenericInstanceId instance_id, Phase* phase) -> SemIR::GenericInstanceId { if (!instance_id.is_valid()) { return SemIR::GenericInstanceId::Invalid; } - const auto& instance = context.generic_instances().Get(instance_id); - auto args_id = GetConstantValue(context, instance.args_id, phase); + const auto& instance = eval_context.generic_instances().Get(instance_id); + auto args_id = GetConstantValue(eval_context, instance.args_id, phase); if (!args_id.is_valid()) { return SemIR::GenericInstanceId::Invalid; } @@ -197,17 +298,18 @@ static auto GetConstantValue(Context& context, if (args_id == instance.args_id) { return instance_id; } - return MakeGenericInstance(context, instance.generic_id, args_id); + return MakeGenericInstance(eval_context.context, instance.generic_id, + args_id); } // Replaces the specified field of the given typed instruction with its constant // value, if it has constant phase. Returns true on success, false if the value // has runtime phase. template -static auto ReplaceFieldWithConstantValue(Context& context, InstT* inst, - FieldIdT InstT::*field, Phase* phase) - -> bool { - auto unwrapped = GetConstantValue(context, inst->*field, phase); +static auto ReplaceFieldWithConstantValue(EvalContext& eval_context, + InstT* inst, FieldIdT InstT::*field, + Phase* phase) -> bool { + auto unwrapped = GetConstantValue(eval_context, inst->*field, phase); if (!unwrapped.is_valid() && (inst->*field).is_valid()) { return false; } @@ -227,7 +329,7 @@ static auto ReplaceFieldWithConstantValue(Context& context, InstT* inst, // `ConstantId::Error` is returned. template static auto RebuildAndValidateIfFieldsAreConstant( - Context& context, SemIR::Inst inst, ValidateFn validate_fn, + EvalContext& eval_context, SemIR::Inst inst, ValidateFn validate_fn, EachFieldIdT InstT::*... each_field_id) -> SemIR::ConstantId { // Build a constant instruction by replacing each non-constant operand with // its constant value. @@ -235,38 +337,40 @@ static auto RebuildAndValidateIfFieldsAreConstant( // Some instruction kinds don't have a `type_id` field. For those that do, the // type contributes to the phase. Phase phase = inst.type_id().is_valid() - ? GetTypePhase(context, inst.type_id()) + ? GetTypePhase(eval_context, inst.type_id()) : Phase::Template; - if ((ReplaceFieldWithConstantValue(context, &typed_inst, each_field_id, + if ((ReplaceFieldWithConstantValue(eval_context, &typed_inst, each_field_id, &phase) && ...)) { if (phase == Phase::UnknownDueToError || !validate_fn(typed_inst)) { return SemIR::ConstantId::Error; } - return MakeConstantResult(context, typed_inst, phase); + return MakeConstantResult(eval_context.context, typed_inst, phase); } return MakeNonConstantResult(phase); } // Same as above but with no validation step. template -static auto RebuildIfFieldsAreConstant(Context& context, SemIR::Inst inst, +static auto RebuildIfFieldsAreConstant(EvalContext& eval_context, + SemIR::Inst inst, EachFieldIdT InstT::*... each_field_id) -> SemIR::ConstantId { return RebuildAndValidateIfFieldsAreConstant( - context, inst, [](...) { return true; }, each_field_id...); + eval_context, inst, [](...) { return true; }, each_field_id...); } // Rebuilds the given aggregate initialization instruction as a corresponding // constant aggregate value, if its elements are all constants. -static auto RebuildInitAsValue(Context& context, SemIR::Inst inst, +static auto RebuildInitAsValue(EvalContext& eval_context, SemIR::Inst inst, SemIR::InstKind value_kind) -> SemIR::ConstantId { auto init_inst = inst.As(); - Phase phase = GetTypePhase(context, init_inst.type_id); - auto elements_id = GetConstantValue(context, init_inst.elements_id, &phase); + Phase phase = GetTypePhase(eval_context, init_inst.type_id); + auto elements_id = + GetConstantValue(eval_context, init_inst.elements_id, &phase); return MakeConstantResult( - context, + eval_context.context, SemIR::AnyAggregateValue{.kind = value_kind, .type_id = init_inst.type_id, .elements_id = elements_id}, @@ -274,22 +378,23 @@ static auto RebuildInitAsValue(Context& context, SemIR::Inst inst, } // Performs an access into an aggregate, retrieving the specified element. -static auto PerformAggregateAccess(Context& context, SemIR::Inst inst) +static auto PerformAggregateAccess(EvalContext& eval_context, SemIR::Inst inst) -> SemIR::ConstantId { auto access_inst = inst.As(); Phase phase = Phase::Template; if (auto aggregate_id = - GetConstantValue(context, access_inst.aggregate_id, &phase); + GetConstantValue(eval_context, access_inst.aggregate_id, &phase); aggregate_id.is_valid()) { if (auto aggregate = - context.insts().TryGetAs(aggregate_id)) { - auto elements = context.inst_blocks().Get(aggregate->elements_id); + eval_context.insts().TryGetAs( + aggregate_id)) { + auto elements = eval_context.inst_blocks().Get(aggregate->elements_id); auto index = static_cast(access_inst.index.index); CARBON_CHECK(index < elements.size()) << "Access out of bounds."; // `Phase` is not used here. If this element is a template constant, then // so is the result of indexing, even if the aggregate also contains a // symbolic context. - return context.constant_values().Get(elements[index]); + return eval_context.GetConstantValue(elements[index]); } else { CARBON_CHECK(phase != Phase::Template) << "Failed to evaluate template constant " << inst; @@ -300,18 +405,18 @@ static auto PerformAggregateAccess(Context& context, SemIR::Inst inst) // Performs an index into a homogeneous aggregate, retrieving the specified // element. -static auto PerformAggregateIndex(Context& context, SemIR::Inst inst) +static auto PerformAggregateIndex(EvalContext& eval_context, SemIR::Inst inst) -> SemIR::ConstantId { auto index_inst = inst.As(); Phase phase = Phase::Template; auto aggregate_id = - GetConstantValue(context, index_inst.aggregate_id, &phase); - auto index_id = GetConstantValue(context, index_inst.index_id, &phase); + GetConstantValue(eval_context, index_inst.aggregate_id, &phase); + auto index_id = GetConstantValue(eval_context, index_inst.index_id, &phase); if (!index_id.is_valid()) { return MakeNonConstantResult(phase); } - auto index = context.insts().TryGetAs(index_id); + auto index = eval_context.insts().TryGetAs(index_id); if (!index) { CARBON_CHECK(phase != Phase::Template) << "Template constant integer should be a literal"; @@ -320,22 +425,24 @@ static auto PerformAggregateIndex(Context& context, SemIR::Inst inst) // Array indexing is invalid if the index is constant and out of range. auto aggregate_type_id = - context.insts().Get(index_inst.aggregate_id).type_id(); - const auto& index_val = context.ints().Get(index->int_id); + eval_context.insts().Get(index_inst.aggregate_id).type_id(); + const auto& index_val = eval_context.ints().Get(index->int_id); if (auto array_type = - context.types().TryGetAs(aggregate_type_id)) { - if (auto bound = - context.insts().TryGetAs(array_type->bound_id)) { + eval_context.types().TryGetAs(aggregate_type_id)) { + if (auto bound = eval_context.insts().TryGetAs( + array_type->bound_id)) { // This awkward call to `getZExtValue` is a workaround for APInt not // supporting comparisons between integers of different bit widths. if (index_val.getActiveBits() > 64 || - context.ints().Get(bound->int_id).ule(index_val.getZExtValue())) { + eval_context.ints() + .Get(bound->int_id) + .ule(index_val.getZExtValue())) { CARBON_DIAGNOSTIC(ArrayIndexOutOfBounds, Error, "Array index `{0}` is past the end of type `{1}`.", TypedInt, SemIR::TypeId); - context.emitter().Emit(index_inst.index_id, ArrayIndexOutOfBounds, - {.type = index->type_id, .value = index_val}, - aggregate_type_id); + eval_context.emitter().Emit( + index_inst.index_id, ArrayIndexOutOfBounds, + {.type = index->type_id, .value = index_val}, aggregate_type_id); return SemIR::ConstantId::Error; } } @@ -345,18 +452,18 @@ static auto PerformAggregateIndex(Context& context, SemIR::Inst inst) return MakeNonConstantResult(phase); } auto aggregate = - context.insts().TryGetAs(aggregate_id); + eval_context.insts().TryGetAs(aggregate_id); if (!aggregate) { CARBON_CHECK(phase != Phase::Template) << "Unexpected representation for template constant aggregate"; return MakeNonConstantResult(phase); } - auto elements = context.inst_blocks().Get(aggregate->elements_id); + auto elements = eval_context.inst_blocks().Get(aggregate->elements_id); // We checked this for the array case above. CARBON_CHECK(index_val.ult(elements.size())) << "Index out of bounds in tuple indexing"; - return context.constant_values().Get(elements[index_val.getZExtValue()]); + return eval_context.GetConstantValue(elements[index_val.getZExtValue()]); } // Enforces that an integer type has a valid bit width. @@ -867,7 +974,7 @@ static auto MakeConstantForBuiltinCall(Context& context, SemIRLoc loc, } // Makes a constant for a call instruction. -static auto MakeConstantForCall(Context& context, SemIRLoc loc, +static auto MakeConstantForCall(EvalContext& eval_context, SemIRLoc loc, SemIR::Call call) -> SemIR::ConstantId { Phase phase = Phase::Template; @@ -880,17 +987,17 @@ static auto MakeConstantForCall(Context& context, SemIRLoc loc, } // If the callee isn't constant, this is not a constant call. - if (!ReplaceFieldWithConstantValue(context, &call, &SemIR::Call::callee_id, - &phase)) { + if (!ReplaceFieldWithConstantValue(eval_context, &call, + &SemIR::Call::callee_id, &phase)) { return SemIR::ConstantId::NotConstant; } auto callee_function = - SemIR::GetCalleeFunction(context.sem_ir(), call.callee_id); + SemIR::GetCalleeFunction(eval_context.sem_ir(), call.callee_id); auto builtin_kind = SemIR::BuiltinFunctionKind::None; if (callee_function.function_id.is_valid()) { // Calls to builtins might be constant. - builtin_kind = context.functions() + builtin_kind = eval_context.functions() .Get(callee_function.function_id) .builtin_function_kind; if (builtin_kind == SemIR::BuiltinFunctionKind::None) { @@ -904,7 +1011,7 @@ static auto MakeConstantForCall(Context& context, SemIRLoc loc, } // If the arguments aren't constant, this is not a constant call. - if (!ReplaceFieldWithConstantValue(context, &call, &SemIR::Call::args_id, + if (!ReplaceFieldWithConstantValue(eval_context, &call, &SemIR::Call::args_id, &phase)) { return SemIR::ConstantId::NotConstant; } @@ -914,34 +1021,37 @@ static auto MakeConstantForCall(Context& context, SemIRLoc loc, // Handle calls to builtins. if (builtin_kind != SemIR::BuiltinFunctionKind::None) { - return MakeConstantForBuiltinCall(context, loc, call, builtin_kind, - context.inst_blocks().Get(call.args_id), - phase); + return MakeConstantForBuiltinCall( + eval_context.context, loc, call, builtin_kind, + eval_context.inst_blocks().Get(call.args_id), phase); } // Look at the type of the callee for special cases: calls to generic class // and generic interface types. - auto type_inst = - context.types().GetAsInst(context.insts().Get(call.callee_id).type_id()); + auto type_inst = eval_context.GetConstantValueAsInst( + eval_context.insts().Get(call.callee_id).type_id()); CARBON_KIND_SWITCH(type_inst) { case CARBON_KIND(SemIR::GenericClassType generic_class): { auto instance_id = MakeGenericInstance( - context, context.classes().Get(generic_class.class_id).generic_id, + eval_context.context, + eval_context.classes().Get(generic_class.class_id).generic_id, call.args_id); return MakeConstantResult( - context, + eval_context.context, SemIR::ClassType{.type_id = call.type_id, .class_id = generic_class.class_id, .instance_id = instance_id}, phase); } case CARBON_KIND(SemIR::GenericInterfaceType generic_interface): { - auto instance_id = MakeGenericInstance( - context, - context.interfaces().Get(generic_interface.interface_id).generic_id, - call.args_id); + auto instance_id = + MakeGenericInstance(eval_context.context, + eval_context.interfaces() + .Get(generic_interface.interface_id) + .generic_id, + call.args_id); return MakeConstantResult( - context, + eval_context.context, SemIR::InterfaceType{.type_id = call.type_id, .interface_id = generic_interface.interface_id, .instance_id = instance_id}, @@ -953,37 +1063,37 @@ static auto MakeConstantForCall(Context& context, SemIRLoc loc, } } -auto TryEvalInst(Context& context, SemIR::InstId inst_id, SemIR::Inst inst) - -> SemIR::ConstantId { +auto TryEvalInstInContext(EvalContext& eval_context, SemIR::InstId inst_id, + SemIR::Inst inst) -> SemIR::ConstantId { // TODO: Ensure we have test coverage for each of these cases that can result // in a constant, once those situations are all reachable. CARBON_KIND_SWITCH(inst) { // These cases are constants if their operands are. case SemIR::AddrOf::Kind: - return RebuildIfFieldsAreConstant(context, inst, + return RebuildIfFieldsAreConstant(eval_context, inst, &SemIR::AddrOf::lvalue_id); case CARBON_KIND(SemIR::ArrayType array_type): { return RebuildAndValidateIfFieldsAreConstant( - context, inst, + eval_context, inst, [&](SemIR::ArrayType result) { auto bound_id = array_type.bound_id; - auto int_bound = - context.insts().TryGetAs(result.bound_id); + auto int_bound = eval_context.insts().TryGetAs( + result.bound_id); if (!int_bound) { // TODO: Permit symbolic array bounds. This will require fixing // callers of `GetArrayBoundValue`. - context.TODO(bound_id, "symbolic array bound"); + eval_context.context.TODO(bound_id, "symbolic array bound"); return false; } // TODO: We should check that the size of the resulting array type // fits in 64 bits, not just that the bound does. Should we use a // 32-bit limit for 32-bit targets? - const auto& bound_val = context.ints().Get(int_bound->int_id); - if (context.types().IsSignedInt(int_bound->type_id) && + const auto& bound_val = eval_context.ints().Get(int_bound->int_id); + if (eval_context.types().IsSignedInt(int_bound->type_id) && bound_val.isNegative()) { CARBON_DIAGNOSTIC(ArrayBoundNegative, Error, "Array bound of {0} is negative.", TypedInt); - context.emitter().Emit( + eval_context.emitter().Emit( bound_id, ArrayBoundNegative, {.type = int_bound->type_id, .value = bound_val}); return false; @@ -991,7 +1101,7 @@ auto TryEvalInst(Context& context, SemIR::InstId inst_id, SemIR::Inst inst) if (bound_val.getActiveBits() > 64) { CARBON_DIAGNOSTIC(ArrayBoundTooLarge, Error, "Array bound of {0} is too large.", TypedInt); - context.emitter().Emit( + eval_context.emitter().Emit( bound_id, ArrayBoundTooLarge, {.type = int_bound->type_id, .value = bound_val}); return false; @@ -1002,72 +1112,74 @@ auto TryEvalInst(Context& context, SemIR::InstId inst_id, SemIR::Inst inst) } case SemIR::AssociatedEntityType::Kind: return RebuildIfFieldsAreConstant( - context, inst, &SemIR::AssociatedEntityType::entity_type_id); + eval_context, inst, &SemIR::AssociatedEntityType::entity_type_id); case SemIR::BoundMethod::Kind: - return RebuildIfFieldsAreConstant(context, inst, + return RebuildIfFieldsAreConstant(eval_context, inst, &SemIR::BoundMethod::object_id, &SemIR::BoundMethod::function_id); case SemIR::ClassType::Kind: - return RebuildIfFieldsAreConstant(context, inst, + return RebuildIfFieldsAreConstant(eval_context, inst, &SemIR::ClassType::instance_id); case SemIR::InterfaceType::Kind: - return RebuildIfFieldsAreConstant(context, inst, + return RebuildIfFieldsAreConstant(eval_context, inst, &SemIR::InterfaceType::instance_id); case SemIR::InterfaceWitness::Kind: - return RebuildIfFieldsAreConstant(context, inst, + return RebuildIfFieldsAreConstant(eval_context, inst, &SemIR::InterfaceWitness::elements_id); case CARBON_KIND(SemIR::IntType int_type): { return RebuildAndValidateIfFieldsAreConstant( - context, inst, + eval_context, inst, [&](SemIR::IntType result) { - return ValidateIntType(context, int_type.bit_width_id, result); + return ValidateIntType(eval_context.context, int_type.bit_width_id, + result); }, &SemIR::IntType::bit_width_id); } case SemIR::PointerType::Kind: - return RebuildIfFieldsAreConstant(context, inst, + return RebuildIfFieldsAreConstant(eval_context, inst, &SemIR::PointerType::pointee_id); case CARBON_KIND(SemIR::FloatType float_type): { return RebuildAndValidateIfFieldsAreConstant( - context, inst, + eval_context, inst, [&](SemIR::FloatType result) { - return ValidateFloatType(context, float_type.bit_width_id, result); + return ValidateFloatType(eval_context.context, + float_type.bit_width_id, result); }, &SemIR::FloatType::bit_width_id); } case SemIR::StructType::Kind: - return RebuildIfFieldsAreConstant(context, inst, + return RebuildIfFieldsAreConstant(eval_context, inst, &SemIR::StructType::fields_id); case SemIR::StructTypeField::Kind: - return RebuildIfFieldsAreConstant(context, inst, + return RebuildIfFieldsAreConstant(eval_context, inst, &SemIR::StructTypeField::field_type_id); case SemIR::StructValue::Kind: - return RebuildIfFieldsAreConstant(context, inst, + return RebuildIfFieldsAreConstant(eval_context, inst, &SemIR::StructValue::elements_id); case SemIR::TupleType::Kind: - return RebuildIfFieldsAreConstant(context, inst, + return RebuildIfFieldsAreConstant(eval_context, inst, &SemIR::TupleType::elements_id); case SemIR::TupleValue::Kind: - return RebuildIfFieldsAreConstant(context, inst, + return RebuildIfFieldsAreConstant(eval_context, inst, &SemIR::TupleValue::elements_id); case SemIR::UnboundElementType::Kind: return RebuildIfFieldsAreConstant( - context, inst, &SemIR::UnboundElementType::class_type_id, + eval_context, inst, &SemIR::UnboundElementType::class_type_id, &SemIR::UnboundElementType::element_type_id); // Initializers evaluate to a value of the object representation. case SemIR::ArrayInit::Kind: // TODO: Add an `ArrayValue` to represent a constant array object // representation instead of using a `TupleValue`. - return RebuildInitAsValue(context, inst, SemIR::TupleValue::Kind); + return RebuildInitAsValue(eval_context, inst, SemIR::TupleValue::Kind); case SemIR::ClassInit::Kind: // TODO: Add a `ClassValue` to represent a constant class object // representation instead of using a `StructValue`. - return RebuildInitAsValue(context, inst, SemIR::StructValue::Kind); + return RebuildInitAsValue(eval_context, inst, SemIR::StructValue::Kind); case SemIR::StructInit::Kind: - return RebuildInitAsValue(context, inst, SemIR::StructValue::Kind); + return RebuildInitAsValue(eval_context, inst, SemIR::StructValue::Kind); case SemIR::TupleInit::Kind: - return RebuildInitAsValue(context, inst, SemIR::TupleValue::Kind); + return RebuildInitAsValue(eval_context, inst, SemIR::TupleValue::Kind); case SemIR::AssociatedEntity::Kind: case SemIR::BuiltinInst::Kind: @@ -1075,29 +1187,29 @@ auto TryEvalInst(Context& context, SemIR::InstId inst_id, SemIR::Inst inst) case SemIR::GenericClassType::Kind: case SemIR::GenericInterfaceType::Kind: // Builtins are always template constants. - return MakeConstantResult(context, inst, Phase::Template); + return MakeConstantResult(eval_context.context, inst, Phase::Template); case CARBON_KIND(SemIR::FunctionDecl fn_decl): { return MakeConstantResult( - context, + eval_context.context, SemIR::StructValue{.type_id = fn_decl.type_id, .elements_id = SemIR::InstBlockId::Empty}, - GetTypePhase(context, fn_decl.type_id)); + GetTypePhase(eval_context, fn_decl.type_id)); } case CARBON_KIND(SemIR::ClassDecl class_decl): { // If the class has generic parameters, we don't produce a class type, but // a callable whose return value is a class type. - if (context.classes().Get(class_decl.class_id).is_generic()) { + if (eval_context.classes().Get(class_decl.class_id).is_generic()) { return MakeConstantResult( - context, + eval_context.context, SemIR::StructValue{.type_id = class_decl.type_id, .elements_id = SemIR::InstBlockId::Empty}, - GetTypePhase(context, class_decl.type_id)); + GetTypePhase(eval_context, class_decl.type_id)); } // A non-generic class declaration evaluates to the class type. return MakeConstantResult( - context, + eval_context.context, SemIR::ClassType{.type_id = SemIR::TypeId::TypeType, .class_id = class_decl.class_id, .instance_id = SemIR::GenericInstanceId::Invalid}, @@ -1106,16 +1218,18 @@ auto TryEvalInst(Context& context, SemIR::InstId inst_id, SemIR::Inst inst) case CARBON_KIND(SemIR::InterfaceDecl interface_decl): { // If the interface has generic parameters, we don't produce an interface // type, but a callable whose return value is an interface type. - if (context.interfaces().Get(interface_decl.interface_id).is_generic()) { + if (eval_context.interfaces() + .Get(interface_decl.interface_id) + .is_generic()) { return MakeConstantResult( - context, + eval_context.context, SemIR::StructValue{.type_id = interface_decl.type_id, .elements_id = SemIR::InstBlockId::Empty}, - GetTypePhase(context, interface_decl.type_id)); + GetTypePhase(eval_context, interface_decl.type_id)); } // A non-generic interface declaration evaluates to the interface type. return MakeConstantResult( - context, + eval_context.context, SemIR::InterfaceType{ .type_id = SemIR::TypeId::TypeType, .interface_id = interface_decl.interface_id, @@ -1124,9 +1238,9 @@ auto TryEvalInst(Context& context, SemIR::InstId inst_id, SemIR::Inst inst) } case CARBON_KIND(SemIR::SpecificConstant instance): { - // Pull the instance-specific constant value out of the generic instance. + // Pull the constant value out of the specific. return SemIR::GetConstantValueInInstance( - context.sem_ir(), instance.instance_id, instance.inst_id); + eval_context.sem_ir(), instance.instance_id, instance.inst_id); } // These cases are treated as being the unique canonical definition of the @@ -1147,20 +1261,20 @@ auto TryEvalInst(Context& context, SemIR::InstId inst_id, SemIR::Inst inst) // TODO: Convert literals into a canonical form. Currently we can form two // different `i32` constants with the same value if they are represented // by `APInt`s with different bit widths. - return MakeConstantResult(context, inst, Phase::Template); + return MakeConstantResult(eval_context.context, inst, Phase::Template); // The elements of a constant aggregate can be accessed. case SemIR::ClassElementAccess::Kind: case SemIR::InterfaceWitnessAccess::Kind: case SemIR::StructAccess::Kind: case SemIR::TupleAccess::Kind: - return PerformAggregateAccess(context, inst); + return PerformAggregateAccess(eval_context, inst); case SemIR::ArrayIndex::Kind: case SemIR::TupleIndex::Kind: - return PerformAggregateIndex(context, inst); + return PerformAggregateIndex(eval_context, inst); case CARBON_KIND(SemIR::Call call): { - return MakeConstantForCall(context, inst_id, call); + return MakeConstantForCall(eval_context, inst_id, call); } // TODO: These need special handling. @@ -1173,58 +1287,73 @@ auto TryEvalInst(Context& context, SemIR::InstId inst_id, SemIR::Inst inst) break; case CARBON_KIND(SemIR::BindSymbolicName bind): { + const auto& bind_name = eval_context.bind_names().Get(bind.bind_name_id); + + // If we know which instance we're evaluating within and this is an + // argument of that instance, its constant value is the corresponding + // argument value. + if (bind_name.bind_index.is_valid() && + eval_context.specific_id.is_valid()) { + const auto& specific = + eval_context.generic_instances().Get(eval_context.specific_id); + auto args = eval_context.inst_blocks().Get(specific.args_id); + CARBON_CHECK(static_cast(bind_name.bind_index.index) < + args.size()) + << "Use of binding " << bind_name.bind_index + << " with no corresponding value."; + return eval_context.context.constant_values().Get( + args[bind_name.bind_index.index]); + } + // The constant form of a symbolic binding is an idealized form of the // original, with no equivalent value. - bind.bind_name_id = context.bind_names().MakeCanonical(bind.bind_name_id); + bind.bind_name_id = + eval_context.bind_names().MakeCanonical(bind.bind_name_id); bind.value_id = SemIR::InstId::Invalid; - return MakeConstantResult(context, bind, Phase::Symbolic); + return MakeConstantResult(eval_context.context, bind, Phase::Symbolic); } // These semantic wrappers don't change the constant value. case CARBON_KIND(SemIR::AsCompatible inst): { - return context.constant_values().Get(inst.source_id); + return eval_context.GetConstantValue(inst.source_id); } case CARBON_KIND(SemIR::BindAlias typed_inst): { - return context.constant_values().Get(typed_inst.value_id); + return eval_context.GetConstantValue(typed_inst.value_id); } case CARBON_KIND(SemIR::ExportDecl typed_inst): { - return context.constant_values().Get(typed_inst.value_id); + return eval_context.GetConstantValue(typed_inst.value_id); } case CARBON_KIND(SemIR::NameRef typed_inst): { - // Map from an instance-specific constant value to the canonical value. - // TODO: Remove this once we properly model instructions with - // instance-dependent constant values. - return GetConstantValueInInstance(context.sem_ir(), - SemIR::GenericInstanceId::Invalid, - typed_inst.value_id); + return eval_context.GetConstantValue(typed_inst.value_id); } case CARBON_KIND(SemIR::Converted typed_inst): { - return context.constant_values().Get(typed_inst.result_id); + return eval_context.GetConstantValue(typed_inst.result_id); } case CARBON_KIND(SemIR::InitializeFrom typed_inst): { - return context.constant_values().Get(typed_inst.src_id); + return eval_context.GetConstantValue(typed_inst.src_id); } case CARBON_KIND(SemIR::SpliceBlock typed_inst): { - return context.constant_values().Get(typed_inst.result_id); + return eval_context.GetConstantValue(typed_inst.result_id); } case CARBON_KIND(SemIR::ValueOfInitializer typed_inst): { - return context.constant_values().Get(typed_inst.init_id); + return eval_context.GetConstantValue(typed_inst.init_id); } case CARBON_KIND(SemIR::FacetTypeAccess typed_inst): { // TODO: Once we start tracking the witness in the facet value, remove it // here. For now, we model a facet value as just a type. - return context.constant_values().Get(typed_inst.facet_id); + return eval_context.GetConstantValue(typed_inst.facet_id); } // `not true` -> `false`, `not false` -> `true`. // All other uses of unary `not` are non-constant. case CARBON_KIND(SemIR::UnaryOperatorNot typed_inst): { - auto const_id = context.constant_values().Get(typed_inst.operand_id); + auto const_id = eval_context.GetConstantValue(typed_inst.operand_id); auto phase = GetPhase(const_id); if (phase == Phase::Template) { - auto value = context.insts().GetAs( - context.constant_values().GetInstId(const_id)); - return MakeBoolResult(context, value.type_id, !value.value.ToBool()); + auto value = eval_context.insts().GetAs( + eval_context.context.constant_values().GetInstId(const_id)); + return MakeBoolResult(eval_context.context, value.type_id, + !value.value.ToBool()); } if (phase == Phase::UnknownDueToError) { return SemIR::ConstantId::Error; @@ -1235,15 +1364,15 @@ auto TryEvalInst(Context& context, SemIR::InstId inst_id, SemIR::Inst inst) // `const (const T)` evaluates to `const T`. Otherwise, `const T` evaluates // to itself. case CARBON_KIND(SemIR::ConstType typed_inst): { - auto inner_id = context.constant_values().Get( - context.types().GetInstId(typed_inst.inner_id)); + auto inner_id = eval_context.GetConstantValue( + eval_context.types().GetInstId(typed_inst.inner_id)); if (inner_id.is_constant() && - context.insts() - .Get(context.constant_values().GetInstId(inner_id)) + eval_context.insts() + .Get(eval_context.context.constant_values().GetInstId(inner_id)) .Is()) { return inner_id; } - return MakeConstantResult(context, inst, GetPhase(inner_id)); + return MakeConstantResult(eval_context.context, inst, GetPhase(inner_id)); } // These cases are either not expressions or not constant. @@ -1272,4 +1401,48 @@ auto TryEvalInst(Context& context, SemIR::InstId inst_id, SemIR::Inst inst) return SemIR::ConstantId::NotConstant; } +auto TryEvalInst(Context& context, SemIR::InstId inst_id, SemIR::Inst inst) + -> SemIR::ConstantId { + EvalContext eval_context = { + .context = context, + .specific_id = SemIR::GenericInstanceId::Invalid, + .specific_eval_info = std::nullopt, + }; + return TryEvalInstInContext(eval_context, inst_id, inst); +} + +auto TryEvalBlockForSpecific(Context& context, + SemIR::GenericInstanceId specific_id, + SemIR::GenericInstIndex::Region region) + -> SemIR::InstBlockId { + auto generic_id = context.generic_instances().Get(specific_id).generic_id; + auto eval_block_id = context.generics().Get(generic_id).GetEvalBlock(region); + auto eval_block = context.inst_blocks().Get(eval_block_id); + + llvm::SmallVector result; + result.resize(eval_block.size(), SemIR::InstId::Invalid); + + EvalContext eval_context = { + .context = context, + .specific_id = specific_id, + .specific_eval_info = + SpecificEvalInfo{ + .region = region, + .values = result, + }, + }; + + for (auto [i, inst_id] : llvm::enumerate(eval_block)) { + auto const_id = TryEvalInstInContext(eval_context, inst_id, + context.insts().Get(inst_id)); + result[i] = context.constant_values().GetInstId(const_id); + + // TODO: If this becomes possible through monomorphization failure, produce + // a diagnostic and put `SemIR::InstId::BuiltinError` in the table entry. + CARBON_CHECK(result[i].is_valid()); + } + + return context.inst_blocks().Add(result); +} + } // namespace Carbon::Check diff --git a/toolchain/check/eval.h b/toolchain/check/eval.h index 6152fcffdbe3..668b33207906 100644 --- a/toolchain/check/eval.h +++ b/toolchain/check/eval.h @@ -14,11 +14,17 @@ namespace Carbon::Check { // Determines the phase of the instruction `inst`, and returns its constant // value if it has constant phase. If it has runtime phase, returns // `SemIR::ConstantId::NotConstant`. -// -// TODO: Support symbolic phase. auto TryEvalInst(Context& context, SemIR::InstId inst_id, SemIR::Inst inst) -> SemIR::ConstantId; +// Evaluates the eval block for a region of a specific. Produces a block +// containing the evaluated constant values of the instructions in the eval +// block. +auto TryEvalBlockForSpecific(Context& context, + SemIR::GenericInstanceId specific_id, + SemIR::GenericInstIndex::Region region) + -> SemIR::InstBlockId; + } // namespace Carbon::Check #endif // CARBON_TOOLCHAIN_CHECK_EVAL_H_ diff --git a/toolchain/check/generic.cpp b/toolchain/check/generic.cpp index 1404a3c2ef29..06f5af48a956 100644 --- a/toolchain/check/generic.cpp +++ b/toolchain/check/generic.cpp @@ -5,6 +5,7 @@ #include "toolchain/check/generic.h" #include "common/map.h" +#include "toolchain/check/eval.h" #include "toolchain/check/generic_region_stack.h" #include "toolchain/check/subst.h" #include "toolchain/sem_ir/ids.h" @@ -130,8 +131,6 @@ static auto MakeGenericEvalBlock(Context& context, SemIR::GenericId generic_id, Map constants_in_generic; // TODO: For the definition region, populate constants from the declaration. - // TODO: Add `BindSymbolicName` instructions for enclosing generics to the - // map. // The work done in this loop might invalidate iterators into the generic // region stack, but shouldn't add new dependent instructions to the current @@ -194,6 +193,10 @@ auto FinishGenericDecl(Context& context, SemIR::InstId decl_id) return SemIR::GenericId::Invalid; } + // Build the new Generic object. Note that we intentionally do not hold a + // persistent reference to it throughout this function, because the `generics` + // collection can have items added to it by import resolution while we are + // building this generic. auto bindings_id = context.inst_blocks().Add(all_bindings); auto generic_id = context.generics().Add( SemIR::Generic{.decl_id = decl_id, @@ -203,12 +206,10 @@ auto FinishGenericDecl(Context& context, SemIR::InstId decl_id) auto decl_block_id = MakeGenericEvalBlock( context, generic_id, SemIR::GenericInstIndex::Region::Declaration); context.generic_region_stack().Pop(); + context.generics().Get(generic_id).decl_block_id = decl_block_id; auto self_instance_id = MakeGenericSelfInstance(context, generic_id); - - auto& generic_info = context.generics().Get(generic_id); - generic_info.decl_block_id = decl_block_id; - generic_info.self_instance_id = self_instance_id; + context.generics().Get(generic_id).self_instance_id = self_instance_id; return generic_id; } @@ -238,7 +239,22 @@ auto MakeGenericInstance(Context& context, SemIR::GenericId generic_id, SemIR::InstBlockId args_id) -> SemIR::GenericInstanceId { auto instance_id = context.generic_instances().GetOrAdd(generic_id, args_id); - // TODO: Perform substitution into the generic declaration if needed. + + // TODO: Remove this once we import generics properly. + if (!generic_id.is_valid()) { + return instance_id; + } + + // If this is the first time we've formed this instance, evaluate its decl + // block to form information about the instance. + if (!context.generic_instances().Get(instance_id).decl_block_id.is_valid()) { + auto decl_block_id = TryEvalBlockForSpecific( + context, instance_id, SemIR::GenericInstIndex::Region::Declaration); + // Note that TryEvalBlockForSpecific may reallocate the list of generic + // instances, so re-lookup the instance here. + context.generic_instances().Get(instance_id).decl_block_id = decl_block_id; + } + return instance_id; } diff --git a/toolchain/check/testdata/array/generic_empty.carbon b/toolchain/check/testdata/array/generic_empty.carbon index 8dc53cd8be6a..38d6141de068 100644 --- a/toolchain/check/testdata/array/generic_empty.carbon +++ b/toolchain/check/testdata/array/generic_empty.carbon @@ -54,3 +54,8 @@ fn G(T:! type) { // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific file.%G.decl(constants.%T) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: @G.%T => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/basics/no_prelude/raw_ir.carbon b/toolchain/check/testdata/basics/no_prelude/raw_ir.carbon index d620a6ae3cf6..b1d00955cb3f 100644 --- a/toolchain/check/testdata/basics/no_prelude/raw_ir.carbon +++ b/toolchain/check/testdata/basics/no_prelude/raw_ir.carbon @@ -28,7 +28,7 @@ fn Foo[T:! type](n: T) -> (T, ()) { // CHECK:STDOUT: bind_name0: {name: name1, parent_scope: name_scope, index: comp_time_bind0} // CHECK:STDOUT: bind_name1: {name: name2, parent_scope: name_scope, index: comp_time_bind} // CHECK:STDOUT: functions: -// CHECK:STDOUT: function0: {name: name0, parent_scope: name_scope0, param_refs: block5, return_storage: inst+15, return_slot: present, body: [block11]} +// CHECK:STDOUT: function0: {name: name0, parent_scope: name_scope0, param_refs: block5, return_storage: inst+15, return_slot: present, body: [block12]} // CHECK:STDOUT: classes: {} // CHECK:STDOUT: generics: // CHECK:STDOUT: generic0: {decl: inst+16, bindings: block8} @@ -75,14 +75,14 @@ fn Foo[T:! type](n: T) -> (T, ()) { // CHECK:STDOUT: 'inst+19': {kind: PointerType, arg0: type4, type: typeTypeType} // CHECK:STDOUT: 'inst+20': {kind: NameRef, arg0: name2, arg1: inst+6, type: type1} // CHECK:STDOUT: 'inst+21': {kind: TupleLiteral, arg0: empty, type: type2} -// CHECK:STDOUT: 'inst+22': {kind: TupleLiteral, arg0: block12, type: type4} +// CHECK:STDOUT: 'inst+22': {kind: TupleLiteral, arg0: block13, type: type4} // CHECK:STDOUT: 'inst+23': {kind: TupleAccess, arg0: inst+15, arg1: element0, type: type1} // CHECK:STDOUT: 'inst+24': {kind: InitializeFrom, arg0: inst+20, arg1: inst+23, type: type1} // CHECK:STDOUT: 'inst+25': {kind: TupleAccess, arg0: inst+15, arg1: element1, type: type2} // CHECK:STDOUT: 'inst+26': {kind: TupleInit, arg0: empty, arg1: inst+25, type: type2} -// CHECK:STDOUT: 'inst+27': {kind: TupleValue, arg0: block14, type: type2} +// CHECK:STDOUT: 'inst+27': {kind: TupleValue, arg0: block15, type: type2} // CHECK:STDOUT: 'inst+28': {kind: Converted, arg0: inst+21, arg1: inst+26, type: type2} -// CHECK:STDOUT: 'inst+29': {kind: TupleInit, arg0: block13, arg1: inst+15, type: type4} +// CHECK:STDOUT: 'inst+29': {kind: TupleInit, arg0: block14, arg1: inst+15, type: type4} // CHECK:STDOUT: 'inst+30': {kind: Converted, arg0: inst+22, arg1: inst+29, type: type4} // CHECK:STDOUT: 'inst+31': {kind: ReturnExpr, arg0: inst+30, arg1: inst+15} // CHECK:STDOUT: constant_values: @@ -136,6 +136,9 @@ fn Foo[T:! type](n: T) -> (T, ()) { // CHECK:STDOUT: block10: // CHECK:STDOUT: 0: inst+3 // CHECK:STDOUT: block11: +// CHECK:STDOUT: 0: inst+3 +// CHECK:STDOUT: 1: inst+13 +// CHECK:STDOUT: block12: // CHECK:STDOUT: 0: inst+20 // CHECK:STDOUT: 1: inst+21 // CHECK:STDOUT: 2: inst+22 @@ -147,14 +150,14 @@ fn Foo[T:! type](n: T) -> (T, ()) { // CHECK:STDOUT: 8: inst+29 // CHECK:STDOUT: 9: inst+30 // CHECK:STDOUT: 10: inst+31 -// CHECK:STDOUT: block12: +// CHECK:STDOUT: block13: // CHECK:STDOUT: 0: inst+20 // CHECK:STDOUT: 1: inst+21 -// CHECK:STDOUT: block13: +// CHECK:STDOUT: block14: // CHECK:STDOUT: 0: inst+24 // CHECK:STDOUT: 1: inst+28 -// CHECK:STDOUT: block14: {} -// CHECK:STDOUT: block15: +// CHECK:STDOUT: block15: {} +// CHECK:STDOUT: block16: // CHECK:STDOUT: 0: inst+0 // CHECK:STDOUT: 1: inst+16 // CHECK:STDOUT: ... diff --git a/toolchain/check/testdata/builtins/int/make_type_signed.carbon b/toolchain/check/testdata/builtins/int/make_type_signed.carbon index 6b86137c0f54..8d1e64844382 100644 --- a/toolchain/check/testdata/builtins/int/make_type_signed.carbon +++ b/toolchain/check/testdata/builtins/int/make_type_signed.carbon @@ -217,6 +217,12 @@ var m: Int(1000000000); // CHECK:STDOUT: return %x.ref // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific file.%Symbolic.decl(constants.%N) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: @Symbolic.%N => constants.%N +// CHECK:STDOUT: file.%int.make_type_signed.loc14_28 => constants.%.6 +// CHECK:STDOUT: } +// CHECK:STDOUT: // CHECK:STDOUT: --- fail_zero_size.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { diff --git a/toolchain/check/testdata/builtins/int/make_type_unsigned.carbon b/toolchain/check/testdata/builtins/int/make_type_unsigned.carbon index 1779bda7b027..8896cedf2624 100644 --- a/toolchain/check/testdata/builtins/int/make_type_unsigned.carbon +++ b/toolchain/check/testdata/builtins/int/make_type_unsigned.carbon @@ -217,6 +217,12 @@ var m: UInt(1000000000); // CHECK:STDOUT: return %x.ref // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific file.%Symbolic.decl(constants.%N) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: @Symbolic.%N => constants.%N +// CHECK:STDOUT: file.%int.make_type_unsigned.loc14_29 => constants.%.6 +// CHECK:STDOUT: } +// CHECK:STDOUT: // CHECK:STDOUT: --- fail_zero_size.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { diff --git a/toolchain/check/testdata/class/fail_generic_method.carbon b/toolchain/check/testdata/class/fail_generic_method.carbon index ab0686f9e4a4..e90960d29c28 100644 --- a/toolchain/check/testdata/class/fail_generic_method.carbon +++ b/toolchain/check/testdata/class/fail_generic_method.carbon @@ -38,7 +38,7 @@ fn Class(N:! i32).F[self: Self](n: T) {} // CHECK:STDOUT: %Class.type: type = generic_class_type @Class [template] // CHECK:STDOUT: %.1: type = tuple_type () [template] // CHECK:STDOUT: %Class.1: %Class.type = struct_value () [template] -// CHECK:STDOUT: %Class.2: type = class_type @Class, (%T) [symbolic] +// CHECK:STDOUT: %Class.2: type = class_type @Class, file.%Class.decl(%T) [symbolic] // CHECK:STDOUT: %.2: type = unbound_element_type %Class.2, %T [symbolic] // CHECK:STDOUT: %F.type: type = fn_type @F [template] // CHECK:STDOUT: %F: %F.type = struct_value () [template] @@ -85,7 +85,7 @@ fn Class(N:! i32).F[self: Self](n: T) {} // CHECK:STDOUT: %T.ref.loc12: type = name_ref T, file.%T.loc11_13.2 [symbolic = constants.%T] // CHECK:STDOUT: %.loc12: %.2 = field_decl a, element0 [template] // CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [template = constants.%F] { -// CHECK:STDOUT: %.loc13: type = specific_constant constants.%Class.2, (constants.%T) [symbolic = %.loc13 (constants.%Class.2)] +// CHECK:STDOUT: %.loc13: type = specific_constant constants.%Class.2, file.%Class.decl(constants.%T) [symbolic = %.loc13 (constants.%Class.2)] // CHECK:STDOUT: %Self.ref: type = name_ref Self, %.loc13 [symbolic = %.loc13 (constants.%Class.2)] // CHECK:STDOUT: %self.loc13_8.1: @Class.%.loc13 (%Class.2) = param self // CHECK:STDOUT: %self.loc13_8.2: @Class.%.loc13 (%Class.2) = bind_name self, %self.loc13_8.1 @@ -111,3 +111,19 @@ fn Class(N:! i32).F[self: Self](n: T) {} // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific file.%Class.decl(constants.%T) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: file.%T.loc11_13.2 => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @Class.%F.decl(constants.%T) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: @Class.%.loc13 => constants.%Class.2 +// CHECK:STDOUT: @Class.%T.ref.loc13 => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific file.%.decl(constants.%N) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: file.%N.loc32_10.2 => constants.%N +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/class/generic/basic.carbon b/toolchain/check/testdata/class/generic/basic.carbon index df253041af6a..037aece1e026 100644 --- a/toolchain/check/testdata/class/generic/basic.carbon +++ b/toolchain/check/testdata/class/generic/basic.carbon @@ -29,7 +29,7 @@ class Class(T:! type) { // CHECK:STDOUT: %Class.type: type = generic_class_type @Class [template] // CHECK:STDOUT: %.1: type = tuple_type () [template] // CHECK:STDOUT: %Class.1: %Class.type = struct_value () [template] -// CHECK:STDOUT: %Class.2: type = class_type @Class, (%T) [symbolic] +// CHECK:STDOUT: %Class.2: type = class_type @Class, file.%Class.decl(%T) [symbolic] // CHECK:STDOUT: %.2: type = ptr_type %Class.2 [symbolic] // CHECK:STDOUT: %.3: type = ptr_type %T [symbolic] // CHECK:STDOUT: %GetAddr.type: type = fn_type @GetAddr [template] @@ -57,7 +57,7 @@ class Class(T:! type) { // CHECK:STDOUT: class @Class // CHECK:STDOUT: generic [file.%T.loc11_13.2: type] { // CHECK:STDOUT: %GetAddr.decl: %GetAddr.type = fn_decl @GetAddr [template = constants.%GetAddr] { -// CHECK:STDOUT: %.loc12_25: type = specific_constant constants.%Class.2, (constants.%T) [symbolic = %.loc12_25 (constants.%Class.2)] +// CHECK:STDOUT: %.loc12_25: type = specific_constant constants.%Class.2, file.%Class.decl(constants.%T) [symbolic = %.loc12_25 (constants.%Class.2)] // CHECK:STDOUT: %Self.ref.loc12: type = name_ref Self, %.loc12_25 [symbolic = %.loc12_25 (constants.%Class.2)] // CHECK:STDOUT: %.loc12_29: type = ptr_type %Class.2 [symbolic = %.loc12_29 (constants.%.2)] // CHECK:STDOUT: %self.loc12_19.1: @Class.%.loc12_29 (%.2) = param self @@ -68,7 +68,7 @@ class Class(T:! type) { // CHECK:STDOUT: %return.var.loc12: ref %.3 = var // CHECK:STDOUT: } // CHECK:STDOUT: %GetValue.decl: %GetValue.type = fn_decl @GetValue [template = constants.%GetValue] { -// CHECK:STDOUT: %.loc17: type = specific_constant constants.%Class.2, (constants.%T) [symbolic = %.loc17 (constants.%Class.2)] +// CHECK:STDOUT: %.loc17: type = specific_constant constants.%Class.2, file.%Class.decl(constants.%T) [symbolic = %.loc17 (constants.%Class.2)] // CHECK:STDOUT: %Self.ref.loc17: type = name_ref Self, %.loc17 [symbolic = %.loc17 (constants.%Class.2)] // CHECK:STDOUT: %self.loc17_15.1: @Class.%.loc17 (%Class.2) = param self // CHECK:STDOUT: %self.loc17_15.2: @Class.%.loc17 (%Class.2) = bind_name self, %self.loc17_15.1 @@ -106,3 +106,22 @@ class Class(T:! type) { // CHECK:STDOUT: return %.loc18_16.2 // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific file.%Class.decl(constants.%T) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: file.%T.loc11_13.2 => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @Class.%GetAddr.decl(constants.%T) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: @Class.%.loc12_25 => constants.%Class.2 +// CHECK:STDOUT: @Class.%.loc12_29 => constants.%.2 +// CHECK:STDOUT: @Class.%T.ref.loc12 => constants.%T +// CHECK:STDOUT: @Class.%.loc12_38 => constants.%.3 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @Class.%GetValue.decl(constants.%T) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: @Class.%.loc17 => constants.%Class.2 +// CHECK:STDOUT: @Class.%T.ref.loc17 => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/class/generic/call.carbon b/toolchain/check/testdata/class/generic/call.carbon index f05eacabb732..4c742d77377f 100644 --- a/toolchain/check/testdata/class/generic/call.carbon +++ b/toolchain/check/testdata/class/generic/call.carbon @@ -73,14 +73,14 @@ var a: Class(5, i32*); // CHECK:STDOUT: %N: i32 = bind_symbolic_name N 1 [symbolic] // CHECK:STDOUT: %Class.type: type = generic_class_type @Class [template] // CHECK:STDOUT: %Class.1: %Class.type = struct_value () [template] -// CHECK:STDOUT: %Class.2: type = class_type @Class, (%T, %N) [symbolic] +// CHECK:STDOUT: %Class.2: type = class_type @Class, file.%Class.decl(%T, %N) [symbolic] // CHECK:STDOUT: %.2: type = struct_type {} [template] // CHECK:STDOUT: %.3: type = ptr_type i32 [template] // CHECK:STDOUT: %.4: i32 = int_literal 5 [template] -// CHECK:STDOUT: %Class.3: type = class_type @Class, (%.3, %.4) [template] +// CHECK:STDOUT: %Class.3: type = class_type @Class, file.%Class.decl(%.3, %.4) [template] // CHECK:STDOUT: %.5: type = ptr_type %.2 [template] // CHECK:STDOUT: %.6: i32 = int_literal 0 [template] -// CHECK:STDOUT: %Class.4: type = class_type @Class, (%.1, %.6) [template] +// CHECK:STDOUT: %Class.4: type = class_type @Class, file.%Class.decl(%.1, %.6) [template] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { @@ -136,6 +136,24 @@ var a: Class(5, i32*); // CHECK:STDOUT: // CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32"; // CHECK:STDOUT: +// CHECK:STDOUT: specific file.%Class.decl(constants.%T, constants.%N) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: file.%T.loc4_13.2 => constants.%T +// CHECK:STDOUT: file.%N.loc4_23.2 => constants.%N +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific file.%Class.decl(constants.%.3, constants.%.4) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: file.%T.loc4_13.2 => constants.%.3 +// CHECK:STDOUT: file.%N.loc4_23.2 => constants.%.4 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific file.%Class.decl(constants.%.1, constants.%.6) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: file.%T.loc4_13.2 => constants.%.1 +// CHECK:STDOUT: file.%N.loc4_23.2 => constants.%.6 +// CHECK:STDOUT: } +// CHECK:STDOUT: // CHECK:STDOUT: --- fail_too_few.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { @@ -146,7 +164,7 @@ var a: Class(5, i32*); // CHECK:STDOUT: %N: i32 = bind_symbolic_name N 1 [symbolic] // CHECK:STDOUT: %Class.type: type = generic_class_type @Class [template] // CHECK:STDOUT: %Class.1: %Class.type = struct_value () [template] -// CHECK:STDOUT: %Class.2: type = class_type @Class, (%T, %N) [symbolic] +// CHECK:STDOUT: %Class.2: type = class_type @Class, file.%Class.decl(%T, %N) [symbolic] // CHECK:STDOUT: %.2: type = struct_type {} [template] // CHECK:STDOUT: %.3: type = ptr_type i32 [template] // CHECK:STDOUT: } @@ -193,6 +211,12 @@ var a: Class(5, i32*); // CHECK:STDOUT: // CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32"; // CHECK:STDOUT: +// CHECK:STDOUT: specific file.%Class.decl(constants.%T, constants.%N) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: file.%T.loc4_13.2 => constants.%T +// CHECK:STDOUT: file.%N.loc4_23.2 => constants.%N +// CHECK:STDOUT: } +// CHECK:STDOUT: // CHECK:STDOUT: --- fail_too_many.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { @@ -203,7 +227,7 @@ var a: Class(5, i32*); // CHECK:STDOUT: %N: i32 = bind_symbolic_name N 1 [symbolic] // CHECK:STDOUT: %Class.type: type = generic_class_type @Class [template] // CHECK:STDOUT: %Class.1: %Class.type = struct_value () [template] -// CHECK:STDOUT: %Class.2: type = class_type @Class, (%T, %N) [symbolic] +// CHECK:STDOUT: %Class.2: type = class_type @Class, file.%Class.decl(%T, %N) [symbolic] // CHECK:STDOUT: %.2: type = struct_type {} [template] // CHECK:STDOUT: %.3: type = ptr_type i32 [template] // CHECK:STDOUT: %.4: i32 = int_literal 1 [template] @@ -254,6 +278,12 @@ var a: Class(5, i32*); // CHECK:STDOUT: // CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32"; // CHECK:STDOUT: +// CHECK:STDOUT: specific file.%Class.decl(constants.%T, constants.%N) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: file.%T.loc4_13.2 => constants.%T +// CHECK:STDOUT: file.%N.loc4_23.2 => constants.%N +// CHECK:STDOUT: } +// CHECK:STDOUT: // CHECK:STDOUT: --- fail_no_conversion.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { @@ -264,7 +294,7 @@ var a: Class(5, i32*); // CHECK:STDOUT: %N: i32 = bind_symbolic_name N 1 [symbolic] // CHECK:STDOUT: %Class.type: type = generic_class_type @Class [template] // CHECK:STDOUT: %Class.1: %Class.type = struct_value () [template] -// CHECK:STDOUT: %Class.2: type = class_type @Class, (%T, %N) [symbolic] +// CHECK:STDOUT: %Class.2: type = class_type @Class, file.%Class.decl(%T, %N) [symbolic] // CHECK:STDOUT: %.2: type = struct_type {} [template] // CHECK:STDOUT: %.3: i32 = int_literal 5 [template] // CHECK:STDOUT: %.4: type = ptr_type i32 [template] @@ -313,3 +343,9 @@ var a: Class(5, i32*); // CHECK:STDOUT: // CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32"; // CHECK:STDOUT: +// CHECK:STDOUT: specific file.%Class.decl(constants.%T, constants.%N) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: file.%T.loc4_13.2 => constants.%T +// CHECK:STDOUT: file.%N.loc4_23.2 => constants.%N +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/class/generic/fail_todo_use.carbon b/toolchain/check/testdata/class/generic/fail_todo_use.carbon index a5522e5215f3..097e433630f0 100644 --- a/toolchain/check/testdata/class/generic/fail_todo_use.carbon +++ b/toolchain/check/testdata/class/generic/fail_todo_use.carbon @@ -43,7 +43,7 @@ fn Run() -> i32 { // CHECK:STDOUT: %Class.type: type = generic_class_type @Class [template] // CHECK:STDOUT: %.1: type = tuple_type () [template] // CHECK:STDOUT: %Class.1: %Class.type = struct_value () [template] -// CHECK:STDOUT: %Class.2: type = class_type @Class, (%T) [symbolic] +// CHECK:STDOUT: %Class.2: type = class_type @Class, file.%Class.decl(%T) [symbolic] // CHECK:STDOUT: %.2: type = ptr_type %Class.2 [symbolic] // CHECK:STDOUT: %.3: type = ptr_type %T [symbolic] // CHECK:STDOUT: %Get.type: type = fn_type @Get [template] @@ -55,7 +55,7 @@ fn Run() -> i32 { // CHECK:STDOUT: %Int32: %Int32.type = struct_value () [template] // CHECK:STDOUT: %Run.type: type = fn_type @Run [template] // CHECK:STDOUT: %Run: %Run.type = struct_value () [template] -// CHECK:STDOUT: %Class.3: type = class_type @Class, (i32) [template] +// CHECK:STDOUT: %Class.3: type = class_type @Class, file.%Class.decl(i32) [template] // CHECK:STDOUT: %.7: i32 = int_literal 0 [template] // CHECK:STDOUT: %.8: type = struct_type {.k: i32} [template] // CHECK:STDOUT: %.9: type = ptr_type %Class.3 [template] @@ -89,7 +89,7 @@ fn Run() -> i32 { // CHECK:STDOUT: class @Class // CHECK:STDOUT: generic [file.%T.loc11_13.2: type] { // CHECK:STDOUT: %Get.decl: %Get.type = fn_decl @Get [template = constants.%Get] { -// CHECK:STDOUT: %.loc12_21: type = specific_constant constants.%Class.2, (constants.%T) [symbolic = %.loc12_21 (constants.%Class.2)] +// CHECK:STDOUT: %.loc12_21: type = specific_constant constants.%Class.2, file.%Class.decl(constants.%T) [symbolic = %.loc12_21 (constants.%Class.2)] // CHECK:STDOUT: %Self.ref: type = name_ref Self, %.loc12_21 [symbolic = %.loc12_21 (constants.%Class.2)] // CHECK:STDOUT: %.loc12_25: type = ptr_type %Class.2 [symbolic = %.loc12_25 (constants.%.2)] // CHECK:STDOUT: %self.loc12_15.1: @Class.%.loc12_25 (%.2) = param self @@ -143,3 +143,21 @@ fn Run() -> i32 { // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific file.%Class.decl(constants.%T) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: file.%T.loc11_13.2 => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @Class.%Get.decl(constants.%T) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: @Class.%.loc12_21 => constants.%Class.2 +// CHECK:STDOUT: @Class.%.loc12_25 => constants.%.2 +// CHECK:STDOUT: @Class.%T.ref.loc12 => constants.%T +// CHECK:STDOUT: @Class.%.loc12_34 => constants.%.3 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific file.%Class.decl(i32) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: file.%T.loc11_13.2 => i32 +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/class/generic/field.carbon b/toolchain/check/testdata/class/generic/field.carbon index 77694354aba7..93f7ee6f2caf 100644 --- a/toolchain/check/testdata/class/generic/field.carbon +++ b/toolchain/check/testdata/class/generic/field.carbon @@ -58,7 +58,7 @@ fn H(U:! type, c: Class(U)) -> U { // CHECK:STDOUT: %Class.type: type = generic_class_type @Class [template] // CHECK:STDOUT: %.1: type = tuple_type () [template] // CHECK:STDOUT: %Class.1: %Class.type = struct_value () [template] -// CHECK:STDOUT: %Class.2: type = class_type @Class, (%T) [symbolic] +// CHECK:STDOUT: %Class.2: type = class_type @Class, file.%Class.decl(%T) [symbolic] // CHECK:STDOUT: %.2: type = unbound_element_type %Class.2, %T [symbolic] // CHECK:STDOUT: %.3: type = struct_type {.x: %T} [symbolic] // CHECK:STDOUT: %G.type: type = fn_type @G [template] @@ -113,6 +113,17 @@ fn H(U:! type, c: Class(U)) -> U { // CHECK:STDOUT: return %.loc9_11.2 // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific file.%Class.decl(constants.%T) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: file.%T.loc2_13.2 => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific file.%G.decl(constants.%T) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: @G.%T => constants.%T +// CHECK:STDOUT: file.%.loc8_24 => constants.%Class.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: // CHECK:STDOUT: --- fail_todo_field.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { @@ -120,17 +131,17 @@ fn H(U:! type, c: Class(U)) -> U { // CHECK:STDOUT: %Class.type: type = generic_class_type @Class [template] // CHECK:STDOUT: %.1: type = tuple_type () [template] // CHECK:STDOUT: %Class.1: %Class.type = struct_value () [template] -// CHECK:STDOUT: %Class.2: type = class_type @Class, (%T) [symbolic] +// CHECK:STDOUT: %Class.2: type = class_type @Class, file.%Class.decl(%T) [symbolic] // CHECK:STDOUT: %.2: type = unbound_element_type %Class.2, %T [symbolic] // CHECK:STDOUT: %.3: type = struct_type {.x: %T} [symbolic] // CHECK:STDOUT: %Int32.type: type = fn_type @Int32 [template] // CHECK:STDOUT: %Int32: %Int32.type = struct_value () [template] -// CHECK:STDOUT: %Class.3: type = class_type @Class, (i32) [template] +// CHECK:STDOUT: %Class.3: type = class_type @Class, file.%Class.decl(i32) [template] // CHECK:STDOUT: %F.type: type = fn_type @F [template] // CHECK:STDOUT: %F: %F.type = struct_value () [template] // CHECK:STDOUT: %.4: type = ptr_type %.3 [symbolic] // CHECK:STDOUT: %U: type = bind_symbolic_name U 0 [symbolic] -// CHECK:STDOUT: %Class.4: type = class_type @Class, (%U) [symbolic] +// CHECK:STDOUT: %Class.4: type = class_type @Class, file.%Class.decl(%U) [symbolic] // CHECK:STDOUT: %H.type: type = fn_type @H [template] // CHECK:STDOUT: %H: %H.type = struct_value () [template] // CHECK:STDOUT: } @@ -212,3 +223,24 @@ fn H(U:! type, c: Class(U)) -> U { // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific file.%Class.decl(constants.%T) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: file.%T.loc2_13.2 => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific file.%Class.decl(i32) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: file.%T.loc2_13.2 => i32 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific file.%Class.decl(constants.%U) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: file.%T.loc2_13.2 => constants.%U +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific file.%H.decl(constants.%U) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: @H.%U => constants.%U +// CHECK:STDOUT: file.%.loc18_24 => constants.%Class.4 +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/class/generic/import.carbon b/toolchain/check/testdata/class/generic/import.carbon index 15359f02b526..cfcf89b8c46e 100644 --- a/toolchain/check/testdata/class/generic/import.carbon +++ b/toolchain/check/testdata/class/generic/import.carbon @@ -95,10 +95,10 @@ class Class(U:! type) { // CHECK:STDOUT: %Class.type: type = generic_class_type @Class [template] // CHECK:STDOUT: %.1: type = tuple_type () [template] // CHECK:STDOUT: %Class.1: %Class.type = struct_value () [template] -// CHECK:STDOUT: %Class.2: type = class_type @Class, (%T) [symbolic] +// CHECK:STDOUT: %Class.2: type = class_type @Class, file.%Class.decl(%T) [symbolic] // CHECK:STDOUT: %CompleteClass.type: type = generic_class_type @CompleteClass [template] // CHECK:STDOUT: %CompleteClass.1: %CompleteClass.type = struct_value () [template] -// CHECK:STDOUT: %CompleteClass.2: type = class_type @CompleteClass, (%T) [symbolic] +// CHECK:STDOUT: %CompleteClass.2: type = class_type @CompleteClass, file.%CompleteClass.decl(%T) [symbolic] // CHECK:STDOUT: %Int32.type: type = fn_type @Int32 [template] // CHECK:STDOUT: %Int32: %Int32.type = struct_value () [template] // CHECK:STDOUT: %.2: type = unbound_element_type %CompleteClass.2, i32 [symbolic] @@ -106,7 +106,7 @@ class Class(U:! type) { // CHECK:STDOUT: %F.1: %F.type.1 = struct_value () [template] // CHECK:STDOUT: %.3: type = struct_type {.n: i32} [template] // CHECK:STDOUT: %.4: i32 = int_literal 0 [template] -// CHECK:STDOUT: %CompleteClass.3: type = class_type @CompleteClass, (i32) [template] +// CHECK:STDOUT: %CompleteClass.3: type = class_type @CompleteClass, file.%CompleteClass.decl(i32) [template] // CHECK:STDOUT: %F.type.2: type = fn_type @F.2 [template] // CHECK:STDOUT: %F.2: %F.type.2 = struct_value () [template] // CHECK:STDOUT: } @@ -179,6 +179,25 @@ class Class(U:! type) { // CHECK:STDOUT: // CHECK:STDOUT: fn @F.2() -> %CompleteClass.3; // CHECK:STDOUT: +// CHECK:STDOUT: specific file.%Class.decl(constants.%T) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: file.%T.loc4_13.2 => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific file.%CompleteClass.decl(constants.%T) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: file.%T.loc6_21.2 => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @CompleteClass.%F.decl(constants.%T) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific file.%CompleteClass.decl(i32) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: file.%T.loc6_21.2 => i32 +// CHECK:STDOUT: } +// CHECK:STDOUT: // CHECK:STDOUT: --- foo.impl.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { @@ -186,16 +205,16 @@ class Class(U:! type) { // CHECK:STDOUT: %Class.type: type = generic_class_type @Class [template] // CHECK:STDOUT: %.1: type = tuple_type () [template] // CHECK:STDOUT: %Class.1: %Class.type = struct_value () [template] -// CHECK:STDOUT: %Class.2: type = class_type @Class, (%T) [symbolic] +// CHECK:STDOUT: %Class.2: type = class_type @Class, (%T) [symbolic] // CHECK:STDOUT: %.2: type = unbound_element_type %Class.2, %T [symbolic] // CHECK:STDOUT: %.3: type = struct_type {.x: %T} [symbolic] // CHECK:STDOUT: %CompleteClass.type: type = generic_class_type @CompleteClass [template] // CHECK:STDOUT: %CompleteClass.1: %CompleteClass.type = struct_value () [template] // CHECK:STDOUT: %.4: type = struct_type {.n: i32} [template] -// CHECK:STDOUT: %CompleteClass.2: type = class_type @CompleteClass, (%T) [symbolic] +// CHECK:STDOUT: %CompleteClass.2: type = class_type @CompleteClass, (%T) [symbolic] // CHECK:STDOUT: %Int32.type: type = fn_type @Int32 [template] // CHECK:STDOUT: %Int32: %Int32.type = struct_value () [template] -// CHECK:STDOUT: %CompleteClass.3: type = class_type @CompleteClass, (i32) [template] +// CHECK:STDOUT: %CompleteClass.3: type = class_type @CompleteClass, (i32) [template] // CHECK:STDOUT: %F.type: type = fn_type @F [template] // CHECK:STDOUT: %F: %F.type = struct_value () [template] // CHECK:STDOUT: %.5: type = ptr_type %.4 [template] @@ -269,6 +288,10 @@ class Class(U:! type) { // CHECK:STDOUT: return %.loc9_18 to %return // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific (constants.%T); +// CHECK:STDOUT: +// CHECK:STDOUT: specific (i32); +// CHECK:STDOUT: // CHECK:STDOUT: --- use_foo.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { @@ -281,8 +304,8 @@ class Class(U:! type) { // CHECK:STDOUT: %CompleteClass.1: %CompleteClass.type = struct_value () [template] // CHECK:STDOUT: %.2: type = struct_type {.n: i32} [template] // CHECK:STDOUT: %T: type = bind_symbolic_name T 0, [symbolic] -// CHECK:STDOUT: %CompleteClass.2: type = class_type @CompleteClass, (%T) [symbolic] -// CHECK:STDOUT: %CompleteClass.3: type = class_type @CompleteClass, (i32) [template] +// CHECK:STDOUT: %CompleteClass.2: type = class_type @CompleteClass, (%T) [symbolic] +// CHECK:STDOUT: %CompleteClass.3: type = class_type @CompleteClass, (i32) [template] // CHECK:STDOUT: %.3: type = ptr_type %.2 [template] // CHECK:STDOUT: %F.type.1: type = fn_type @F.1 [template] // CHECK:STDOUT: %F.1: %F.type.1 = struct_value () [template] @@ -356,6 +379,10 @@ class Class(U:! type) { // CHECK:STDOUT: // CHECK:STDOUT: fn @F.2() -> i32; // CHECK:STDOUT: +// CHECK:STDOUT: specific (constants.%T); +// CHECK:STDOUT: +// CHECK:STDOUT: specific (i32); +// CHECK:STDOUT: // CHECK:STDOUT: --- fail_todo_use_foo.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { @@ -368,8 +395,8 @@ class Class(U:! type) { // CHECK:STDOUT: %CompleteClass.1: %CompleteClass.type = struct_value () [template] // CHECK:STDOUT: %.2: type = struct_type {.n: i32} [template] // CHECK:STDOUT: %T: type = bind_symbolic_name T 0, [symbolic] -// CHECK:STDOUT: %CompleteClass.2: type = class_type @CompleteClass, (%T) [symbolic] -// CHECK:STDOUT: %CompleteClass.3: type = class_type @CompleteClass, (i32) [template] +// CHECK:STDOUT: %CompleteClass.2: type = class_type @CompleteClass, (%T) [symbolic] +// CHECK:STDOUT: %CompleteClass.3: type = class_type @CompleteClass, (i32) [template] // CHECK:STDOUT: %.3: type = ptr_type %.2 [template] // CHECK:STDOUT: %F.type: type = fn_type @F [template] // CHECK:STDOUT: %F: %F.type = struct_value () [template] @@ -438,6 +465,10 @@ class Class(U:! type) { // CHECK:STDOUT: // CHECK:STDOUT: fn @F() -> %CompleteClass.3; // CHECK:STDOUT: +// CHECK:STDOUT: specific (constants.%T); +// CHECK:STDOUT: +// CHECK:STDOUT: specific (i32); +// CHECK:STDOUT: // CHECK:STDOUT: --- fail_generic_arg_mismatch.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { @@ -448,13 +479,13 @@ class Class(U:! type) { // CHECK:STDOUT: %CompleteClass.1: %CompleteClass.type = struct_value () [template] // CHECK:STDOUT: %.2: type = struct_type {.n: i32} [template] // CHECK:STDOUT: %T: type = bind_symbolic_name T 0, [symbolic] -// CHECK:STDOUT: %CompleteClass.2: type = class_type @CompleteClass, (%T) [symbolic] +// CHECK:STDOUT: %CompleteClass.2: type = class_type @CompleteClass, (%T) [symbolic] // CHECK:STDOUT: %Int32.type: type = fn_type @Int32 [template] // CHECK:STDOUT: %Int32: %Int32.type = struct_value () [template] // CHECK:STDOUT: %.3: type = ptr_type i32 [template] -// CHECK:STDOUT: %CompleteClass.3: type = class_type @CompleteClass, (%.3) [template] +// CHECK:STDOUT: %CompleteClass.3: type = class_type @CompleteClass, (%.3) [template] // CHECK:STDOUT: %.4: type = ptr_type %.2 [template] -// CHECK:STDOUT: %CompleteClass.4: type = class_type @CompleteClass, (i32) [template] +// CHECK:STDOUT: %CompleteClass.4: type = class_type @CompleteClass, (i32) [template] // CHECK:STDOUT: %F.type: type = fn_type @F [template] // CHECK:STDOUT: %F: %F.type = struct_value () [template] // CHECK:STDOUT: } @@ -513,6 +544,12 @@ class Class(U:! type) { // CHECK:STDOUT: // CHECK:STDOUT: fn @F() -> %CompleteClass.4; // CHECK:STDOUT: +// CHECK:STDOUT: specific (constants.%T); +// CHECK:STDOUT: +// CHECK:STDOUT: specific (constants.%.3); +// CHECK:STDOUT: +// CHECK:STDOUT: specific (i32); +// CHECK:STDOUT: // CHECK:STDOUT: --- fail_bad_foo.impl.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { @@ -521,10 +558,10 @@ class Class(U:! type) { // CHECK:STDOUT: %.1: type = tuple_type () [template] // CHECK:STDOUT: %Class.1: %Class.type = struct_value () [template] // CHECK:STDOUT: %T: type = bind_symbolic_name T 0, [symbolic] -// CHECK:STDOUT: %Class.2: type = class_type @Class, (%T) [symbolic] +// CHECK:STDOUT: %Class.2: type = class_type @Class, (%T) [symbolic] // CHECK:STDOUT: %.type: type = generic_class_type @.1 [template] // CHECK:STDOUT: %.2: %.type = struct_value () [template] -// CHECK:STDOUT: %.3: type = class_type @.1, (%U) [symbolic] +// CHECK:STDOUT: %.3: type = class_type @.1, file.%.decl(%U) [symbolic] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { @@ -562,3 +599,10 @@ class Class(U:! type) { // CHECK:STDOUT: .x = %.loc13 // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific (constants.%T); +// CHECK:STDOUT: +// CHECK:STDOUT: specific file.%.decl(constants.%U) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: file.%U.loc9_13.2 => constants.%U +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/class/generic/member_inline.carbon b/toolchain/check/testdata/class/generic/member_inline.carbon index 8c1cbe408812..af7b0e7f34bf 100644 --- a/toolchain/check/testdata/class/generic/member_inline.carbon +++ b/toolchain/check/testdata/class/generic/member_inline.carbon @@ -21,7 +21,7 @@ class Class(T:! type) { // CHECK:STDOUT: %Class.type: type = generic_class_type @Class [template] // CHECK:STDOUT: %.1: type = tuple_type () [template] // CHECK:STDOUT: %Class.1: %Class.type = struct_value () [template] -// CHECK:STDOUT: %Class.2: type = class_type @Class, (%T) [symbolic] +// CHECK:STDOUT: %Class.2: type = class_type @Class, file.%Class.decl(%T) [symbolic] // CHECK:STDOUT: %F.type: type = fn_type @F [template] // CHECK:STDOUT: %F: %F.type = struct_value () [template] // CHECK:STDOUT: %.2: type = struct_type {} [template] @@ -62,3 +62,13 @@ class Class(T:! type) { // CHECK:STDOUT: return %n.ref // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific file.%Class.decl(constants.%T) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: file.%T.loc11_13.2 => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @Class.%F.decl(constants.%T) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: @Class.%T.ref.loc12_11 => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/class/generic/member_out_of_line.carbon b/toolchain/check/testdata/class/generic/member_out_of_line.carbon index 60626bdd51ea..5074f37c173a 100644 --- a/toolchain/check/testdata/class/generic/member_out_of_line.carbon +++ b/toolchain/check/testdata/class/generic/member_out_of_line.carbon @@ -106,7 +106,7 @@ fn Generic(T:! ()).WrongType() {} // CHECK:STDOUT: %Class.type: type = generic_class_type @Class [template] // CHECK:STDOUT: %.1: type = tuple_type () [template] // CHECK:STDOUT: %Class.1: %Class.type = struct_value () [template] -// CHECK:STDOUT: %Class.2: type = class_type @Class, (%T) [symbolic] +// CHECK:STDOUT: %Class.2: type = class_type @Class, file.%Class.decl(%T) [symbolic] // CHECK:STDOUT: %F.type: type = fn_type @F [template] // CHECK:STDOUT: %F: %F.type = struct_value () [template] // CHECK:STDOUT: %.2: type = struct_type {} [template] @@ -156,6 +156,16 @@ fn Generic(T:! ()).WrongType() {} // CHECK:STDOUT: return %n.ref // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific file.%Class.decl(constants.%T) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: file.%T.loc4_13.2 => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @Class.%F.decl(constants.%T) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: @Class.%T.ref.loc5_11 => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: // CHECK:STDOUT: --- nested.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { @@ -163,11 +173,11 @@ fn Generic(T:! ()).WrongType() {} // CHECK:STDOUT: %A.type: type = generic_class_type @A [template] // CHECK:STDOUT: %.1: type = tuple_type () [template] // CHECK:STDOUT: %A.1: %A.type = struct_value () [template] -// CHECK:STDOUT: %A.2: type = class_type @A, (%T) [symbolic] +// CHECK:STDOUT: %A.2: type = class_type @A, file.%A.decl(%T) [symbolic] // CHECK:STDOUT: %N: %T = bind_symbolic_name N 1 [symbolic] // CHECK:STDOUT: %B.type: type = generic_class_type @B [template] // CHECK:STDOUT: %B.1: %B.type = struct_value () [template] -// CHECK:STDOUT: %B.2: type = class_type @B, (%T, %N) [symbolic] +// CHECK:STDOUT: %B.2: type = class_type @B, @A.%B.decl(%T, %N) [symbolic] // CHECK:STDOUT: %F.type: type = fn_type @F [template] // CHECK:STDOUT: %F: %F.type = struct_value () [template] // CHECK:STDOUT: %.2: type = struct_type {} [template] @@ -191,7 +201,7 @@ fn Generic(T:! ()).WrongType() {} // CHECK:STDOUT: %T.ref.loc10_22: type = name_ref T, %T.loc10_6.2 [symbolic = constants.%T] // CHECK:STDOUT: %N.loc10_18.1: %T = param N // CHECK:STDOUT: %N.loc10_18.2: %T = bind_symbolic_name N 1, %N.loc10_18.1 [symbolic = constants.%N] -// CHECK:STDOUT: %.loc10: type = specific_constant constants.%B.2, (constants.%T, constants.%N) [symbolic = constants.%B.2] +// CHECK:STDOUT: %.loc10: type = specific_constant constants.%B.2, @A.%B.decl(constants.%T, constants.%N) [symbolic = constants.%B.2] // CHECK:STDOUT: %Self.ref: type = name_ref Self, %.loc10 [symbolic = constants.%B.2] // CHECK:STDOUT: %self.loc10_27.1: %B.2 = param self // CHECK:STDOUT: @F.%self: %B.2 = bind_name self, %self.loc10_27.1 @@ -217,7 +227,7 @@ fn Generic(T:! ()).WrongType() {} // CHECK:STDOUT: class @B // CHECK:STDOUT: generic [file.%T.loc4_9.2: type, @A.%N.loc5_11.2: @A.%T.ref (%T)] { // CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [template = constants.%F] { -// CHECK:STDOUT: %.loc6: type = specific_constant constants.%B.2, (constants.%T, constants.%N) [symbolic = %.loc6 (constants.%B.2)] +// CHECK:STDOUT: %.loc6: type = specific_constant constants.%B.2, @A.%B.decl(constants.%T, constants.%N) [symbolic = %.loc6 (constants.%B.2)] // CHECK:STDOUT: %Self.ref: type = name_ref Self, %.loc6 [symbolic = %.loc6 (constants.%B.2)] // CHECK:STDOUT: %self.loc6_10.1: @B.%.loc6 (%B.2) = param self // CHECK:STDOUT: %self.loc6_10.2: @B.%.loc6 (%B.2) = bind_name self, %self.loc6_10.1 @@ -237,6 +247,23 @@ fn Generic(T:! ()).WrongType() {} // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific file.%A.decl(constants.%T) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: file.%T.loc4_9.2 => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @A.%B.decl(constants.%T, constants.%N) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: @A.%T.ref => constants.%T +// CHECK:STDOUT: @A.%N.loc5_11.2 => constants.%N +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @B.%F.decl(constants.%T, constants.%N) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: @B.%.loc6 => constants.%B.2 +// CHECK:STDOUT: @B.%T.ref => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: // CHECK:STDOUT: --- fail_mismatched_not_generic_vs_generic.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { @@ -280,6 +307,11 @@ fn Generic(T:! ()).WrongType() {} // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific file.%.decl(constants.%T) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: file.%T.loc15_15.2 => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: // CHECK:STDOUT: --- fail_mismatched_too_few_args.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { @@ -287,7 +319,7 @@ fn Generic(T:! ()).WrongType() {} // CHECK:STDOUT: %Generic.type: type = generic_class_type @Generic [template] // CHECK:STDOUT: %.1: type = tuple_type () [template] // CHECK:STDOUT: %Generic.1: %Generic.type = struct_value () [template] -// CHECK:STDOUT: %Generic.2: type = class_type @Generic, (%T) [symbolic] +// CHECK:STDOUT: %Generic.2: type = class_type @Generic, file.%Generic.decl(%T) [symbolic] // CHECK:STDOUT: %TooFew.type: type = fn_type @TooFew [template] // CHECK:STDOUT: %TooFew: %TooFew.type = struct_value () [template] // CHECK:STDOUT: %.2: type = struct_type {} [template] @@ -326,6 +358,15 @@ fn Generic(T:! ()).WrongType() {} // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific file.%Generic.decl(constants.%T) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: file.%T.loc4_15.2 => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @Generic.%TooFew.decl(constants.%T) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: } +// CHECK:STDOUT: // CHECK:STDOUT: --- fail_mismatched_too_many_args.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { @@ -333,7 +374,7 @@ fn Generic(T:! ()).WrongType() {} // CHECK:STDOUT: %Generic.type: type = generic_class_type @Generic [template] // CHECK:STDOUT: %.1: type = tuple_type () [template] // CHECK:STDOUT: %Generic.1: %Generic.type = struct_value () [template] -// CHECK:STDOUT: %Generic.2: type = class_type @Generic, (%T) [symbolic] +// CHECK:STDOUT: %Generic.2: type = class_type @Generic, file.%Generic.decl(%T) [symbolic] // CHECK:STDOUT: %TooMany.type: type = fn_type @TooMany [template] // CHECK:STDOUT: %TooMany: %TooMany.type = struct_value () [template] // CHECK:STDOUT: %.2: type = struct_type {} [template] @@ -379,6 +420,21 @@ fn Generic(T:! ()).WrongType() {} // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific file.%Generic.decl(constants.%T) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: file.%T.loc4_15.2 => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @Generic.%TooMany.decl(constants.%T) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific file.%.decl(constants.%T, constants.%U) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: file.%T.loc15_12.2 => constants.%T +// CHECK:STDOUT: file.%U.loc15_22.2 => constants.%U +// CHECK:STDOUT: } +// CHECK:STDOUT: // CHECK:STDOUT: --- fail_mismatched_wrong_arg_type.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { @@ -386,7 +442,7 @@ fn Generic(T:! ()).WrongType() {} // CHECK:STDOUT: %Generic.type: type = generic_class_type @Generic [template] // CHECK:STDOUT: %.1: type = tuple_type () [template] // CHECK:STDOUT: %Generic.1: %Generic.type = struct_value () [template] -// CHECK:STDOUT: %Generic.2: type = class_type @Generic, (%T.1) [symbolic] +// CHECK:STDOUT: %Generic.2: type = class_type @Generic, file.%Generic.decl(%T.1) [symbolic] // CHECK:STDOUT: %WrongType.type: type = fn_type @WrongType [template] // CHECK:STDOUT: %WrongType: %WrongType.type = struct_value () [template] // CHECK:STDOUT: %.2: type = struct_type {} [template] @@ -432,3 +488,17 @@ fn Generic(T:! ()).WrongType() {} // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific file.%Generic.decl(constants.%T.1) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: file.%T.loc4_15.2 => constants.%T.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @Generic.%WrongType.decl(constants.%T.1) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific file.%.decl(constants.%T.2) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: file.%T.loc14_12.2 => constants.%T.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/class/generic/redeclare.carbon b/toolchain/check/testdata/class/generic/redeclare.carbon index 89f4c16fd551..4bd4c23ffc11 100644 --- a/toolchain/check/testdata/class/generic/redeclare.carbon +++ b/toolchain/check/testdata/class/generic/redeclare.carbon @@ -93,7 +93,7 @@ class E(U:! type) {} // CHECK:STDOUT: %Generic.type: type = generic_class_type @Generic [template] // CHECK:STDOUT: %.1: type = tuple_type () [template] // CHECK:STDOUT: %Generic.1: %Generic.type = struct_value () [template] -// CHECK:STDOUT: %Generic.2: type = class_type @Generic, (%T) [symbolic] +// CHECK:STDOUT: %Generic.2: type = class_type @Generic, file.%Generic.decl.loc4(%T) [symbolic] // CHECK:STDOUT: %.2: type = struct_type {} [template] // CHECK:STDOUT: } // CHECK:STDOUT: @@ -120,6 +120,11 @@ class E(U:! type) {} // CHECK:STDOUT: .Self = constants.%Generic.2 // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific file.%Generic.decl.loc4(constants.%T) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: file.%T.loc4_15.2 => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: // CHECK:STDOUT: --- fail_mismatch_param_list.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { @@ -128,7 +133,7 @@ class E(U:! type) {} // CHECK:STDOUT: %.type: type = generic_class_type @.1 [template] // CHECK:STDOUT: %.1: type = tuple_type () [template] // CHECK:STDOUT: %.2: %.type = struct_value () [template] -// CHECK:STDOUT: %.3: type = class_type @.1, (%T) [symbolic] +// CHECK:STDOUT: %.3: type = class_type @.1, file.%.decl(%T) [symbolic] // CHECK:STDOUT: %.4: type = struct_type {} [template] // CHECK:STDOUT: } // CHECK:STDOUT: @@ -154,6 +159,11 @@ class E(U:! type) {} // CHECK:STDOUT: .Self = constants.%.3 // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific file.%.decl(constants.%T) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: file.%T.loc12_9.2 => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: // CHECK:STDOUT: --- fail_mismatch_implicit_param_list.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { @@ -163,12 +173,12 @@ class E(U:! type) {} // CHECK:STDOUT: %N.1: i32 = bind_symbolic_name N 0 [symbolic] // CHECK:STDOUT: %B.type: type = generic_class_type @B [template] // CHECK:STDOUT: %B.1: %B.type = struct_value () [template] -// CHECK:STDOUT: %B.2: type = class_type @B, (%N.1) [symbolic] +// CHECK:STDOUT: %B.2: type = class_type @B, file.%B.decl(%N.1) [symbolic] // CHECK:STDOUT: %T: type = bind_symbolic_name T 0 [symbolic] // CHECK:STDOUT: %N.2: %T = bind_symbolic_name N 1 [symbolic] // CHECK:STDOUT: %.type: type = generic_class_type @.1 [template] // CHECK:STDOUT: %.2: %.type = struct_value () [template] -// CHECK:STDOUT: %.3: type = class_type @.1, (%T, %N.2) [symbolic] +// CHECK:STDOUT: %.3: type = class_type @.1, file.%.decl(%T, %N.2) [symbolic] // CHECK:STDOUT: %.4: type = struct_type {} [template] // CHECK:STDOUT: } // CHECK:STDOUT: @@ -210,6 +220,17 @@ class E(U:! type) {} // CHECK:STDOUT: // CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32"; // CHECK:STDOUT: +// CHECK:STDOUT: specific file.%B.decl(constants.%N.1) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: file.%N.loc4_9.2 => constants.%N.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific file.%.decl(constants.%T, constants.%N.2) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: file.%T.loc12_9.2 => constants.%T +// CHECK:STDOUT: file.%N.loc12_19.2 => constants.%N.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: // CHECK:STDOUT: --- fail_mismatch_param_count.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { @@ -217,13 +238,13 @@ class E(U:! type) {} // CHECK:STDOUT: %C.type: type = generic_class_type @C [template] // CHECK:STDOUT: %.1: type = tuple_type () [template] // CHECK:STDOUT: %C.1: %C.type = struct_value () [template] -// CHECK:STDOUT: %C.2: type = class_type @C, (%T) [symbolic] +// CHECK:STDOUT: %C.2: type = class_type @C, file.%C.decl(%T) [symbolic] // CHECK:STDOUT: %Int32.type: type = fn_type @Int32 [template] // CHECK:STDOUT: %Int32: %Int32.type = struct_value () [template] // CHECK:STDOUT: %U: i32 = bind_symbolic_name U 1 [symbolic] // CHECK:STDOUT: %.type: type = generic_class_type @.1 [template] // CHECK:STDOUT: %.2: %.type = struct_value () [template] -// CHECK:STDOUT: %.3: type = class_type @.1, (%T, %U) [symbolic] +// CHECK:STDOUT: %.3: type = class_type @.1, file.%.decl(%T, %U) [symbolic] // CHECK:STDOUT: %.4: type = struct_type {} [template] // CHECK:STDOUT: } // CHECK:STDOUT: @@ -264,6 +285,17 @@ class E(U:! type) {} // CHECK:STDOUT: // CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32"; // CHECK:STDOUT: +// CHECK:STDOUT: specific file.%C.decl(constants.%T) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: file.%T.loc4_9.2 => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific file.%.decl(constants.%T, constants.%U) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: file.%T.loc12_9.2 => constants.%T +// CHECK:STDOUT: file.%U.loc12_19.2 => constants.%U +// CHECK:STDOUT: } +// CHECK:STDOUT: // CHECK:STDOUT: --- fail_mismatch_param_type.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { @@ -271,13 +303,13 @@ class E(U:! type) {} // CHECK:STDOUT: %D.type: type = generic_class_type @D [template] // CHECK:STDOUT: %.1: type = tuple_type () [template] // CHECK:STDOUT: %D.1: %D.type = struct_value () [template] -// CHECK:STDOUT: %D.2: type = class_type @D, (%T.1) [symbolic] +// CHECK:STDOUT: %D.2: type = class_type @D, file.%D.decl(%T.1) [symbolic] // CHECK:STDOUT: %Int32.type: type = fn_type @Int32 [template] // CHECK:STDOUT: %Int32: %Int32.type = struct_value () [template] // CHECK:STDOUT: %T.2: i32 = bind_symbolic_name T 0 [symbolic] // CHECK:STDOUT: %.type: type = generic_class_type @.1 [template] // CHECK:STDOUT: %.2: %.type = struct_value () [template] -// CHECK:STDOUT: %.3: type = class_type @.1, (%T.2) [symbolic] +// CHECK:STDOUT: %.3: type = class_type @.1, file.%.decl(%T.2) [symbolic] // CHECK:STDOUT: %.4: type = struct_type {} [template] // CHECK:STDOUT: } // CHECK:STDOUT: @@ -316,6 +348,16 @@ class E(U:! type) {} // CHECK:STDOUT: // CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32"; // CHECK:STDOUT: +// CHECK:STDOUT: specific file.%D.decl(constants.%T.1) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: file.%T.loc4_9.2 => constants.%T.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific file.%.decl(constants.%T.2) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: file.%T.loc12_9.2 => constants.%T.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: // CHECK:STDOUT: --- fail_mismatch_param_name.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { @@ -323,11 +365,11 @@ class E(U:! type) {} // CHECK:STDOUT: %E.type: type = generic_class_type @E [template] // CHECK:STDOUT: %.1: type = tuple_type () [template] // CHECK:STDOUT: %E.1: %E.type = struct_value () [template] -// CHECK:STDOUT: %E.2: type = class_type @E, (%T) [symbolic] +// CHECK:STDOUT: %E.2: type = class_type @E, file.%E.decl(%T) [symbolic] // CHECK:STDOUT: %U: type = bind_symbolic_name U 0 [symbolic] // CHECK:STDOUT: %.type: type = generic_class_type @.1 [template] // CHECK:STDOUT: %.2: %.type = struct_value () [template] -// CHECK:STDOUT: %.3: type = class_type @.1, (%U) [symbolic] +// CHECK:STDOUT: %.3: type = class_type @.1, file.%.decl(%U) [symbolic] // CHECK:STDOUT: %.4: type = struct_type {} [template] // CHECK:STDOUT: } // CHECK:STDOUT: @@ -357,3 +399,13 @@ class E(U:! type) {} // CHECK:STDOUT: .Self = constants.%.3 // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific file.%E.decl(constants.%T) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: file.%T.loc4_9.2 => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific file.%.decl(constants.%U) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: file.%U.loc11_9.2 => constants.%U +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/class/generic/self.carbon b/toolchain/check/testdata/class/generic/self.carbon index 1f7e9c2fb7f6..796e7cf5a098 100644 --- a/toolchain/check/testdata/class/generic/self.carbon +++ b/toolchain/check/testdata/class/generic/self.carbon @@ -26,7 +26,7 @@ class Class(T:! type) { // CHECK:STDOUT: %Class.type: type = generic_class_type @Class [template] // CHECK:STDOUT: %.1: type = tuple_type () [template] // CHECK:STDOUT: %Class.1: %Class.type = struct_value () [template] -// CHECK:STDOUT: %Class.2: type = class_type @Class, (%T) [symbolic] +// CHECK:STDOUT: %Class.2: type = class_type @Class, file.%Class.decl(%T) [symbolic] // CHECK:STDOUT: %MakeSelf.type: type = fn_type @MakeSelf [template] // CHECK:STDOUT: %MakeSelf: %MakeSelf.type = struct_value () [template] // CHECK:STDOUT: %MakeClass.type: type = fn_type @MakeClass [template] @@ -53,7 +53,7 @@ class Class(T:! type) { // CHECK:STDOUT: class @Class // CHECK:STDOUT: generic [file.%T.loc11_13.2: type] { // CHECK:STDOUT: %MakeSelf.decl: %MakeSelf.type = fn_decl @MakeSelf [template = constants.%MakeSelf] { -// CHECK:STDOUT: %.loc14: type = specific_constant constants.%Class.2, (constants.%T) [symbolic = %.loc14 (constants.%Class.2)] +// CHECK:STDOUT: %.loc14: type = specific_constant constants.%Class.2, file.%Class.decl(constants.%T) [symbolic = %.loc14 (constants.%Class.2)] // CHECK:STDOUT: %Self.ref: type = name_ref Self, %.loc14 [symbolic = %.loc14 (constants.%Class.2)] // CHECK:STDOUT: %return.var.loc14: ref %Class.2 = var // CHECK:STDOUT: } @@ -94,7 +94,7 @@ class Class(T:! type) { // CHECK:STDOUT: %.loc17_9: ref %Class.2 = splice_block %c.var {} // CHECK:STDOUT: %MakeSelf.call: init %Class.2 = call %MakeSelf.ref() to %.loc17_9 // CHECK:STDOUT: assign %c.var, %MakeSelf.call -// CHECK:STDOUT: %.loc18_12: type = specific_constant constants.%Class.2, (constants.%T) [symbolic = constants.%Class.2] +// CHECK:STDOUT: %.loc18_12: type = specific_constant constants.%Class.2, file.%Class.decl(constants.%T) [symbolic = constants.%Class.2] // CHECK:STDOUT: %Self.ref: type = name_ref Self, %.loc18_12 [symbolic = constants.%Class.2] // CHECK:STDOUT: %s.var: ref %Class.2 = var s // CHECK:STDOUT: %s: ref %Class.2 = bind_name s, %s.var @@ -105,3 +105,23 @@ class Class(T:! type) { // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific file.%Class.decl(constants.%T) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: file.%T.loc11_13.2 => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @Class.%MakeSelf.decl(constants.%T) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: @Class.%.loc14 => constants.%Class.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @Class.%MakeClass.decl(constants.%T) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: @Class.%T.ref => constants.%T +// CHECK:STDOUT: @Class.%.loc15_26 => constants.%Class.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @Class.%F.decl(constants.%T) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/class/generic_method.carbon b/toolchain/check/testdata/class/generic_method.carbon index 2b4bf66d5112..ebf33e41f36d 100644 --- a/toolchain/check/testdata/class/generic_method.carbon +++ b/toolchain/check/testdata/class/generic_method.carbon @@ -22,7 +22,7 @@ fn Class(T:! type).F[self: Self](n: T) {} // CHECK:STDOUT: %Class.type: type = generic_class_type @Class [template] // CHECK:STDOUT: %.1: type = tuple_type () [template] // CHECK:STDOUT: %Class.1: %Class.type = struct_value () [template] -// CHECK:STDOUT: %Class.2: type = class_type @Class, (%T) [symbolic] +// CHECK:STDOUT: %Class.2: type = class_type @Class, file.%Class.decl(%T) [symbolic] // CHECK:STDOUT: %.2: type = unbound_element_type %Class.2, %T [symbolic] // CHECK:STDOUT: %F.type: type = fn_type @F [template] // CHECK:STDOUT: %F: %F.type = struct_value () [template] @@ -44,7 +44,7 @@ fn Class(T:! type).F[self: Self](n: T) {} // CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [template = constants.%F] { // CHECK:STDOUT: %T.loc16_10.1: type = param T // CHECK:STDOUT: %T.loc16_10.2: type = bind_symbolic_name T 0, %T.loc16_10.1 [symbolic = constants.%T] -// CHECK:STDOUT: %.loc16: type = specific_constant constants.%Class.2, (constants.%T) [symbolic = constants.%Class.2] +// CHECK:STDOUT: %.loc16: type = specific_constant constants.%Class.2, %Class.decl(constants.%T) [symbolic = constants.%Class.2] // CHECK:STDOUT: %Self.ref: type = name_ref Self, %.loc16 [symbolic = constants.%Class.2] // CHECK:STDOUT: %self.loc16_22.1: %Class.2 = param self // CHECK:STDOUT: @F.%self: %Class.2 = bind_name self, %self.loc16_22.1 @@ -59,7 +59,7 @@ fn Class(T:! type).F[self: Self](n: T) {} // CHECK:STDOUT: %T.ref.loc12: type = name_ref T, file.%T.loc11_13.2 [symbolic = constants.%T] // CHECK:STDOUT: %.loc12: %.2 = field_decl a, element0 [template] // CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [template = constants.%F] { -// CHECK:STDOUT: %.loc13: type = specific_constant constants.%Class.2, (constants.%T) [symbolic = %.loc13 (constants.%Class.2)] +// CHECK:STDOUT: %.loc13: type = specific_constant constants.%Class.2, file.%Class.decl(constants.%T) [symbolic = %.loc13 (constants.%Class.2)] // CHECK:STDOUT: %Self.ref: type = name_ref Self, %.loc13 [symbolic = %.loc13 (constants.%Class.2)] // CHECK:STDOUT: %self.loc13_8.1: @Class.%.loc13 (%Class.2) = param self // CHECK:STDOUT: %self.loc13_8.2: @Class.%.loc13 (%Class.2) = bind_name self, %self.loc13_8.1 @@ -80,3 +80,14 @@ fn Class(T:! type).F[self: Self](n: T) {} // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific file.%Class.decl(constants.%T) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: file.%T.loc11_13.2 => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @Class.%F.decl(constants.%T) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: @Class.%.loc13 => constants.%Class.2 +// CHECK:STDOUT: @Class.%T.ref.loc13 => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/eval/fail_symbolic.carbon b/toolchain/check/testdata/eval/fail_symbolic.carbon index f85a4c994083..b4afd5f87793 100644 --- a/toolchain/check/testdata/eval/fail_symbolic.carbon +++ b/toolchain/check/testdata/eval/fail_symbolic.carbon @@ -63,3 +63,8 @@ fn G(N:! i32) { // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific file.%G.decl(constants.%N) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: @G.%N => constants.%N +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/eval/symbolic.carbon b/toolchain/check/testdata/eval/symbolic.carbon index 5b3999892ba6..8c1088c4e45e 100644 --- a/toolchain/check/testdata/eval/symbolic.carbon +++ b/toolchain/check/testdata/eval/symbolic.carbon @@ -70,3 +70,8 @@ fn F(T:! type) { // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific file.%F.decl(constants.%T) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: @F.%T => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/function/builtin/method.carbon b/toolchain/check/testdata/function/builtin/method.carbon index debe90653de9..ece2ffa4720d 100644 --- a/toolchain/check/testdata/function/builtin/method.carbon +++ b/toolchain/check/testdata/function/builtin/method.carbon @@ -136,3 +136,8 @@ var arr: [i32; 1.(I.F)(2)]; // CHECK:STDOUT: // CHECK:STDOUT: fn @F.2[@impl.%self.loc16_8.2: i32](@impl.%other.loc16_19.2: i32) -> i32 = "int.sadd"; // CHECK:STDOUT: +// CHECK:STDOUT: specific @I.%F.decl(constants.%Self) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: @I.%Self.ref.loc12_14 => constants.%Self +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/function/builtin/no_prelude/call_from_operator.carbon b/toolchain/check/testdata/function/builtin/no_prelude/call_from_operator.carbon index 1e9adc3897dc..8a9fa1fe2fa9 100644 --- a/toolchain/check/testdata/function/builtin/no_prelude/call_from_operator.carbon +++ b/toolchain/check/testdata/function/builtin/no_prelude/call_from_operator.carbon @@ -86,6 +86,11 @@ var arr: [i32; 1 + 2] = (3, 4, 3 + 4); // CHECK:STDOUT: fn @Op[@Add.%self.loc7_9.2: @Add.%Self.ref.loc7_15 (%Self)](@Add.%other.loc7_21.2: @Add.%Self.ref.loc7_15 (%Self)) -> %Self // CHECK:STDOUT: generic [@Add.%Self: %.2]; // CHECK:STDOUT: +// CHECK:STDOUT: specific @Add.%Op.decl(constants.%Self) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: @Add.%Self.ref.loc7_15 => constants.%Self +// CHECK:STDOUT: } +// CHECK:STDOUT: // CHECK:STDOUT: --- user.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { diff --git a/toolchain/check/testdata/function/generic/fail_todo_param_in_type.carbon b/toolchain/check/testdata/function/generic/fail_todo_param_in_type.carbon index 40ec90f4b23a..05e2fa5e0c27 100644 --- a/toolchain/check/testdata/function/generic/fail_todo_param_in_type.carbon +++ b/toolchain/check/testdata/function/generic/fail_todo_param_in_type.carbon @@ -58,3 +58,8 @@ fn F(N:! i32, a: [i32; N]*); // CHECK:STDOUT: fn @F(%N: i32, %a: ) // CHECK:STDOUT: generic [%N: i32]; // CHECK:STDOUT: +// CHECK:STDOUT: specific file.%F.decl(constants.%N) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: @F.%N => constants.%N +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/function/generic/no_prelude/fail_type_param_mismatch.carbon b/toolchain/check/testdata/function/generic/no_prelude/fail_type_param_mismatch.carbon index 7f074834f6d8..8a1d80259f81 100644 --- a/toolchain/check/testdata/function/generic/no_prelude/fail_type_param_mismatch.carbon +++ b/toolchain/check/testdata/function/generic/no_prelude/fail_type_param_mismatch.carbon @@ -54,3 +54,9 @@ fn F(T:! type, U:! type) { // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific file.%F.decl(constants.%T, constants.%U) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: @F.%T => constants.%T +// CHECK:STDOUT: @F.%U => constants.%U +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/function/generic/no_prelude/indirect_generic_type.carbon b/toolchain/check/testdata/function/generic/no_prelude/indirect_generic_type.carbon index 30b9b910b3f7..76c41a0bf73b 100644 --- a/toolchain/check/testdata/function/generic/no_prelude/indirect_generic_type.carbon +++ b/toolchain/check/testdata/function/generic/no_prelude/indirect_generic_type.carbon @@ -50,3 +50,10 @@ fn F(T:! type, p: T**) -> T* { // CHECK:STDOUT: return %.loc12_10.2 // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific file.%F.decl(constants.%T) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: @F.%T => constants.%T +// CHECK:STDOUT: file.%.loc11_20 => constants.%.1 +// CHECK:STDOUT: file.%.loc11_21 => constants.%.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/function/generic/no_prelude/type_param.carbon b/toolchain/check/testdata/function/generic/no_prelude/type_param.carbon index a2866b32e01c..c99b3f6d0b5b 100644 --- a/toolchain/check/testdata/function/generic/no_prelude/type_param.carbon +++ b/toolchain/check/testdata/function/generic/no_prelude/type_param.carbon @@ -49,3 +49,8 @@ fn F(T:! type) { // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific file.%F.decl(constants.%T) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: @F.%T => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/function/generic/no_prelude/type_param_scope.carbon b/toolchain/check/testdata/function/generic/no_prelude/type_param_scope.carbon index 493a397f9f87..e266a9375c12 100644 --- a/toolchain/check/testdata/function/generic/no_prelude/type_param_scope.carbon +++ b/toolchain/check/testdata/function/generic/no_prelude/type_param_scope.carbon @@ -47,3 +47,8 @@ fn F(T:! type, n: T) -> T { // CHECK:STDOUT: return %m.ref // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific file.%F.decl(constants.%T) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: @F.%T => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/function/generic/redeclare.carbon b/toolchain/check/testdata/function/generic/redeclare.carbon index afe5077bd043..67c079017ad9 100644 --- a/toolchain/check/testdata/function/generic/redeclare.carbon +++ b/toolchain/check/testdata/function/generic/redeclare.carbon @@ -145,6 +145,12 @@ fn F(U:! type, T:! type) -> U* { // CHECK:STDOUT: return %.loc7_14.2 // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific file.%F.decl.loc4(constants.%T) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: file.%T.loc4_6.2 => constants.%T +// CHECK:STDOUT: file.%.loc4 => constants.%.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: // CHECK:STDOUT: --- fail_different_return_type.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { @@ -198,6 +204,20 @@ fn F(U:! type, T:! type) -> U* { // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific file.%F.decl(constants.%T, constants.%U) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: @F.%T => constants.%T +// CHECK:STDOUT: @F.%U => constants.%U +// CHECK:STDOUT: file.%.loc4 => constants.%.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific file.%.decl(constants.%T, constants.%U) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: @.1.%T => constants.%T +// CHECK:STDOUT: @.1.%U => constants.%U +// CHECK:STDOUT: file.%.loc13 => constants.%.3 +// CHECK:STDOUT: } +// CHECK:STDOUT: // CHECK:STDOUT: --- fail_reorder.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { @@ -253,6 +273,20 @@ fn F(U:! type, T:! type) -> U* { // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific file.%F.decl(constants.%T.1, constants.%U.1) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: @F.%T => constants.%T.1 +// CHECK:STDOUT: @F.%U => constants.%U.1 +// CHECK:STDOUT: file.%.loc4 => constants.%.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific file.%.decl(constants.%U.2, constants.%T.2) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: @.1.%U => constants.%U.2 +// CHECK:STDOUT: @.1.%T => constants.%T.2 +// CHECK:STDOUT: file.%.loc13 => constants.%.3 +// CHECK:STDOUT: } +// CHECK:STDOUT: // CHECK:STDOUT: --- fail_rename.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { @@ -308,3 +342,17 @@ fn F(U:! type, T:! type) -> U* { // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific file.%F.decl(constants.%T.1, constants.%U.1) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: @F.%T => constants.%T.1 +// CHECK:STDOUT: @F.%U => constants.%U.1 +// CHECK:STDOUT: file.%.loc4 => constants.%.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific file.%.decl(constants.%U.2, constants.%T.2) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: @.1.%U => constants.%U.2 +// CHECK:STDOUT: @.1.%T => constants.%T.2 +// CHECK:STDOUT: file.%.loc13 => constants.%.3 +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/impl/compound.carbon b/toolchain/check/testdata/impl/compound.carbon index 110a5d37bd53..5097342ebd51 100644 --- a/toolchain/check/testdata/impl/compound.carbon +++ b/toolchain/check/testdata/impl/compound.carbon @@ -219,3 +219,12 @@ fn InstanceCallIndirect(p: i32*) { // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific @Simple.%F.decl(constants.%Self) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @Simple.%G.decl(constants.%Self) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: @Simple.%Self.ref => constants.%Self +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/impl/extend_impl.carbon b/toolchain/check/testdata/impl/extend_impl.carbon index 0148e9341ae1..6be6b8b79cf6 100644 --- a/toolchain/check/testdata/impl/extend_impl.carbon +++ b/toolchain/check/testdata/impl/extend_impl.carbon @@ -112,3 +112,7 @@ fn G(c: C) { // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific @HasF.%F.decl(constants.%Self) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/impl/fail_call_invalid.carbon b/toolchain/check/testdata/impl/fail_call_invalid.carbon index be616325efc4..d597c293cd64 100644 --- a/toolchain/check/testdata/impl/fail_call_invalid.carbon +++ b/toolchain/check/testdata/impl/fail_call_invalid.carbon @@ -117,3 +117,8 @@ fn InstanceCall(n: i32) { // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific @Simple.%G.decl(constants.%Self) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: @Simple.%Self.ref => constants.%Self +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/impl/fail_extend_impl_forall.carbon b/toolchain/check/testdata/impl/fail_extend_impl_forall.carbon index 2a383b9cbf84..9b087c625f79 100644 --- a/toolchain/check/testdata/impl/fail_extend_impl_forall.carbon +++ b/toolchain/check/testdata/impl/fail_extend_impl_forall.carbon @@ -28,7 +28,7 @@ class C { // CHECK:STDOUT: %GenericInterface.type: type = generic_interface_type @GenericInterface [template] // CHECK:STDOUT: %.1: type = tuple_type () [template] // CHECK:STDOUT: %GenericInterface: %GenericInterface.type = struct_value () [template] -// CHECK:STDOUT: %.2: type = interface_type @GenericInterface, (%T) [symbolic] +// CHECK:STDOUT: %.2: type = interface_type @GenericInterface, file.%GenericInterface.decl(%T) [symbolic] // CHECK:STDOUT: %Self: %.2 = bind_symbolic_name Self 1 [symbolic] // CHECK:STDOUT: %F.type.1: type = fn_type @F.1 [template] // CHECK:STDOUT: %F.1: %F.type.1 = struct_value () [template] @@ -110,3 +110,18 @@ class C { // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific file.%GenericInterface.decl(constants.%T) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: file.%T.loc11_28.2 => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @GenericInterface.%F.decl(constants.%T, constants.%Self) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: @GenericInterface.%T.ref => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @impl.%F.decl(constants.%T) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: @impl.%T.ref => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/impl/fail_extend_partially_defined_interface.carbon b/toolchain/check/testdata/impl/fail_extend_partially_defined_interface.carbon index 88dccc80511a..1d1f74883b7d 100644 --- a/toolchain/check/testdata/impl/fail_extend_partially_defined_interface.carbon +++ b/toolchain/check/testdata/impl/fail_extend_partially_defined_interface.carbon @@ -62,3 +62,7 @@ interface I { // CHECK:STDOUT: has_error // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific @I.%C.decl(constants.%Self) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/impl/fail_impl_as_scope.carbon b/toolchain/check/testdata/impl/fail_impl_as_scope.carbon index 8724b532dcce..5525f4fbb4ce 100644 --- a/toolchain/check/testdata/impl/fail_impl_as_scope.carbon +++ b/toolchain/check/testdata/impl/fail_impl_as_scope.carbon @@ -75,3 +75,7 @@ impl as Simple { // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific @Simple.%F.decl(constants.%Self) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/impl/fail_impl_bad_assoc_fn.carbon b/toolchain/check/testdata/impl/fail_impl_bad_assoc_fn.carbon index 8c59808a3a5e..ca917fd270e6 100644 --- a/toolchain/check/testdata/impl/fail_impl_bad_assoc_fn.carbon +++ b/toolchain/check/testdata/impl/fail_impl_bad_assoc_fn.carbon @@ -887,3 +887,21 @@ class SelfNestedBadReturnType { // CHECK:STDOUT: // CHECK:STDOUT: fn @F.15(@impl.15.%x.loc212_10.2: %.26) -> %.21; // CHECK:STDOUT: +// CHECK:STDOUT: specific @I.%F.decl(constants.%Self.1) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @J.%F.decl(constants.%Self.2) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @SelfNested.%F.decl(constants.%Self.3) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: @SelfNested.%Self.ref.loc188_12 => constants.%Self.3 +// CHECK:STDOUT: @SelfNested.%.loc188_16.3 => constants.%.10 +// CHECK:STDOUT: => +// CHECK:STDOUT: @SelfNested.%.loc188_37 => constants.%.11 +// CHECK:STDOUT: @SelfNested.%.loc188_38.2 => constants.%.13 +// CHECK:STDOUT: @SelfNested.%.loc188_52 => constants.%.15 +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/impl/impl_as.carbon b/toolchain/check/testdata/impl/impl_as.carbon index a73ea5a710e6..a4451c4bd997 100644 --- a/toolchain/check/testdata/impl/impl_as.carbon +++ b/toolchain/check/testdata/impl/impl_as.carbon @@ -96,3 +96,7 @@ class C { // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific @Simple.%F.decl(constants.%Self) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/impl/impl_forall.carbon b/toolchain/check/testdata/impl/impl_forall.carbon index 964b60290051..c770d28591d6 100644 --- a/toolchain/check/testdata/impl/impl_forall.carbon +++ b/toolchain/check/testdata/impl/impl_forall.carbon @@ -77,3 +77,11 @@ impl forall [T:! type] T as Simple { // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific @Simple.%F.decl(constants.%Self) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @impl.%F.decl(constants.%T) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/impl/lookup/alias.carbon b/toolchain/check/testdata/impl/lookup/alias.carbon index e1e5d6836e9c..153a9063d7d0 100644 --- a/toolchain/check/testdata/impl/lookup/alias.carbon +++ b/toolchain/check/testdata/impl/lookup/alias.carbon @@ -118,3 +118,7 @@ fn G(c: C) { // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific @HasF.%F.decl(constants.%Self) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/impl/lookup/fail_alias_impl_not_found.carbon b/toolchain/check/testdata/impl/lookup/fail_alias_impl_not_found.carbon index eb4a8cf98db6..db4f8c957fd8 100644 --- a/toolchain/check/testdata/impl/lookup/fail_alias_impl_not_found.carbon +++ b/toolchain/check/testdata/impl/lookup/fail_alias_impl_not_found.carbon @@ -96,3 +96,7 @@ fn F(c: C) { // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific @I.%F.decl(constants.%Self) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/impl/lookup/fail_todo_undefined_impl.carbon b/toolchain/check/testdata/impl/lookup/fail_todo_undefined_impl.carbon index 93f5aeb8a89a..e0dca3271477 100644 --- a/toolchain/check/testdata/impl/lookup/fail_todo_undefined_impl.carbon +++ b/toolchain/check/testdata/impl/lookup/fail_todo_undefined_impl.carbon @@ -124,3 +124,7 @@ impl C as I { // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific @I.%F.decl(constants.%Self) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/impl/lookup/import.carbon b/toolchain/check/testdata/impl/lookup/import.carbon index d776b1392b80..b31fcdc80485 100644 --- a/toolchain/check/testdata/impl/lookup/import.carbon +++ b/toolchain/check/testdata/impl/lookup/import.carbon @@ -96,6 +96,10 @@ fn G(c: Impl.C) { // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific @HasF.%F.decl(constants.%Self) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: } +// CHECK:STDOUT: // CHECK:STDOUT: --- use.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { diff --git a/toolchain/check/testdata/impl/lookup/instance_method.carbon b/toolchain/check/testdata/impl/lookup/instance_method.carbon index bcdc189de8c4..653dd72459b4 100644 --- a/toolchain/check/testdata/impl/lookup/instance_method.carbon +++ b/toolchain/check/testdata/impl/lookup/instance_method.carbon @@ -142,3 +142,8 @@ fn F(c: C) -> i32 { // CHECK:STDOUT: return %.loc24_15.2 // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific @I.%F.decl(constants.%Self) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: @I.%Self.ref => constants.%Self +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/impl/lookup/no_prelude/import.carbon b/toolchain/check/testdata/impl/lookup/no_prelude/import.carbon index 347dadd6ed4f..ba7b3105292d 100644 --- a/toolchain/check/testdata/impl/lookup/no_prelude/import.carbon +++ b/toolchain/check/testdata/impl/lookup/no_prelude/import.carbon @@ -93,6 +93,10 @@ fn G(c: Impl.C) { // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific @HasF.%F.decl(constants.%Self) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: } +// CHECK:STDOUT: // CHECK:STDOUT: --- use.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { diff --git a/toolchain/check/testdata/impl/no_prelude/basic.carbon b/toolchain/check/testdata/impl/no_prelude/basic.carbon index fb28ac8afcdc..5cf80e98602f 100644 --- a/toolchain/check/testdata/impl/no_prelude/basic.carbon +++ b/toolchain/check/testdata/impl/no_prelude/basic.carbon @@ -81,3 +81,7 @@ impl C as Simple { // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific @Simple.%F.decl(constants.%Self) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/impl/no_prelude/import_self.carbon b/toolchain/check/testdata/impl/no_prelude/import_self.carbon index 3fe431134afb..267cd4e80d83 100644 --- a/toolchain/check/testdata/impl/no_prelude/import_self.carbon +++ b/toolchain/check/testdata/impl/no_prelude/import_self.carbon @@ -78,6 +78,11 @@ fn F(x: (), y: ()) -> () { // CHECK:STDOUT: fn @Op[@Add.%self.loc5_9.2: @Add.%Self.ref.loc5_15 (%Self)](@Add.%other.loc5_21.2: @Add.%Self.ref.loc5_15 (%Self)) -> %Self // CHECK:STDOUT: generic [@Add.%Self: %.1]; // CHECK:STDOUT: +// CHECK:STDOUT: specific @Add.%Op.decl(constants.%Self) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: @Add.%Self.ref.loc5_15 => constants.%Self +// CHECK:STDOUT: } +// CHECK:STDOUT: // CHECK:STDOUT: --- b.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { diff --git a/toolchain/check/testdata/impl/no_prelude/self_in_class.carbon b/toolchain/check/testdata/impl/no_prelude/self_in_class.carbon index b5cbd8724e78..c1b1319b074f 100644 --- a/toolchain/check/testdata/impl/no_prelude/self_in_class.carbon +++ b/toolchain/check/testdata/impl/no_prelude/self_in_class.carbon @@ -107,3 +107,8 @@ class A { // CHECK:STDOUT: return %.loc21_34 to @impl.%return.var // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific @DefaultConstructible.%Make.decl(constants.%Self) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: @DefaultConstructible.%Self.ref => constants.%Self +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/impl/no_prelude/self_in_signature.carbon b/toolchain/check/testdata/impl/no_prelude/self_in_signature.carbon index ebf60e7a25b0..f8e10275a85c 100644 --- a/toolchain/check/testdata/impl/no_prelude/self_in_signature.carbon +++ b/toolchain/check/testdata/impl/no_prelude/self_in_signature.carbon @@ -275,3 +275,17 @@ impl D as SelfNested { // CHECK:STDOUT: // CHECK:STDOUT: fn @F.6(@impl.4.%x.loc36_8.2: %.22); // CHECK:STDOUT: +// CHECK:STDOUT: specific @UseSelf.%F.decl(constants.%Self.1) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: @UseSelf.%Self.ref.loc12_14 => constants.%Self.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @SelfNested.%F.decl(constants.%Self.2) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: @SelfNested.%Self.ref.loc28_12 => constants.%Self.2 +// CHECK:STDOUT: @SelfNested.%.loc28_16.3 => constants.%.10 +// CHECK:STDOUT: => +// CHECK:STDOUT: @SelfNested.%.loc28_36 => constants.%.11 +// CHECK:STDOUT: @SelfNested.%.loc28_37.2 => constants.%.13 +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/interface/fail_todo_define_default_fn_inline.carbon b/toolchain/check/testdata/interface/fail_todo_define_default_fn_inline.carbon index a8880bf523d7..23ff00f34034 100644 --- a/toolchain/check/testdata/interface/fail_todo_define_default_fn_inline.carbon +++ b/toolchain/check/testdata/interface/fail_todo_define_default_fn_inline.carbon @@ -95,3 +95,11 @@ interface Interface { // CHECK:STDOUT: fn @G(@Interface.%a.loc21_16.2: i32, @Interface.%b.loc21_24.2: i32) -> i32 = "int.sadd" // CHECK:STDOUT: generic [@Interface.%Self: %.1]; // CHECK:STDOUT: +// CHECK:STDOUT: specific @Interface.%F.decl(constants.%Self) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @Interface.%G.decl(constants.%Self) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/interface/fail_todo_define_default_fn_out_of_line.carbon b/toolchain/check/testdata/interface/fail_todo_define_default_fn_out_of_line.carbon index 03d44dd4915f..b8f711781011 100644 --- a/toolchain/check/testdata/interface/fail_todo_define_default_fn_out_of_line.carbon +++ b/toolchain/check/testdata/interface/fail_todo_define_default_fn_out_of_line.carbon @@ -141,3 +141,11 @@ fn Interface.G(a: i32, b: i32) -> i32 = "int.sadd"; // CHECK:STDOUT: // CHECK:STDOUT: fn @.2(%a: i32, %b: i32) -> i32 = "int.sadd"; // CHECK:STDOUT: +// CHECK:STDOUT: specific @Interface.%F.decl(constants.%Self) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @Interface.%G.decl(constants.%Self) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/interface/no_prelude/as_type_of_type.carbon b/toolchain/check/testdata/interface/no_prelude/as_type_of_type.carbon index 56a74642efdb..4019d8f82119 100644 --- a/toolchain/check/testdata/interface/no_prelude/as_type_of_type.carbon +++ b/toolchain/check/testdata/interface/no_prelude/as_type_of_type.carbon @@ -57,3 +57,8 @@ fn F(T:! Empty) { // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific file.%F.decl(constants.%T) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: @F.%T => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/interface/no_prelude/basic.carbon b/toolchain/check/testdata/interface/no_prelude/basic.carbon index 43a1a6d443f6..6158e1a8ae97 100644 --- a/toolchain/check/testdata/interface/no_prelude/basic.carbon +++ b/toolchain/check/testdata/interface/no_prelude/basic.carbon @@ -63,3 +63,7 @@ interface ForwardDeclared { // CHECK:STDOUT: fn @F() // CHECK:STDOUT: generic [@ForwardDeclared.%Self: %.2]; // CHECK:STDOUT: +// CHECK:STDOUT: specific @ForwardDeclared.%F.decl(constants.%Self.2) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/interface/no_prelude/default_fn.carbon b/toolchain/check/testdata/interface/no_prelude/default_fn.carbon index 379b338fdb1f..6c8c7d877ed1 100644 --- a/toolchain/check/testdata/interface/no_prelude/default_fn.carbon +++ b/toolchain/check/testdata/interface/no_prelude/default_fn.carbon @@ -104,3 +104,7 @@ class C { // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific @I.%F.decl(constants.%Self) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/interface/no_prelude/fail_add_member_outside_definition.carbon b/toolchain/check/testdata/interface/no_prelude/fail_add_member_outside_definition.carbon index 45b6df498749..0b4dc8bd8c36 100644 --- a/toolchain/check/testdata/interface/no_prelude/fail_add_member_outside_definition.carbon +++ b/toolchain/check/testdata/interface/no_prelude/fail_add_member_outside_definition.carbon @@ -101,3 +101,15 @@ interface Outer { // CHECK:STDOUT: fn @F.2() // CHECK:STDOUT: generic [@Outer.%Self: %.3]; // CHECK:STDOUT: +// CHECK:STDOUT: specific @Outer.%Inner.decl(constants.%Self.2) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @Inner.%.decl(constants.%Self.2, constants.%Self.3) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @Outer.%F.decl(constants.%Self.2) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/interface/no_prelude/fail_generic_redeclaration.carbon b/toolchain/check/testdata/interface/no_prelude/fail_generic_redeclaration.carbon index ce50b4cbaef1..70a2494cb11e 100644 --- a/toolchain/check/testdata/interface/no_prelude/fail_generic_redeclaration.carbon +++ b/toolchain/check/testdata/interface/no_prelude/fail_generic_redeclaration.carbon @@ -45,7 +45,7 @@ interface DifferentParams(T:! ()) {} // CHECK:STDOUT: %.type.1: type = generic_interface_type @.1 [template] // CHECK:STDOUT: %.2: type = tuple_type () [template] // CHECK:STDOUT: %.3: %.type.1 = struct_value () [template] -// CHECK:STDOUT: %.4: type = interface_type @.1, (%T.1) [symbolic] +// CHECK:STDOUT: %.4: type = interface_type @.1, file.%.decl.loc19(%T.1) [symbolic] // CHECK:STDOUT: %Self.1: %.4 = bind_symbolic_name Self 1 [symbolic] // CHECK:STDOUT: %Generic.type: type = generic_interface_type @Generic [template] // CHECK:STDOUT: %Generic: %Generic.type = struct_value () [template] @@ -56,7 +56,7 @@ interface DifferentParams(T:! ()) {} // CHECK:STDOUT: %T.2: %.2 = bind_symbolic_name T 0 [symbolic] // CHECK:STDOUT: %.type.2: type = generic_interface_type @.3 [template] // CHECK:STDOUT: %.6: %.type.2 = struct_value () [template] -// CHECK:STDOUT: %.7: type = interface_type @.3, (%T.2) [symbolic] +// CHECK:STDOUT: %.7: type = interface_type @.3, file.%.decl.loc38(%T.2) [symbolic] // CHECK:STDOUT: %Self.3: %.7 = bind_symbolic_name Self 1 [symbolic] // CHECK:STDOUT: } // CHECK:STDOUT: @@ -122,3 +122,23 @@ interface DifferentParams(T:! ()) {} // CHECK:STDOUT: witness = () // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific file.%.decl.loc19(constants.%T.1) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: file.%T.loc19_22.2 => constants.%T.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific file.%Generic.decl(constants.%T.1) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: file.%T.loc21_19.2 => constants.%T.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific file.%DifferentParams.decl(constants.%T.1) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: file.%T.loc31_27.2 => constants.%T.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific file.%.decl.loc38(constants.%T.2) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: file.%T.loc38_27.2 => constants.%T.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/interface/no_prelude/fail_lookup_undefined.carbon b/toolchain/check/testdata/interface/no_prelude/fail_lookup_undefined.carbon index 861dab742c61..397d763a610a 100644 --- a/toolchain/check/testdata/interface/no_prelude/fail_lookup_undefined.carbon +++ b/toolchain/check/testdata/interface/no_prelude/fail_lookup_undefined.carbon @@ -113,3 +113,11 @@ interface BeingDefined { // CHECK:STDOUT: fn @.2() // CHECK:STDOUT: generic [@BeingDefined.%Self: %.4]; // CHECK:STDOUT: +// CHECK:STDOUT: specific @BeingDefined.%H.decl(constants.%Self) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @BeingDefined.%.decl(constants.%Self) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/interface/no_prelude/fail_member_lookup.carbon b/toolchain/check/testdata/interface/no_prelude/fail_member_lookup.carbon index 20a7b938e731..0e5a0e38066f 100644 --- a/toolchain/check/testdata/interface/no_prelude/fail_member_lookup.carbon +++ b/toolchain/check/testdata/interface/no_prelude/fail_member_lookup.carbon @@ -80,3 +80,7 @@ fn F() { // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific @Interface.%F.decl(constants.%Self) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/interface/no_prelude/fail_redeclare_member.carbon b/toolchain/check/testdata/interface/no_prelude/fail_redeclare_member.carbon index 9030b048b359..7574bae6a739 100644 --- a/toolchain/check/testdata/interface/no_prelude/fail_redeclare_member.carbon +++ b/toolchain/check/testdata/interface/no_prelude/fail_redeclare_member.carbon @@ -58,3 +58,11 @@ interface Interface { // CHECK:STDOUT: fn @.1() // CHECK:STDOUT: generic [@Interface.%Self: %.1]; // CHECK:STDOUT: +// CHECK:STDOUT: specific @Interface.%F.decl(constants.%Self) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @Interface.%.decl(constants.%Self) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/interface/no_prelude/fail_todo_facet_lookup.carbon b/toolchain/check/testdata/interface/no_prelude/fail_todo_facet_lookup.carbon index 8aff5758f337..6a0f8ef9d842 100644 --- a/toolchain/check/testdata/interface/no_prelude/fail_todo_facet_lookup.carbon +++ b/toolchain/check/testdata/interface/no_prelude/fail_todo_facet_lookup.carbon @@ -95,3 +95,17 @@ fn CallFacet(T:! Interface, x: T) { // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific @Interface.%F.decl(constants.%Self) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific file.%CallStatic.decl(constants.%T) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: @CallStatic.%T => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific file.%CallFacet.decl(constants.%T) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: @CallFacet.%T => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/interface/no_prelude/fail_todo_generic_default_fn.carbon b/toolchain/check/testdata/interface/no_prelude/fail_todo_generic_default_fn.carbon index 332e08813865..c1513ebd6bab 100644 --- a/toolchain/check/testdata/interface/no_prelude/fail_todo_generic_default_fn.carbon +++ b/toolchain/check/testdata/interface/no_prelude/fail_todo_generic_default_fn.carbon @@ -28,7 +28,7 @@ fn I(T:! type).F[self: Self]() -> Self { return self; } // CHECK:STDOUT: %I.type: type = generic_interface_type @I [template] // CHECK:STDOUT: %.1: type = tuple_type () [template] // CHECK:STDOUT: %I: %I.type = struct_value () [template] -// CHECK:STDOUT: %.2: type = interface_type @I, (%T) [symbolic] +// CHECK:STDOUT: %.2: type = interface_type @I, file.%I.decl(%T) [symbolic] // CHECK:STDOUT: %Self: %.2 = bind_symbolic_name Self 1 [symbolic] // CHECK:STDOUT: %F.type: type = fn_type @F [template] // CHECK:STDOUT: %F: %F.type = struct_value () [template] @@ -49,13 +49,13 @@ fn I(T:! type).F[self: Self]() -> Self { return self; } // CHECK:STDOUT: %.decl: %.type = fn_decl @.1 [template = constants.%.5] { // CHECK:STDOUT: %T.loc22_6.1: type = param T // CHECK:STDOUT: %T.loc22_6.2: type = bind_symbolic_name T 0, %T.loc22_6.1 [symbolic = %T.loc22_6.2 (constants.%T)] -// CHECK:STDOUT: %.loc22_24.1: (%.2) = specific_constant @I.%Self, (constants.%T) [symbolic = %.loc22_24.1 (constants.%Self)] +// CHECK:STDOUT: %.loc22_24.1: (%.2) = specific_constant @I.%Self, %I.decl(constants.%T) [symbolic = %.loc22_24.1 (constants.%Self)] // CHECK:STDOUT: %Self.ref.loc22_24: (%.2) = name_ref Self, %.loc22_24.1 [symbolic = %.loc22_24.1 (constants.%Self)] // CHECK:STDOUT: %.loc22_24.2: type = facet_type_access %Self.ref.loc22_24 [symbolic = %.loc22_24.1 (constants.%Self)] // CHECK:STDOUT: %.loc22_24.3: type = converted %Self.ref.loc22_24, %.loc22_24.2 [symbolic = %.loc22_24.1 (constants.%Self)] // CHECK:STDOUT: %self.loc22_18.1: file.%.loc22_24.1 (%Self) = param self // CHECK:STDOUT: @.1.%self: file.%.loc22_24.1 (%Self) = bind_name self, %self.loc22_18.1 -// CHECK:STDOUT: %.loc22_35.1: (%.2) = specific_constant @I.%Self, (constants.%T) [symbolic = %.loc22_24.1 (constants.%Self)] +// CHECK:STDOUT: %.loc22_35.1: (%.2) = specific_constant @I.%Self, %I.decl(constants.%T) [symbolic = %.loc22_24.1 (constants.%Self)] // CHECK:STDOUT: %Self.ref.loc22_35: (%.2) = name_ref Self, %.loc22_35.1 [symbolic = %.loc22_24.1 (constants.%Self)] // CHECK:STDOUT: %.loc22_35.2: type = facet_type_access %Self.ref.loc22_35 [symbolic = %.loc22_24.1 (constants.%Self)] // CHECK:STDOUT: %.loc22_35.3: type = converted %Self.ref.loc22_35, %.loc22_35.2 [symbolic = %.loc22_24.1 (constants.%Self)] @@ -67,13 +67,13 @@ fn I(T:! type).F[self: Self]() -> Self { return self; } // CHECK:STDOUT: generic [file.%T.loc11_13.2: type] { // CHECK:STDOUT: %Self: %.2 = bind_symbolic_name Self 1 [symbolic = constants.%Self] // CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [template = constants.%F] { -// CHECK:STDOUT: %.loc13_14.1: %.2 = specific_constant %Self, (constants.%T) [symbolic = %.loc13_14.1 (constants.%Self)] +// CHECK:STDOUT: %.loc13_14.1: %.2 = specific_constant %Self, file.%I.decl(constants.%T) [symbolic = %.loc13_14.1 (constants.%Self)] // CHECK:STDOUT: %Self.ref.loc13_14: %.2 = name_ref Self, %.loc13_14.1 [symbolic = %.loc13_14.1 (constants.%Self)] // CHECK:STDOUT: %.loc13_14.2: type = facet_type_access %Self.ref.loc13_14 [symbolic = %.loc13_14.1 (constants.%Self)] // CHECK:STDOUT: %.loc13_14.3: type = converted %Self.ref.loc13_14, %.loc13_14.2 [symbolic = %.loc13_14.1 (constants.%Self)] // CHECK:STDOUT: %self.loc13_8.1: @I.%.loc13_14.1 (%Self) = param self // CHECK:STDOUT: %self.loc13_8.2: @I.%.loc13_14.1 (%Self) = bind_name self, %self.loc13_8.1 -// CHECK:STDOUT: %.loc13_25.1: %.2 = specific_constant %Self, (constants.%T) [symbolic = %.loc13_14.1 (constants.%Self)] +// CHECK:STDOUT: %.loc13_25.1: %.2 = specific_constant %Self, file.%I.decl(constants.%T) [symbolic = %.loc13_14.1 (constants.%Self)] // CHECK:STDOUT: %Self.ref.loc13_25: %.2 = name_ref Self, %.loc13_25.1 [symbolic = %.loc13_14.1 (constants.%Self)] // CHECK:STDOUT: %.loc13_25.2: type = facet_type_access %Self.ref.loc13_25 [symbolic = %.loc13_14.1 (constants.%Self)] // CHECK:STDOUT: %.loc13_25.3: type = converted %Self.ref.loc13_25, %.loc13_25.2 [symbolic = %.loc13_14.1 (constants.%Self)] @@ -97,3 +97,25 @@ fn I(T:! type).F[self: Self]() -> Self { return self; } // CHECK:STDOUT: return %self.ref // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific file.%I.decl(constants.%T) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: file.%T.loc11_13.2 => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @I.%F.decl(constants.%T, constants.%Self) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: @I.%.loc13_14.1 => constants.%Self +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific file.%I.decl(file.%T.loc22_6.2) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: file.%T.loc11_13.2 => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific file.%.decl(constants.%T) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: file.%T.loc22_6.2 => constants.%T +// CHECK:STDOUT: => constants.%.2 +// CHECK:STDOUT: file.%.loc22_24.1 => constants.%Self +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/interface/no_prelude/fail_todo_modifiers.carbon b/toolchain/check/testdata/interface/no_prelude/fail_todo_modifiers.carbon index 2eae187451ae..85e6ddae23bc 100644 --- a/toolchain/check/testdata/interface/no_prelude/fail_todo_modifiers.carbon +++ b/toolchain/check/testdata/interface/no_prelude/fail_todo_modifiers.carbon @@ -69,3 +69,11 @@ interface Modifiers { // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific @Modifiers.%Final.decl(constants.%Self) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @Modifiers.%Default.decl(constants.%Self) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/interface/no_prelude/generic.carbon b/toolchain/check/testdata/interface/no_prelude/generic.carbon index b71c38bba05a..cf5154abd65a 100644 --- a/toolchain/check/testdata/interface/no_prelude/generic.carbon +++ b/toolchain/check/testdata/interface/no_prelude/generic.carbon @@ -65,22 +65,22 @@ fn G(T:! Generic(B)) { // CHECK:STDOUT: %Simple.type: type = generic_interface_type @Simple [template] // CHECK:STDOUT: %.1: type = tuple_type () [template] // CHECK:STDOUT: %Simple: %Simple.type = struct_value () [template] -// CHECK:STDOUT: %.2: type = interface_type @Simple, (%T.1) [symbolic] +// CHECK:STDOUT: %.2: type = interface_type @Simple, file.%Simple.decl(%T.1) [symbolic] // CHECK:STDOUT: %Self.1: %.2 = bind_symbolic_name Self 1 [symbolic] // CHECK:STDOUT: %X: type = class_type @X [template] // CHECK:STDOUT: %.3: type = struct_type {} [template] // CHECK:STDOUT: %WithAssocFn.type: type = generic_interface_type @WithAssocFn [template] // CHECK:STDOUT: %WithAssocFn: %WithAssocFn.type = struct_value () [template] -// CHECK:STDOUT: %.4: type = interface_type @WithAssocFn, (%T.1) [symbolic] +// CHECK:STDOUT: %.4: type = interface_type @WithAssocFn, file.%WithAssocFn.decl(%T.1) [symbolic] // CHECK:STDOUT: %Self.2: %.4 = bind_symbolic_name Self 1 [symbolic] // CHECK:STDOUT: %F.type.1: type = fn_type @F.1 [template] // CHECK:STDOUT: %F.1: %F.type.1 = struct_value () [template] // CHECK:STDOUT: %.5: type = assoc_entity_type @WithAssocFn, %F.type.1 [template] // CHECK:STDOUT: %.6: %.5 = assoc_entity element0, @WithAssocFn.%F.decl [template] // CHECK:STDOUT: %C: type = class_type @C [template] -// CHECK:STDOUT: %.7: type = interface_type @Simple, (%C) [template] +// CHECK:STDOUT: %.7: type = interface_type @Simple, file.%Simple.decl(%C) [template] // CHECK:STDOUT: %.8: = interface_witness () [template] -// CHECK:STDOUT: %.9: type = interface_type @WithAssocFn, (%C) [template] +// CHECK:STDOUT: %.9: type = interface_type @WithAssocFn, file.%WithAssocFn.decl(%C) [template] // CHECK:STDOUT: %F.type.2: type = fn_type @F.2 [template] // CHECK:STDOUT: %F.2: %F.type.2 = struct_value () [template] // CHECK:STDOUT: %.10: = interface_witness (%F.2) [template] @@ -237,6 +237,46 @@ fn G(T:! Generic(B)) { // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific file.%Simple.decl(constants.%T.1) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: file.%T.loc4_18.2 => constants.%T.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific file.%WithAssocFn.decl(constants.%T.1) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: file.%T.loc8_23.2 => constants.%T.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @WithAssocFn.%F.decl(constants.%T.1, constants.%Self.2) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific file.%Simple.decl(constants.%C) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: file.%T.loc4_18.2 => constants.%C +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific file.%WithAssocFn.decl(constants.%C) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: file.%T.loc8_23.2 => constants.%C +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific file.%WithImplicitArgs.decl(constants.%T.1, constants.%N) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: file.%T.loc22_28.2 => constants.%T.1 +// CHECK:STDOUT: file.%N.loc22_38.2 => constants.%N +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific file.%Receive.decl(constants.%T.2) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: @Receive.%T => constants.%T.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific file.%Pass.decl(constants.%T.2) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: @Pass.%T => constants.%T.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: // CHECK:STDOUT: --- fail_mismatched_args.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { @@ -244,16 +284,16 @@ fn G(T:! Generic(B)) { // CHECK:STDOUT: %Generic.type: type = generic_interface_type @Generic [template] // CHECK:STDOUT: %.1: type = tuple_type () [template] // CHECK:STDOUT: %Generic: %Generic.type = struct_value () [template] -// CHECK:STDOUT: %.2: type = interface_type @Generic, (%T.1) [symbolic] +// CHECK:STDOUT: %.2: type = interface_type @Generic, file.%Generic.decl(%T.1) [symbolic] // CHECK:STDOUT: %Self: %.2 = bind_symbolic_name Self 1 [symbolic] // CHECK:STDOUT: %A: type = class_type @A [template] // CHECK:STDOUT: %.3: type = struct_type {} [template] // CHECK:STDOUT: %B: type = class_type @B [template] -// CHECK:STDOUT: %.4: type = interface_type @Generic, (%A) [template] +// CHECK:STDOUT: %.4: type = interface_type @Generic, file.%Generic.decl(%A) [template] // CHECK:STDOUT: %T.2: %.4 = bind_symbolic_name T 0 [symbolic] // CHECK:STDOUT: %F.type: type = fn_type @F [template] // CHECK:STDOUT: %F: %F.type = struct_value () [template] -// CHECK:STDOUT: %.5: type = interface_type @Generic, (%B) [template] +// CHECK:STDOUT: %.5: type = interface_type @Generic, file.%Generic.decl(%B) [template] // CHECK:STDOUT: %T.3: %.5 = bind_symbolic_name T 0 [symbolic] // CHECK:STDOUT: %G.type: type = fn_type @G [template] // CHECK:STDOUT: %G: %G.type = struct_value () [template] @@ -324,3 +364,28 @@ fn G(T:! Generic(B)) { // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific file.%Generic.decl(constants.%T.1) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: file.%T.loc4_19.2 => constants.%T.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific file.%Generic.decl(constants.%A) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: file.%T.loc4_19.2 => constants.%A +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific file.%F.decl(constants.%T.2) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: @F.%T => constants.%T.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific file.%Generic.decl(constants.%B) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: file.%T.loc4_19.2 => constants.%B +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific file.%G.decl(constants.%T.3) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: @G.%T => constants.%T.3 +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/interface/no_prelude/generic_binding_after_assoc_const.carbon b/toolchain/check/testdata/interface/no_prelude/generic_binding_after_assoc_const.carbon index 2a689eb58cd6..a292b3edae83 100644 --- a/toolchain/check/testdata/interface/no_prelude/generic_binding_after_assoc_const.carbon +++ b/toolchain/check/testdata/interface/no_prelude/generic_binding_after_assoc_const.carbon @@ -71,3 +71,13 @@ interface I { // CHECK:STDOUT: fn @G(@I.%T.loc16_8.2: type) // CHECK:STDOUT: generic [@I.%Self: %.1, @I.%T.loc16_8.2: type]; // CHECK:STDOUT: +// CHECK:STDOUT: specific @I.%F.decl(constants.%Self, constants.%T) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: @I.%T.loc12_8.2 => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @I.%G.decl(constants.%Self, constants.%T) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: @I.%T.loc16_8.2 => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/interface/no_prelude/generic_import.carbon b/toolchain/check/testdata/interface/no_prelude/generic_import.carbon index 66f37982ee93..e993bfd00f58 100644 --- a/toolchain/check/testdata/interface/no_prelude/generic_import.carbon +++ b/toolchain/check/testdata/interface/no_prelude/generic_import.carbon @@ -34,7 +34,7 @@ impl C as AddWith(C) { // CHECK:STDOUT: %AddWith.type: type = generic_interface_type @AddWith [template] // CHECK:STDOUT: %.1: type = tuple_type () [template] // CHECK:STDOUT: %AddWith: %AddWith.type = struct_value () [template] -// CHECK:STDOUT: %.2: type = interface_type @AddWith, (%T) [symbolic] +// CHECK:STDOUT: %.2: type = interface_type @AddWith, file.%AddWith.decl(%T) [symbolic] // CHECK:STDOUT: %Self: %.2 = bind_symbolic_name Self 1 [symbolic] // CHECK:STDOUT: %F.type: type = fn_type @F [template] // CHECK:STDOUT: %F: %F.type = struct_value () [template] @@ -67,6 +67,15 @@ impl C as AddWith(C) { // CHECK:STDOUT: fn @F() // CHECK:STDOUT: generic [file.%T.loc4_19.2: type, @AddWith.%Self: %.2]; // CHECK:STDOUT: +// CHECK:STDOUT: specific file.%AddWith.decl(constants.%T) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: file.%T.loc4_19.2 => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @AddWith.%F.decl(constants.%T, constants.%Self) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: } +// CHECK:STDOUT: // CHECK:STDOUT: --- b.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { @@ -76,9 +85,9 @@ impl C as AddWith(C) { // CHECK:STDOUT: %.2: type = tuple_type () [template] // CHECK:STDOUT: %AddWith: %AddWith.type = struct_value () [template] // CHECK:STDOUT: %T: type = bind_symbolic_name T 0, [symbolic] -// CHECK:STDOUT: %.3: type = interface_type @AddWith, (%T) [symbolic] +// CHECK:STDOUT: %.3: type = interface_type @AddWith, (%T) [symbolic] // CHECK:STDOUT: %Self: %.3 = bind_symbolic_name Self 1 [symbolic] -// CHECK:STDOUT: %.4: type = interface_type @AddWith, (%C) [template] +// CHECK:STDOUT: %.4: type = interface_type @AddWith, (%C) [template] // CHECK:STDOUT: %F.type.1: type = fn_type @F.1 [template] // CHECK:STDOUT: %F.1: %F.type.1 = struct_value () [template] // CHECK:STDOUT: %F.type.2: type = fn_type @F.2 [template] @@ -138,3 +147,7 @@ impl C as AddWith(C) { // CHECK:STDOUT: // CHECK:STDOUT: fn @F.2(); // CHECK:STDOUT: +// CHECK:STDOUT: specific (constants.%T); +// CHECK:STDOUT: +// CHECK:STDOUT: specific (constants.%C); +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/interface/no_prelude/import.carbon b/toolchain/check/testdata/interface/no_prelude/import.carbon index 9ae96e4caa77..a4700b399618 100644 --- a/toolchain/check/testdata/interface/no_prelude/import.carbon +++ b/toolchain/check/testdata/interface/no_prelude/import.carbon @@ -132,6 +132,14 @@ var f: ForwardDeclared* = &f_ref.f; // CHECK:STDOUT: fn @F.2() // CHECK:STDOUT: generic [@ForwardDeclared.%Self: %.8]; // CHECK:STDOUT: +// CHECK:STDOUT: specific @Basic.%F.decl(constants.%Self.2) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @ForwardDeclared.%F.decl(constants.%Self.3) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: } +// CHECK:STDOUT: // CHECK:STDOUT: --- b.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { diff --git a/toolchain/check/testdata/interface/no_prelude/self.carbon b/toolchain/check/testdata/interface/no_prelude/self.carbon index 343b646a2caf..4bd56b166599 100644 --- a/toolchain/check/testdata/interface/no_prelude/self.carbon +++ b/toolchain/check/testdata/interface/no_prelude/self.carbon @@ -55,3 +55,8 @@ interface UseSelf { // CHECK:STDOUT: fn @F[@UseSelf.%self.loc12_8.2: @UseSelf.%Self.ref.loc12_14 (%Self)]() -> %Self // CHECK:STDOUT: generic [@UseSelf.%Self: %.1]; // CHECK:STDOUT: +// CHECK:STDOUT: specific @UseSelf.%F.decl(constants.%Self) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: @UseSelf.%Self.ref.loc12_14 => constants.%Self +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/interface/todo_define_not_default.carbon b/toolchain/check/testdata/interface/todo_define_not_default.carbon index fb737a742eee..9ecaf41feb5e 100644 --- a/toolchain/check/testdata/interface/todo_define_not_default.carbon +++ b/toolchain/check/testdata/interface/todo_define_not_default.carbon @@ -121,3 +121,11 @@ interface I { // CHECK:STDOUT: fn @G(@I.%a.loc14_8.2: i32, @I.%b.loc14_16.2: i32) -> i32 = "int.sadd" // CHECK:STDOUT: generic [@I.%Self: %.1]; // CHECK:STDOUT: +// CHECK:STDOUT: specific @I.%F.decl(constants.%Self) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @I.%G.decl(constants.%Self) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/namespace/fail_params.carbon b/toolchain/check/testdata/namespace/fail_params.carbon index 935d57d9290b..3e1ccf2f7f3b 100644 --- a/toolchain/check/testdata/namespace/fail_params.carbon +++ b/toolchain/check/testdata/namespace/fail_params.carbon @@ -101,3 +101,8 @@ fn D(T:! type).F() {} // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific file.%.decl(constants.%T) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: file.%T.loc39_6.2 => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/packages/no_prelude/fail_export_name_params.carbon b/toolchain/check/testdata/packages/no_prelude/fail_export_name_params.carbon index 2fbd83d252ca..a89ec94087c8 100644 --- a/toolchain/check/testdata/packages/no_prelude/fail_export_name_params.carbon +++ b/toolchain/check/testdata/packages/no_prelude/fail_export_name_params.carbon @@ -35,10 +35,10 @@ export C2(T:! type); // CHECK:STDOUT: %C1.type: type = generic_class_type @C1 [template] // CHECK:STDOUT: %.1: type = tuple_type () [template] // CHECK:STDOUT: %C1.1: %C1.type = struct_value () [template] -// CHECK:STDOUT: %C1.2: type = class_type @C1, (%T) [symbolic] +// CHECK:STDOUT: %C1.2: type = class_type @C1, file.%C1.decl(%T) [symbolic] // CHECK:STDOUT: %C2.type: type = generic_class_type @C2 [template] // CHECK:STDOUT: %C2.1: %C2.type = struct_value () [template] -// CHECK:STDOUT: %C2.2: type = class_type @C2, (%T) [symbolic] +// CHECK:STDOUT: %C2.2: type = class_type @C2, file.%C2.decl(%T) [symbolic] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: file { @@ -62,6 +62,16 @@ export C2(T:! type); // CHECK:STDOUT: class @C2 // CHECK:STDOUT: generic [file.%T.loc5_10.2: type]; // CHECK:STDOUT: +// CHECK:STDOUT: specific file.%C1.decl(constants.%T) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: file.%T.loc4_10.2 => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific file.%C2.decl(constants.%T) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: file.%T.loc5_10.2 => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: // CHECK:STDOUT: --- fail_b.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { @@ -69,10 +79,10 @@ export C2(T:! type); // CHECK:STDOUT: %.1: type = tuple_type () [template] // CHECK:STDOUT: %C1.1: %C1.type = struct_value () [template] // CHECK:STDOUT: %T: type = bind_symbolic_name T 0, [symbolic] -// CHECK:STDOUT: %C1.2: type = class_type @C1, (%T) [symbolic] +// CHECK:STDOUT: %C1.2: type = class_type @C1, (%T) [symbolic] // CHECK:STDOUT: %C2.type: type = generic_class_type @C2 [template] // CHECK:STDOUT: %C2.1: %C2.type = struct_value () [template] -// CHECK:STDOUT: %C2.2: type = class_type @C2, (%T) [symbolic] +// CHECK:STDOUT: %C2.2: type = class_type @C2, (%T) [symbolic] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { @@ -96,3 +106,5 @@ export C2(T:! type); // CHECK:STDOUT: // CHECK:STDOUT: class @C2; // CHECK:STDOUT: +// CHECK:STDOUT: specific (constants.%T); +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/return/fail_let_in_type.carbon b/toolchain/check/testdata/return/fail_let_in_type.carbon index f2f12489d50e..afda030a1a4d 100644 --- a/toolchain/check/testdata/return/fail_let_in_type.carbon +++ b/toolchain/check/testdata/return/fail_let_in_type.carbon @@ -61,3 +61,8 @@ fn FirstPerfectNumber() -> z { return 6; } // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific (constants.%y) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: => constants.%y +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/struct/import.carbon b/toolchain/check/testdata/struct/import.carbon index 52115d83f901..72f1147e2701 100644 --- a/toolchain/check/testdata/struct/import.carbon +++ b/toolchain/check/testdata/struct/import.carbon @@ -73,13 +73,13 @@ var c_bad: C({.a = 3, .b = 4}) = F(); // CHECK:STDOUT: %S: %.11 = bind_symbolic_name S 0 [symbolic] // CHECK:STDOUT: %C.type: type = generic_class_type @C [template] // CHECK:STDOUT: %C.1: %C.type = struct_value () [template] -// CHECK:STDOUT: %C.2: type = class_type @C, (%S) [symbolic] +// CHECK:STDOUT: %C.2: type = class_type @C, file.%C.decl(%S) [symbolic] // CHECK:STDOUT: %.12: type = struct_type {} [template] // CHECK:STDOUT: %.13: i32 = int_literal 1 [template] // CHECK:STDOUT: %.14: i32 = int_literal 2 [template] // CHECK:STDOUT: %.15: type = ptr_type %.11 [template] // CHECK:STDOUT: %struct.4: %.11 = struct_value (%.13, %.14) [template] -// CHECK:STDOUT: %C.3: type = class_type @C, (%struct.4) [template] +// CHECK:STDOUT: %C.3: type = class_type @C, file.%C.decl(%struct.4) [template] // CHECK:STDOUT: %F.type: type = fn_type @F [template] // CHECK:STDOUT: %F: %F.type = struct_value () [template] // CHECK:STDOUT: } @@ -189,6 +189,16 @@ var c_bad: C({.a = 3, .b = 4}) = F(); // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific file.%C.decl(constants.%S) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: file.%S.loc8_9.2 => constants.%S +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific file.%C.decl(constants.%struct.4) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: file.%S.loc8_9.2 => constants.%struct.4 +// CHECK:STDOUT: } +// CHECK:STDOUT: // CHECK:STDOUT: --- implicit.impl.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { @@ -208,12 +218,12 @@ var c_bad: C({.a = 3, .b = 4}) = F(); // CHECK:STDOUT: %.10: type = struct_type {} [template] // CHECK:STDOUT: %.11: type = struct_type {.a: i32, .b: i32} [template] // CHECK:STDOUT: %S: %.11 = bind_symbolic_name S 0, [symbolic] -// CHECK:STDOUT: %C.2: type = class_type @C, (%S) [symbolic] +// CHECK:STDOUT: %C.2: type = class_type @C, (%S) [symbolic] // CHECK:STDOUT: %.12: i32 = int_literal 1 [template] // CHECK:STDOUT: %.13: i32 = int_literal 2 [template] // CHECK:STDOUT: %.14: type = ptr_type %.11 [template] // CHECK:STDOUT: %struct: %.11 = struct_value (%.12, %.13) [template] -// CHECK:STDOUT: %C.3: type = class_type @C, (%struct) [template] +// CHECK:STDOUT: %C.3: type = class_type @C, (%struct) [template] // CHECK:STDOUT: %.15: type = ptr_type %.10 [template] // CHECK:STDOUT: %F.type: type = fn_type @F [template] // CHECK:STDOUT: %F: %F.type = struct_value () [template] @@ -327,6 +337,10 @@ var c_bad: C({.a = 3, .b = 4}) = F(); // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific (constants.%S); +// CHECK:STDOUT: +// CHECK:STDOUT: specific (constants.%struct); +// CHECK:STDOUT: // CHECK:STDOUT: --- fail_bad_type.impl.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { @@ -336,13 +350,13 @@ var c_bad: C({.a = 3, .b = 4}) = F(); // CHECK:STDOUT: %.2: type = struct_type {} [template] // CHECK:STDOUT: %.3: type = struct_type {.a: i32, .b: i32} [template] // CHECK:STDOUT: %S: %.3 = bind_symbolic_name S 0, [symbolic] -// CHECK:STDOUT: %C.2: type = class_type @C, (%S) [symbolic] +// CHECK:STDOUT: %C.2: type = class_type @C, (%S) [symbolic] // CHECK:STDOUT: %.4: i32 = int_literal 1 [template] // CHECK:STDOUT: %.5: i32 = int_literal 2 [template] // CHECK:STDOUT: %.6: type = struct_type {.c: i32, .d: i32} [template] // CHECK:STDOUT: %.7: type = ptr_type %.3 [template] // CHECK:STDOUT: %struct: %.3 = struct_value (%.4, %.5) [template] -// CHECK:STDOUT: %C.3: type = class_type @C, (%struct) [template] +// CHECK:STDOUT: %C.3: type = class_type @C, (%struct) [template] // CHECK:STDOUT: %F.type: type = fn_type @F [template] // CHECK:STDOUT: %F: %F.type = struct_value () [template] // CHECK:STDOUT: %.8: type = ptr_type %.2 [template] @@ -396,6 +410,10 @@ var c_bad: C({.a = 3, .b = 4}) = F(); // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific (constants.%S); +// CHECK:STDOUT: +// CHECK:STDOUT: specific (constants.%struct); +// CHECK:STDOUT: // CHECK:STDOUT: --- fail_bad_value.impl.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { @@ -405,17 +423,17 @@ var c_bad: C({.a = 3, .b = 4}) = F(); // CHECK:STDOUT: %.2: type = struct_type {} [template] // CHECK:STDOUT: %.3: type = struct_type {.a: i32, .b: i32} [template] // CHECK:STDOUT: %S: %.3 = bind_symbolic_name S 0, [symbolic] -// CHECK:STDOUT: %C.2: type = class_type @C, (%S) [symbolic] +// CHECK:STDOUT: %C.2: type = class_type @C, (%S) [symbolic] // CHECK:STDOUT: %.4: i32 = int_literal 3 [template] // CHECK:STDOUT: %.5: i32 = int_literal 4 [template] // CHECK:STDOUT: %.6: type = ptr_type %.3 [template] // CHECK:STDOUT: %struct.1: %.3 = struct_value (%.4, %.5) [template] -// CHECK:STDOUT: %C.3: type = class_type @C, (%struct.1) [template] +// CHECK:STDOUT: %C.3: type = class_type @C, (%struct.1) [template] // CHECK:STDOUT: %.7: type = ptr_type %.2 [template] // CHECK:STDOUT: %.8: i32 = int_literal 2 [template] // CHECK:STDOUT: %.9: i32 = int_literal 1 [template] // CHECK:STDOUT: %struct.2: %.3 = struct_value (%.9, %.8) [template] -// CHECK:STDOUT: %C.4: type = class_type @C, (%struct.2) [template] +// CHECK:STDOUT: %C.4: type = class_type @C, (%struct.2) [template] // CHECK:STDOUT: %F.type: type = fn_type @F [template] // CHECK:STDOUT: %F: %F.type = struct_value () [template] // CHECK:STDOUT: } @@ -470,3 +488,9 @@ var c_bad: C({.a = 3, .b = 4}) = F(); // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific (constants.%S); +// CHECK:STDOUT: +// CHECK:STDOUT: specific (constants.%struct.1); +// CHECK:STDOUT: +// CHECK:STDOUT: specific (constants.%struct.2); +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/tuples/import.carbon b/toolchain/check/testdata/tuples/import.carbon index d00aa3a782f5..704ec1e388fb 100644 --- a/toolchain/check/testdata/tuples/import.carbon +++ b/toolchain/check/testdata/tuples/import.carbon @@ -81,10 +81,10 @@ var c_bad: C((3, 4)) = F(); // CHECK:STDOUT: %X: %.9 = bind_symbolic_name X 0 [symbolic] // CHECK:STDOUT: %C.type: type = generic_class_type @C [template] // CHECK:STDOUT: %C.1: %C.type = struct_value () [template] -// CHECK:STDOUT: %C.2: type = class_type @C, (%X) [symbolic] +// CHECK:STDOUT: %C.2: type = class_type @C, file.%C.decl(%X) [symbolic] // CHECK:STDOUT: %.18: type = struct_type {} [template] // CHECK:STDOUT: %tuple.5: %.9 = tuple_value (%.15, %.16) [template] -// CHECK:STDOUT: %C.3: type = class_type @C, (%tuple.5) [template] +// CHECK:STDOUT: %C.3: type = class_type @C, file.%C.decl(%tuple.5) [template] // CHECK:STDOUT: %F.type: type = fn_type @F [template] // CHECK:STDOUT: %F: %F.type = struct_value () [template] // CHECK:STDOUT: } @@ -211,6 +211,16 @@ var c_bad: C((3, 4)) = F(); // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific file.%C.decl(constants.%X) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: file.%X.loc7_9.2 => constants.%X +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific file.%C.decl(constants.%tuple.5) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: file.%X.loc7_9.2 => constants.%tuple.5 +// CHECK:STDOUT: } +// CHECK:STDOUT: // CHECK:STDOUT: --- implicit.impl.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { @@ -233,11 +243,11 @@ var c_bad: C((3, 4)) = F(); // CHECK:STDOUT: %C.1: %C.type = struct_value () [template] // CHECK:STDOUT: %.14: type = struct_type {} [template] // CHECK:STDOUT: %X: %.8 = bind_symbolic_name X 0, [symbolic] -// CHECK:STDOUT: %C.2: type = class_type @C, (%X) [symbolic] +// CHECK:STDOUT: %C.2: type = class_type @C, (%X) [symbolic] // CHECK:STDOUT: %.15: i32 = int_literal 1 [template] // CHECK:STDOUT: %.16: i32 = int_literal 2 [template] // CHECK:STDOUT: %tuple: %.8 = tuple_value (%.15, %.16) [template] -// CHECK:STDOUT: %C.3: type = class_type @C, (%tuple) [template] +// CHECK:STDOUT: %C.3: type = class_type @C, (%tuple) [template] // CHECK:STDOUT: %.17: type = ptr_type %.14 [template] // CHECK:STDOUT: %F.type: type = fn_type @F [template] // CHECK:STDOUT: %F: %F.type = struct_value () [template] @@ -368,6 +378,10 @@ var c_bad: C((3, 4)) = F(); // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific (constants.%X); +// CHECK:STDOUT: +// CHECK:STDOUT: specific (constants.%tuple); +// CHECK:STDOUT: // CHECK:STDOUT: --- fail_bad_type.impl.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { @@ -377,14 +391,14 @@ var c_bad: C((3, 4)) = F(); // CHECK:STDOUT: %.2: type = struct_type {} [template] // CHECK:STDOUT: %.3: type = tuple_type (i32, i32) [template] // CHECK:STDOUT: %X: %.3 = bind_symbolic_name X 0, [symbolic] -// CHECK:STDOUT: %C.2: type = class_type @C, (%X) [symbolic] +// CHECK:STDOUT: %C.2: type = class_type @C, (%X) [symbolic] // CHECK:STDOUT: %.4: i32 = int_literal 1 [template] // CHECK:STDOUT: %.5: i32 = int_literal 2 [template] // CHECK:STDOUT: %.6: i32 = int_literal 3 [template] // CHECK:STDOUT: %.7: type = tuple_type (i32, i32, i32) [template] // CHECK:STDOUT: %.8: type = ptr_type %.3 [template] // CHECK:STDOUT: %tuple: %.3 = tuple_value (%.4, %.5) [template] -// CHECK:STDOUT: %C.3: type = class_type @C, (%tuple) [template] +// CHECK:STDOUT: %C.3: type = class_type @C, (%tuple) [template] // CHECK:STDOUT: %F.type: type = fn_type @F [template] // CHECK:STDOUT: %F: %F.type = struct_value () [template] // CHECK:STDOUT: %.9: type = ptr_type %.2 [template] @@ -439,6 +453,10 @@ var c_bad: C((3, 4)) = F(); // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific (constants.%X); +// CHECK:STDOUT: +// CHECK:STDOUT: specific (constants.%tuple); +// CHECK:STDOUT: // CHECK:STDOUT: --- fail_bad_value.impl.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { @@ -448,17 +466,17 @@ var c_bad: C((3, 4)) = F(); // CHECK:STDOUT: %.2: type = struct_type {} [template] // CHECK:STDOUT: %.3: type = tuple_type (i32, i32) [template] // CHECK:STDOUT: %X: %.3 = bind_symbolic_name X 0, [symbolic] -// CHECK:STDOUT: %C.2: type = class_type @C, (%X) [symbolic] +// CHECK:STDOUT: %C.2: type = class_type @C, (%X) [symbolic] // CHECK:STDOUT: %.4: i32 = int_literal 3 [template] // CHECK:STDOUT: %.5: i32 = int_literal 4 [template] // CHECK:STDOUT: %.6: type = ptr_type %.3 [template] // CHECK:STDOUT: %tuple.1: %.3 = tuple_value (%.4, %.5) [template] -// CHECK:STDOUT: %C.3: type = class_type @C, (%tuple.1) [template] +// CHECK:STDOUT: %C.3: type = class_type @C, (%tuple.1) [template] // CHECK:STDOUT: %.7: type = ptr_type %.2 [template] // CHECK:STDOUT: %.8: i32 = int_literal 2 [template] // CHECK:STDOUT: %.9: i32 = int_literal 1 [template] // CHECK:STDOUT: %tuple.2: %.3 = tuple_value (%.9, %.8) [template] -// CHECK:STDOUT: %C.4: type = class_type @C, (%tuple.2) [template] +// CHECK:STDOUT: %C.4: type = class_type @C, (%tuple.2) [template] // CHECK:STDOUT: %F.type: type = fn_type @F [template] // CHECK:STDOUT: %F: %F.type = struct_value () [template] // CHECK:STDOUT: } @@ -513,3 +531,9 @@ var c_bad: C((3, 4)) = F(); // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific (constants.%X); +// CHECK:STDOUT: +// CHECK:STDOUT: specific (constants.%tuple.1); +// CHECK:STDOUT: +// CHECK:STDOUT: specific (constants.%tuple.2); +// CHECK:STDOUT: diff --git a/toolchain/sem_ir/formatter.cpp b/toolchain/sem_ir/formatter.cpp index cbef76da237c..75c6dd8acec0 100644 --- a/toolchain/sem_ir/formatter.cpp +++ b/toolchain/sem_ir/formatter.cpp @@ -74,6 +74,10 @@ class Formatter { FormatFunction(FunctionId(i)); } + for (int i : llvm::seq(sem_ir_.generic_instances().size())) { + FormatSpecific(GenericInstanceId(i)); + } + // End-of-file newline. out_ << "\n"; } @@ -327,6 +331,55 @@ class Formatter { // blocks that don't duplicate portions of the generic body. } + auto FormatSpecificRegion(const Generic& generic, + const GenericInstance& specific, + GenericInstIndex::Region region, + llvm::StringRef region_name) -> void { + if (!specific.GetValueBlock(region).is_valid()) { + return; + } + + IndentLabel(); + out_ << region_name << ":\n"; + for (auto [generic_inst_id, specific_inst_id] : + llvm::zip(sem_ir_.inst_blocks().Get(generic.GetEvalBlock(region)), + sem_ir_.inst_blocks().Get(specific.GetValueBlock(region)))) { + Indent(); + FormatInstName(generic_inst_id); + out_ << " => "; + FormatInstName(specific_inst_id); + out_ << "\n"; + } + } + + auto FormatSpecific(GenericInstanceId id) -> void { + const auto& specific = sem_ir_.generic_instances().Get(id); + + out_ << "\n"; + + out_ << "specific "; + FormatSpecificName(id); + + // TODO: Remove once we stop forming generic specifics with no generic + // during import. + if (!specific.generic_id.is_valid()) { + out_ << ";\n"; + return; + } + out_ << " "; + + const auto& generic = sem_ir_.generics().Get(specific.generic_id); + + OpenBrace(); + FormatSpecificRegion(generic, specific, + GenericInstIndex::Region::Declaration, "declaration"); + FormatSpecificRegion(generic, specific, + GenericInstIndex::Region::Definition, "definition"); + CloseBrace(); + + out_ << "\n"; + } + auto FormatParamList(InstBlockId param_refs_id) -> void { llvm::ListSeparator sep; for (InstId param_id : sem_ir_.inst_blocks().Get(param_refs_id)) { @@ -816,10 +869,7 @@ class Formatter { out_ << ')'; } - auto FormatArg(GenericInstanceId id) -> void { - const auto& instance = sem_ir_.generic_instances().Get(id); - FormatArg(instance.args_id); - } + auto FormatArg(GenericInstanceId id) -> void { FormatSpecificName(id); } auto FormatArg(RealId id) -> void { // TODO: Format with a `.` when the exponent is near zero. @@ -880,6 +930,20 @@ class Formatter { auto FormatImplName(ImplId id) -> void { out_ << inst_namer_.GetNameFor(id); } + auto FormatSpecificName(GenericInstanceId id) -> void { + const auto& specific = sem_ir_.generic_instances().Get(id); + // TODO: We don't yet import generics properly, and instead form specifics + // with an invalid generic ID. In this case, just print a placeholder for + // now. Once import works, we can remove this code. + if (!specific.generic_id.is_valid()) { + out_ << ""; + } else { + const Generic& generic = sem_ir_.generics().Get(specific.generic_id); + FormatInstName(generic.decl_id); + } + FormatArg(specific.args_id); + } + auto FormatConstant(ConstantId id) -> void { if (!id.is_valid()) { out_ << ""; diff --git a/toolchain/sem_ir/generic.h b/toolchain/sem_ir/generic.h index 437a84eb61b3..6edd8243f81a 100644 --- a/toolchain/sem_ir/generic.h +++ b/toolchain/sem_ir/generic.h @@ -19,6 +19,15 @@ struct Generic : public Printable { out << "{decl: " << decl_id << ", bindings: " << bindings_id << "}"; } + // Returns the eval block for the specified region of the generic. This is a + // block of instructions that should be evaluated to compute the values and + // instructions needed by that region of the generic. + auto GetEvalBlock(GenericInstIndex::Region region) const -> InstBlockId { + return region == GenericInstIndex::Region::Declaration + ? decl_block_id + : definition_block_id; + } + // The following members always have values, and do not change throughout the // lifetime of the generic. @@ -36,9 +45,10 @@ struct Generic : public Printable { // The following members are set at the end of the corresponding region of the // generic. - // A block of instructions that should be evaluated to compute the values and - // instructions needed by the declaration of the generic. + // The eval block for the declaration region of the generic. InstBlockId decl_block_id = InstBlockId::Invalid; + // The eval block for the definition region of the generic. + InstBlockId definition_block_id = InstBlockId::Invalid; }; // Provides storage for generics. @@ -61,18 +71,29 @@ struct GenericInstance : Printable { out << "{generic: " << generic_id << ", args: " << args_id << "}"; } + // Returns the value block for this region of the specific. This is a block + // containing values and instructions produced by evaluating the corresponding + // eval block of the generic within the context of this specific. These are + // the constant values and types and the instantiated template-dependent + // instructions that are used in this region of the specific. + auto GetValueBlock(GenericInstIndex::Region region) const -> InstBlockId { + return region == GenericInstIndex::Region::Declaration + ? decl_block_id + : definition_block_id; + } + // The generic that this is an instance of. GenericId generic_id; // Argument values, corresponding to the bindings in `Generic::bindings_id`. InstBlockId args_id; - // The following members are set when the corresponding region of the generic - // instance is resolved. + // The following members are set when the corresponding region of the specific + // is resolved. - // The values and instructions produced by evaluating the decl block of the - // generic. These are the constant values and types and the instantiated - // template-dependent instructions needed by the declaration of this instance. + // The value block for the declaration region of the specific. InstBlockId decl_block_id = InstBlockId::Invalid; + // The value block for the definition region of the specific. + InstBlockId definition_block_id = InstBlockId::Invalid; }; // Provides storage for deduplicated instances of generics. @@ -99,6 +120,11 @@ class GenericInstanceStore : public Yaml::Printable { return generic_instances_.OutputYaml(); } + auto array_ref() const -> llvm::ArrayRef { + return generic_instances_.array_ref(); + } + auto size() const -> size_t { return generic_instances_.size(); } + private: // Context for hashing keys. class KeyContext;