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;