diff --git a/scripts/lldbinit.py b/scripts/lldbinit.py index ff1732ab9157..3102e17a9d87 100644 --- a/scripts/lldbinit.py +++ b/scripts/lldbinit.py @@ -86,6 +86,7 @@ Example usage: "constant": "SemIR::MakeConstantId", "constraint": "SemIR::MakeNamedConstraintId", "declared_facet_type": "SemIR::MakeDeclaredFacetTypeId", + "default_value": "SemIR::MakeDefaultValueId", "entity_name": "SemIR::MakeEntityNameId", "function": "SemIR::MakeFunctionId", "generated_function": "SemIR::MakeGeneratedFunctionId", diff --git a/toolchain/check/context.h b/toolchain/check/context.h index 5e2b46f1092b..b47aa9a90c22 100644 --- a/toolchain/check/context.h +++ b/toolchain/check/context.h @@ -401,6 +401,9 @@ class Context { auto declared_facet_types() -> SemIR::DeclaredFacetTypeStore& { return sem_ir().declared_facet_types(); } + auto default_values() -> SemIR::DefaultValueStore& { + return sem_ir().default_values(); + } auto identified_facet_types() -> SemIR::IdentifiedFacetTypeStore& { return sem_ir().identified_facet_types(); } diff --git a/toolchain/check/cpp/import.cpp b/toolchain/check/cpp/import.cpp index 0b1aa7950ad4..3e997c675cdf 100644 --- a/toolchain/check/cpp/import.cpp +++ b/toolchain/check/cpp/import.cpp @@ -1967,7 +1967,6 @@ static auto ImportFunction(Context& context, SemIR::LocId loc_id, .call_param_patterns_id = function_params_insts->call_param_patterns_id, .call_params_id = function_params_insts->call_params_id, - .call_param_default_values_id = SemIR::InstBlockId::Empty, .call_param_ranges = function_params_insts->param_ranges, .return_type_inst_id = function_params_insts->return_type_inst_id, .return_form_inst_id = function_params_insts->return_form_inst_id, diff --git a/toolchain/check/dump.cpp b/toolchain/check/dump.cpp index 3a16396a1809..636241e49455 100644 --- a/toolchain/check/dump.cpp +++ b/toolchain/check/dump.cpp @@ -64,18 +64,24 @@ LLVM_DUMP_METHOD static auto Dump(const Context& context, return SemIR::Dump(context.sem_ir(), const_id); } -LLVM_DUMP_METHOD static auto Dump(const Context& context, - SemIR::EntityNameId entity_name_id) - -> std::string { - return SemIR::Dump(context.sem_ir(), entity_name_id); -} - LLVM_DUMP_METHOD static auto Dump( const Context& context, SemIR::DeclaredFacetTypeId declared_facet_type_id) -> std::string { return SemIR::Dump(context.sem_ir(), declared_facet_type_id); } +LLVM_DUMP_METHOD static auto Dump(const Context& context, + SemIR::DefaultValueId value_id) + -> std::string { + return SemIR::Dump(context.sem_ir(), value_id); +} + +LLVM_DUMP_METHOD static auto Dump(const Context& context, + SemIR::EntityNameId entity_name_id) + -> std::string { + return SemIR::Dump(context.sem_ir(), entity_name_id); +} + LLVM_DUMP_METHOD static auto Dump(const Context& context, SemIR::FunctionId function_id) -> std::string { diff --git a/toolchain/check/full_pattern_stack.h b/toolchain/check/full_pattern_stack.h index ba30486e8ea3..7f6c6e080bee 100644 --- a/toolchain/check/full_pattern_stack.h +++ b/toolchain/check/full_pattern_stack.h @@ -81,6 +81,7 @@ class FullPatternStack { bind_name_stack_.PushArray(); var_pattern_stack_.PushArray(); next_var_index_stack_.push_back(-1); + unspecified_default_values_stack_.PushArray(); } // Marks the start of a new full-pattern for a name binding declaration. @@ -89,6 +90,7 @@ class FullPatternStack { bind_name_stack_.PushArray(); var_pattern_stack_.PushArray(); next_var_index_stack_.push_back(-1); + unspecified_default_values_stack_.PushArray(); } // Marks the start of a new full-pattern for a class `var` declaration. @@ -97,6 +99,7 @@ class FullPatternStack { bind_name_stack_.PushArray(); var_pattern_stack_.PushArray(); next_var_index_stack_.push_back(-1); + unspecified_default_values_stack_.PushArray(); } // Marks the start of the current parameterized entity's implicit parameter @@ -121,8 +124,6 @@ class FullPatternStack { CARBON_CHECK(kind_stack_.back() == Kind::NotInEitherParamList, "{0}", kind_stack_.back()); kind_stack_.back() = Kind::ExplicitParamList; - raw_default_values_stack_.PushArray(); - converted_default_values_stack_.PushArray(); } // Marks the end of the current parameterized entity's explicit parameter @@ -142,17 +143,14 @@ class FullPatternStack { // Marks the end of checking and pattern matching for the current // full-pattern. auto PopFullPattern() -> void { - auto kind = kind_stack_.pop_back_val(); + kind_stack_.pop_back(); bind_name_stack_.PopArray(); int index = next_var_index_stack_.pop_back_val(); CARBON_CHECK(index < 0 || static_cast(index) == var_pattern_stack_.PeekArray().size(), "`GetLocalVarStorage` not called for all var patterns"); var_pattern_stack_.PopArray(); - if (kind == Kind::ExplicitParamList) { - raw_default_values_stack_.PopArray(); - converted_default_values_stack_.PopArray(); - } + unspecified_default_values_stack_.PopArray(); } // Records that `name_id` was introduced by the current full-pattern. @@ -207,51 +205,18 @@ class FullPatternStack { kind_stack_.size()); } - // Adds the inst id for a default value for any subpattern in the - // full-pattern. We store these before the type of the pattern with this - // default value is known. Returns the index of the added instruction - // as a `DefaultValueId`. Note default values are only supported for - // explicit parameter lists. - auto AddRawDefaultValue(SemIR::InstId inst_id) -> SemIR::DefaultValueId { - CARBON_CHECK(kind_stack_.back() == Kind::ExplicitParamList); - return AddDefaultValue(inst_id, raw_default_values_stack_); + // Adds an unspecified pattern default value to the array at the top of the + // full pattern stack. We track these for possible later use in diagnostics. + auto AddUnspecifiedDefaultValue(SemIR::InstId inst_id) -> void { + unspecified_default_values_stack_.AppendToTop(inst_id); } - // Adds the inst id for a default value after conversion to the pattern type. - // Returns the index of the added instruction as a `DefaultValueId`. - auto AddConvertedDefaultValue(SemIR::InstId inst_id) - -> SemIR::DefaultValueId { - return AddDefaultValue(inst_id, converted_default_values_stack_); - } - - // Returns a reference to the array of raw default value inst ids at the top - // of the stack. Note default values are only supported for explicit parameter - // lists. - auto GetRawDefaultValues() -> llvm::ArrayRef { - return raw_default_values_stack_.empty() - ? llvm::ArrayRef() - : raw_default_values_stack_.PeekArray(); - } - - // Returns a reference to the array of type-converted default value inst ids - // at the top of the stack. - auto GetConvertedDefaultValues() -> llvm::ArrayRef { - return converted_default_values_stack_.empty() - ? llvm::ArrayRef() - : converted_default_values_stack_.PeekArray(); + // Returns the unspecified default values array at the top of the stack. + auto GetUnspecifiedDefaultValues() -> llvm::ArrayRef { + return unspecified_default_values_stack_.PeekArray(); } private: - // TODO: move default value InstIds to a value store and remove them from the - // pattern stack. - auto AddDefaultValue(SemIR::InstId inst_id, ArrayStack& stack) - -> SemIR::DefaultValueId { - auto index = - SemIR::DefaultValueId(static_cast(stack.PeekArray().size())); - stack.AppendToTop(inst_id); - return index; - } - LexicalLookup* lookup_; // The stack of pending full-patterns is organized as a struct of arrays, with @@ -283,16 +248,9 @@ class FullPatternStack { // of that frame are not ready for consumption. llvm::SmallVector next_var_index_stack_; - // The stack of instructions specifying default values for subpatterns - // within this full-pattern. These instructions are as they are written by - // the developer, with no type conversions applied. They are indexed by - // `DefaultValueId` values. - ArrayStack raw_default_values_stack_; - - // The stack of instructions for default values after the conversions to the - // type of the pattern have been applied. They are indexed by `DefaultValueId` - // values. - ArrayStack converted_default_values_stack_; + // For each full pattern we maintain a list of the InstIds of any + // unspecified default values, for use in diagnostics. + ArrayStack unspecified_default_values_stack_; }; } // namespace Carbon::Check diff --git a/toolchain/check/function.cpp b/toolchain/check/function.cpp index b5229c9af9c1..b71c723e0420 100644 --- a/toolchain/check/function.cpp +++ b/toolchain/check/function.cpp @@ -91,7 +91,6 @@ struct FunctionSignatureInsts { SemIR::InstBlockId param_patterns_id = SemIR::InstBlockId::None; SemIR::InstBlockId call_param_patterns_id = SemIR::InstBlockId::None; SemIR::InstBlockId call_params_id = SemIR::InstBlockId::None; - SemIR::InstBlockId call_param_default_values_id = SemIR::InstBlockId::Empty; SemIR::Function::CallParamIndexRanges call_param_ranges = SemIR::Function::CallParamIndexRanges::Empty; SemIR::TypeInstId return_type_inst_id = SemIR::TypeInstId::None; @@ -191,8 +190,6 @@ auto MakeGeneratedFunctionDecl(Context& context, SemIR::LocId loc_id, { .call_param_patterns_id = insts.call_param_patterns_id, .call_params_id = insts.call_params_id, - .call_param_default_values_id = - insts.call_param_default_values_id, .call_param_ranges = insts.call_param_ranges, .return_type_inst_id = insts.return_type_inst_id, .return_form_inst_id = insts.return_form_inst_id, @@ -305,62 +302,6 @@ static auto CheckFunctionEvaluationModeMatches( return false; } -// Checks that if `new_id` has a specified value, it has the same value as -// specified by `prev_id`. If `diagnose` is true this will issue a diagnostic -// if it detects a difference. Returns true if the values are the same or -// `new_id` is unspecified. -// -// Note: this function is only called on the function's first owning -// declaration, as that is the declaration with this requirement. -static auto CheckDefaultValueIsSame(Context& context, SemIR::InstId new_id, - SemIR::InstId prev_id, bool diagnose) - -> bool { - CARBON_CHECK(!context.insts().Is(prev_id)); - if (!context.insts().Is(new_id)) { - auto new_constant_id = context.constant_values().Get(new_id); - auto prev_constant_id = context.constant_values().Get(prev_id); - if (new_constant_id != prev_constant_id) { - if (diagnose) { - CARBON_DIAGNOSTIC( - PatternDefaultValueDiffers, Error, - "default value of {0} differs from the previously declared default " - "value of {1}", - InstIdAsConstant, InstIdAsConstant); - CARBON_DIAGNOSTIC(PatternDefaultValueDiffersNote, Note, - "different previous declaration here"); - context.emitter() - .Build(new_id, PatternDefaultValueDiffers, new_id, prev_id) - .Note(prev_id, PatternDefaultValueDiffersNote) - .Emit(); - } - return false; - } - } - - return true; -} - -// Checks every parameter in `prev_function` and `new_function`, that if they -// both specify a default value those values are identical. If `diagnose` is -// true, issues diagnostics when that condition is violated. Returns true if -// every parameter met the condition. -static auto CheckDefaultValueConsistency(Context& context, - const SemIR::Function& new_function, - const SemIR::Function& prev_function, - bool diagnose) -> bool { - auto new_default_value_ids = context.inst_blocks().GetOrEmpty( - new_function.call_param_default_values_id); - auto prev_default_value_ids = context.inst_blocks().GetOrEmpty( - prev_function.call_param_default_values_id); - - return llvm::all_of( - llvm::zip_equal(new_default_value_ids, prev_default_value_ids), - [&context, diagnose](auto id_pair) -> bool { - auto [new_id, prev_id] = id_pair; - return CheckDefaultValueIsSame(context, new_id, prev_id, diagnose); - }); -} - auto CheckFunctionTypeMatches(Context& context, const SemIR::Function& new_function, const SemIR::Function& prev_function, @@ -379,10 +320,6 @@ auto CheckFunctionTypeMatches(Context& context, diagnose)) { return false; } - if (!CheckDefaultValueConsistency(context, new_function, prev_function, - diagnose)) { - return false; - } return true; } diff --git a/toolchain/check/global_init.cpp b/toolchain/check/global_init.cpp index f95ccfef9d45..561330520441 100644 --- a/toolchain/check/global_init.cpp +++ b/toolchain/check/global_init.cpp @@ -51,7 +51,6 @@ auto GlobalInit::Finalize() -> void { .first_owning_decl_id = SemIR::InstId::None}, {.call_param_patterns_id = SemIR::InstBlockId::Empty, .call_params_id = SemIR::InstBlockId::Empty, - .call_param_default_values_id = SemIR::InstBlockId::Empty, .call_param_ranges = SemIR::Function::CallParamIndexRanges::Empty, .return_type_inst_id = SemIR::TypeInstId::None, .return_form_inst_id = SemIR::InstId::None, diff --git a/toolchain/check/handle_function.cpp b/toolchain/check/handle_function.cpp index 0eb5af6f1464..20efd3fdc83f 100644 --- a/toolchain/check/handle_function.cpp +++ b/toolchain/check/handle_function.cpp @@ -373,18 +373,13 @@ static auto DiagnosePositionalParams(Context& context, function_info.param_patterns_id = SemIR::InstBlockId::Empty; } -// Diagnoses that the default values for function parameters have been +// Diagnoses any default values for function parameters that have not been // completely specified, which is a requirement on the first owning declaration // of a function. -static auto CheckDefaultValuesCompletelySpecified( - Context& context, SemIR::Function& function_info) -> void { - auto unspecified_value_ids = llvm::make_filter_range( - context.inst_blocks().GetOrEmpty( - function_info.call_param_default_values_id), - [&context](auto inst_id) { - return context.insts().Is(inst_id); - }); - for (auto inst_id : unspecified_value_ids) { +static auto DiagnoseDefaultValuesNotSpecified( + Context& context, llvm::ArrayRef unspecified_inst_ids) + -> void { + for (auto inst_id : unspecified_inst_ids) { CARBON_DIAGNOSTIC(PatternDefaultValueNotSpecified, Error, "found unspecified default parameter value in the " "function's first owning declaration"); @@ -455,22 +450,21 @@ static auto BuildFunctionDecl(Context& context, // Build the function entity. This will be merged into an existing function if // there is one, or otherwise added to the function store. - auto function_info = SemIR::Function{ - name_context.MakeEntityWithParamsBase(name, decl_id, is_extern, - introducer.extern_library), - { - .call_param_patterns_id = name.call_param_patterns_id, - .call_params_id = name.call_params_id, - .call_param_default_values_id = name.call_param_default_values_id, - .call_param_ranges = name.param_ranges, - .return_type_inst_id = return_type_inst_id, - .return_form_inst_id = return_form_inst_id, - .return_pattern_id = return_pattern_id, - .virtual_modifier = virtual_modifier, - .evaluation_mode = evaluation_mode, - .interface_modifier = interface_modifier, - .self_param_id = self_param_id, - }}; + auto function_info = + SemIR::Function{name_context.MakeEntityWithParamsBase( + name, decl_id, is_extern, introducer.extern_library), + { + .call_param_patterns_id = name.call_param_patterns_id, + .call_params_id = name.call_params_id, + .call_param_ranges = name.param_ranges, + .return_type_inst_id = return_type_inst_id, + .return_form_inst_id = return_form_inst_id, + .return_pattern_id = return_pattern_id, + .virtual_modifier = virtual_modifier, + .evaluation_mode = evaluation_mode, + .interface_modifier = interface_modifier, + .self_param_id = self_param_id, + }}; if (is_definition) { function_info.definition_id = decl_id; } @@ -478,7 +472,8 @@ static auto BuildFunctionDecl(Context& context, DiagnosePositionalParams(context, function_info); if (name_context.state != DeclNameStack::NameContext::State::Poisoned && !name_context.prev_inst_id().has_value()) { - CheckDefaultValuesCompletelySpecified(context, function_info); + DiagnoseDefaultValuesNotSpecified( + context, context.inst_blocks().Get(name.unspecified_values_block_id)); } TryMergeRedecl( diff --git a/toolchain/check/handle_impl.cpp b/toolchain/check/handle_impl.cpp index 3b2d891f9246..eb5e0c7c559c 100644 --- a/toolchain/check/handle_impl.cpp +++ b/toolchain/check/handle_impl.cpp @@ -200,9 +200,9 @@ static auto PopImplIntroducerAndParamsAsNameComponent( .param_patterns_id = SemIR::InstBlockId::None, .call_param_patterns_id = SemIR::InstBlockId::None, .call_params_id = SemIR::InstBlockId::None, - .call_param_default_values_id = SemIR::InstBlockId::Empty, .param_ranges = SemIR::Function::CallParamIndexRanges::Empty, - .pattern_block_id = pattern_block_id}; + .pattern_block_id = pattern_block_id, + .unspecified_values_block_id = SemIR::InstBlockId::Empty}; } // Build an ImplDecl describing the signature of an impl. This handles the diff --git a/toolchain/check/handle_pattern_list.cpp b/toolchain/check/handle_pattern_list.cpp index 1f61a6099300..fa1eaf5a043c 100644 --- a/toolchain/check/handle_pattern_list.cpp +++ b/toolchain/check/handle_pattern_list.cpp @@ -154,11 +154,15 @@ auto HandleParseNode(Context& context, Parse::PatternListCommaId /*node_id*/) auto HandleParseNode(Context& context, Parse::DefaultValueUnspecifiedId node_id) -> bool { - context.node_stack().Push( - node_id, AddInst( - context, node_id, - {.type_id = GetSingletonType( - context, SemIR::UnspecifiedValueType::TypeInstId)})); + auto inst_id = AddInst( + context, node_id, + {.type_id = + GetSingletonType(context, SemIR::UnspecifiedValueType::TypeInstId)}); + + // Add the unspecified default value for later diagnostics checks. + context.full_pattern_stack().AddUnspecifiedDefaultValue(inst_id); + + context.node_stack().Push(node_id, inst_id); return true; } @@ -194,11 +198,13 @@ auto HandleParseNode(Context& context, Parse::DefaultValuePatternId node_id) return false; } - // Add the value to the default values array in the full pattern stack, for - // recovery later in the NameComponent. We store the raw value here for + // Add the value to the default values store. We store the raw value here for // conversion during pattern matching once the type of the pattern is known. - auto default_value_id = - context.full_pattern_stack().AddRawDefaultValue(expr_inst_id); + auto default_value_id = context.default_values().Add( + {.raw_id = expr_inst_id, + .value_id = SemIR::InstId::None, + .is_unspecified = + context.insts().Is(expr_inst_id)}); // Next on the node stack should be the pattern for which this default was // specified. We pop that so we can issue the DefaultValuePattern in its diff --git a/toolchain/check/import_ref.cpp b/toolchain/check/import_ref.cpp index 9393efed26fc..47e6b7398ad0 100644 --- a/toolchain/check/import_ref.cpp +++ b/toolchain/check/import_ref.cpp @@ -179,6 +179,9 @@ class ImportContext { auto import_constant_values() -> const SemIR::ConstantValueStore& { return import_ir().constant_values(); } + auto import_default_values() -> const SemIR::DefaultValueStore& { + return import_ir().default_values(); + } auto import_entity_names() -> const SemIR::EntityNameStore& { return import_ir().entity_names(); } @@ -267,6 +270,9 @@ class ImportContext { auto local_constant_values() -> SemIR::ConstantValueStore& { return local_ir().constant_values(); } + auto local_default_values() -> SemIR::DefaultValueStore& { + return local_ir().default_values(); + } auto local_entity_names() -> SemIR::EntityNameStore& { return local_ir().entity_names(); } @@ -2306,6 +2312,12 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver, SemIR::DefaultValuePattern inst) -> ResolveResult { auto subpattern = GetLocalImportRefInfo(resolver, inst.subpattern_id); + const auto& import_default_value = + resolver.import_default_values().Get(inst.default_value_id); + // We import the first owning declaration of a function, which must always + // have default values completely specified. + CARBON_CHECK(!import_default_value.is_unspecified); + auto value = GetLocalImportRefInfo(resolver, import_default_value.value_id); if (resolver.HasNewWork()) { return ResolveResult::Retry(); } @@ -2316,7 +2328,10 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver, .type_id = resolver.local_types().GetTypeIdForTypeConstantId( subpattern.local_type_const_id), .subpattern_id = AddLoadedImportRef(resolver, subpattern), - .default_value_id = inst.default_value_id, + .default_value_id = resolver.local_default_values().Add( + {.raw_id = SemIR::InstId::None, + .value_id = AddLoadedImportRef(resolver, value), + .is_unspecified = false}), }); } @@ -2425,7 +2440,6 @@ static auto ImportFunctionDecl( {GetIncompleteLocalEntityBase(context, function_decl_id, import_function), {.call_param_patterns_id = SemIR::InstBlockId::None, .call_params_id = SemIR::InstBlockId::None, - .call_param_default_values_id = SemIR::InstBlockId::Empty, .call_param_ranges = import_function.call_param_ranges, .return_type_inst_id = SemIR::TypeInstId::None, .return_form_inst_id = SemIR::InstId::None, @@ -2571,8 +2585,6 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver, auto call_param_patterns = GetLocalBlockImportRefInfo( resolver, import_function.call_param_patterns_id); - auto call_param_default_values = GetLocalBlockImportRefInfo( - resolver, import_function.call_param_default_values_id); auto return_type_const_id = SemIR::ConstantId::None; if (import_function.return_type_inst_id.has_value()) { return_type_const_id = @@ -2627,10 +2639,6 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver, // Add the function declaration. new_function.call_param_patterns_id = AddLoadedImportRefBlock(resolver, call_param_patterns); - if (call_param_default_values.has_value()) { - new_function.call_param_default_values_id = - AddLoadedImportRefBlock(resolver, *call_param_default_values); - } new_function.parent_scope_id = parent_scope_id; new_function.implicit_param_patterns_id = AddLoadedImportRefBlock(resolver, implicit_param_patterns); diff --git a/toolchain/check/merge.cpp b/toolchain/check/merge.cpp index 296cb0a6beeb..90ed33f7d37e 100644 --- a/toolchain/check/merge.cpp +++ b/toolchain/check/merge.cpp @@ -339,14 +339,30 @@ static auto CheckRedeclParam(Context& context, bool is_implicit_param, auto prev_default_value_pattern = prev_param_pattern.As(); + // If the new pattern specified a default value, it must match the + // previously declared default value. + const auto& new_default_value = context.default_values().Get( + new_default_value_pattern.default_value_id); + + if (!new_default_value.is_unspecified) { + const auto& prev_default_value = context.default_values().Get( + prev_default_value_pattern.default_value_id); + // We require first owning declaration to always specify a default + // value. + CARBON_CHECK(!prev_default_value.is_unspecified); + auto new_constant_id = + context.constant_values().Get(new_default_value.value_id); + auto prev_constant_id = + context.constant_values().Get(prev_default_value.value_id); + if (new_constant_id != prev_constant_id) { + emit_general_diagnostic(); + return false; + } + } + pattern_stack.push_back( {.prev_id = prev_default_value_pattern.subpattern_id, .new_id = new_default_value_pattern.subpattern_id}); - - // The node kind comparison should catch this on the mismatched patterns - // prior to this, so the indices should never mismatch. - CARBON_CHECK(prev_default_value_pattern.default_value_id.index == - new_default_value_pattern.default_value_id.index); break; } default: { diff --git a/toolchain/check/name_component.cpp b/toolchain/check/name_component.cpp index 89190863e256..3a431beb058f 100644 --- a/toolchain/check/name_component.cpp +++ b/toolchain/check/name_component.cpp @@ -45,10 +45,10 @@ auto PopNameComponent(Context& context, SemIR::InstId return_pattern_id) } auto call_param_patterns_id = SemIR::InstBlockId::None; - auto call_param_default_values_id = SemIR::InstBlockId::Empty; auto call_params_id = SemIR::InstBlockId::None; auto param_ranges = SemIR::Function::CallParamIndexRanges::Empty; auto pattern_block_id = SemIR::InstBlockId::None; + auto unspecified_values_block_id = SemIR::InstBlockId::Empty; if (param_patterns_id->has_value() || implicit_param_patterns_id->has_value() || return_pattern_id.has_value()) { @@ -57,11 +57,8 @@ auto PopNameComponent(Context& context, SemIR::InstId return_pattern_id) call_param_patterns_id = results.call_param_patterns_id; call_params_id = results.call_params_id; param_ranges = results.param_ranges; - CARBON_CHECK( - context.full_pattern_stack().GetRawDefaultValues().size() == - context.full_pattern_stack().GetConvertedDefaultValues().size()); - call_param_default_values_id = context.inst_blocks().Add( - context.full_pattern_stack().GetConvertedDefaultValues()); + unspecified_values_block_id = context.inst_blocks().Add( + context.full_pattern_stack().GetUnspecifiedDefaultValues()); pattern_block_id = context.pattern_block_stack().Pop(); context.full_pattern_stack().PopFullPattern(); } @@ -69,21 +66,19 @@ auto PopNameComponent(Context& context, SemIR::InstId return_pattern_id) auto [name_loc_id, name_id] = context.node_stack().PopWithNodeId(); - return { - .name_loc_id = name_loc_id, - .name_id = name_id, - .first_param_node_id = first_param_node_id, - .last_param_node_id = last_param_node_id, - .implicit_params_loc_id = implicit_params_node_id, - .implicit_param_patterns_id = *implicit_param_patterns_id, - .params_loc_id = params_node_id, - .param_patterns_id = *param_patterns_id, - .call_param_patterns_id = call_param_patterns_id, - .call_params_id = call_params_id, - .call_param_default_values_id = call_param_default_values_id, - .param_ranges = param_ranges, - .pattern_block_id = pattern_block_id, - }; + return {.name_loc_id = name_loc_id, + .name_id = name_id, + .first_param_node_id = first_param_node_id, + .last_param_node_id = last_param_node_id, + .implicit_params_loc_id = implicit_params_node_id, + .implicit_param_patterns_id = *implicit_param_patterns_id, + .params_loc_id = params_node_id, + .param_patterns_id = *param_patterns_id, + .call_param_patterns_id = call_param_patterns_id, + .call_params_id = call_params_id, + .param_ranges = param_ranges, + .pattern_block_id = pattern_block_id, + .unspecified_values_block_id = unspecified_values_block_id}; } // Pop the name of a declaration from the node stack, and diagnose if it has diff --git a/toolchain/check/name_component.h b/toolchain/check/name_component.h index 745bd70b5434..8ce99b9595e2 100644 --- a/toolchain/check/name_component.h +++ b/toolchain/check/name_component.h @@ -40,12 +40,13 @@ struct NameComponent { // SemIR::EntityWithParamsBase). SemIR::InstBlockId call_param_patterns_id; SemIR::InstBlockId call_params_id; - // The pattern default values as extracted from the parameter list. - SemIR::InstBlockId call_param_default_values_id; SemIR::Function::CallParamIndexRanges param_ranges; // The pattern block. SemIR::InstBlockId pattern_block_id; + + // The `UnspecifiedValue` insts from the parameter default values, if any. + SemIR::InstBlockId unspecified_values_block_id; }; // Pops a name component from the node stack (and pattern block stack, if it has diff --git a/toolchain/check/pattern_match.cpp b/toolchain/check/pattern_match.cpp index 7c1218a857b1..0eb3d52ff06b 100644 --- a/toolchain/check/pattern_match.cpp +++ b/toolchain/check/pattern_match.cpp @@ -962,21 +962,13 @@ auto MatchContext::DoPostWork(State state, // If a constant was specified, we should be able to convert it into the // type of the parameter. - auto raw_default_value_inst_id = - context_.full_pattern_stack() - .GetRawDefaultValues()[default_value_pattern.default_value_id.index]; - auto converted_inst_id = - context_.insts().Is(raw_default_value_inst_id) - ? raw_default_value_inst_id - : ConvertToValueOfType(context_, - SemIR::LocId(raw_default_value_inst_id), - raw_default_value_inst_id, param_type_id); - - // The index of the converted value should be the same as the raw value. - auto converted_default_id = - context_.full_pattern_stack().AddConvertedDefaultValue(converted_inst_id); - CARBON_CHECK(converted_default_id.index == - default_value_pattern.default_value_id.index); + auto& default_value = + context_.default_values().Get(default_value_pattern.default_value_id); + if (!default_value.is_unspecified) { + default_value.value_id = + ConvertToValueOfType(context_, SemIR::LocId(default_value.raw_id), + default_value.raw_id, param_type_id); + } results_stack_.PopArray(); diff --git a/toolchain/check/testdata/basics/raw_sem_ir/builtins.carbon b/toolchain/check/testdata/basics/raw_sem_ir/builtins.carbon index 892d173c8806..beb1b5cd1c23 100644 --- a/toolchain/check/testdata/basics/raw_sem_ir/builtins.carbon +++ b/toolchain/check/testdata/basics/raw_sem_ir/builtins.carbon @@ -21,6 +21,7 @@ // CHECK:STDOUT: import_ir_insts: {} // CHECK:STDOUT: clang_decls: {} // CHECK:STDOUT: clang_decl_signatures: {} +// CHECK:STDOUT: default_values: {} // CHECK:STDOUT: name_scopes: // CHECK:STDOUT: name_scope0: {inst: inst10, parent_scope: name_scope, has_error: false, extended_scopes: [], names: {}} // CHECK:STDOUT: entity_names: {} diff --git a/toolchain/check/testdata/basics/raw_sem_ir/bundle.carbon b/toolchain/check/testdata/basics/raw_sem_ir/bundle.carbon index eb7d6619ff86..3bd252849dd1 100644 --- a/toolchain/check/testdata/basics/raw_sem_ir/bundle.carbon +++ b/toolchain/check/testdata/basics/raw_sem_ir/bundle.carbon @@ -30,6 +30,7 @@ fn F(generic Form: Core.Form) ->? Form; // CHECK:STDOUT: import_ir_inst0: {ir_id: import_ir70000003, inst_id: inst50000023} // CHECK:STDOUT: clang_decls: {} // CHECK:STDOUT: clang_decl_signatures: {} +// CHECK:STDOUT: default_values: {} // CHECK:STDOUT: name_scopes: // CHECK:STDOUT: name_scope0: {inst: inst10, parent_scope: name_scope, has_error: false, extended_scopes: [], names: {name(Core): inst70000012, name0: inst70000033}} // CHECK:STDOUT: name_scope70000001: {inst: inst70000012, parent_scope: name_scope0, has_error: false, extended_scopes: [], names: {name1: inst70000017}} diff --git a/toolchain/check/testdata/basics/raw_sem_ir/cpp_interop.carbon b/toolchain/check/testdata/basics/raw_sem_ir/cpp_interop.carbon index 3f3865bf078c..560243e7b819 100644 --- a/toolchain/check/testdata/basics/raw_sem_ir/cpp_interop.carbon +++ b/toolchain/check/testdata/basics/raw_sem_ir/cpp_interop.carbon @@ -65,6 +65,7 @@ fn G(x: Cpp.X) { // CHECK:STDOUT: clang_decl_signatures: // CHECK:STDOUT: clang_decl_signature_id50000000: {kind: normal, num_params: 0} // CHECK:STDOUT: clang_decl_signature_id50000001: {kind: normal, num_params: 1, modes: [value]} +// CHECK:STDOUT: default_values: {} // CHECK:STDOUT: name_scopes: // CHECK:STDOUT: name_scope0: {inst: inst10, parent_scope: name_scope, has_error: false, extended_scopes: [], names: {name(Cpp): inst50000012, name0: inst5000001F}} // CHECK:STDOUT: name_scope50000001: {inst: inst50000012, parent_scope: name_scope0, has_error: false, extended_scopes: [], names: {name2: inst50000014, name3: inst5000002D, name4: inst50000055}} diff --git a/toolchain/check/testdata/basics/raw_sem_ir/multifile.carbon b/toolchain/check/testdata/basics/raw_sem_ir/multifile.carbon index b203fc96791d..a2d6c3114018 100644 --- a/toolchain/check/testdata/basics/raw_sem_ir/multifile.carbon +++ b/toolchain/check/testdata/basics/raw_sem_ir/multifile.carbon @@ -38,6 +38,7 @@ fn B() { // CHECK:STDOUT: import_ir_insts: {} // CHECK:STDOUT: clang_decls: {} // CHECK:STDOUT: clang_decl_signatures: {} +// CHECK:STDOUT: default_values: {} // CHECK:STDOUT: name_scopes: // CHECK:STDOUT: name_scope0: {inst: inst10, parent_scope: name_scope, has_error: false, extended_scopes: [], names: {name0: inst50000011}} // CHECK:STDOUT: entity_names: {} @@ -142,6 +143,7 @@ fn B() { // CHECK:STDOUT: import_ir_inst1: {ir_id: import_ir70000002, inst_id: inst50000011} // CHECK:STDOUT: clang_decls: {} // CHECK:STDOUT: clang_decl_signatures: {} +// CHECK:STDOUT: default_values: {} // CHECK:STDOUT: name_scopes: // CHECK:STDOUT: name_scope0: {inst: inst10, parent_scope: name_scope, has_error: false, extended_scopes: [], names: {name1: inst70000012, name0: inst70000013}} // CHECK:STDOUT: name_scope70000001: {inst: inst70000012, parent_scope: name_scope0, has_error: false, extended_scopes: [], names: {name1: inst70000018}} diff --git a/toolchain/check/testdata/basics/raw_sem_ir/multifile_with_textual_ir.carbon b/toolchain/check/testdata/basics/raw_sem_ir/multifile_with_textual_ir.carbon index 7141168657b4..07f44b43f0c9 100644 --- a/toolchain/check/testdata/basics/raw_sem_ir/multifile_with_textual_ir.carbon +++ b/toolchain/check/testdata/basics/raw_sem_ir/multifile_with_textual_ir.carbon @@ -38,6 +38,7 @@ fn B() { // CHECK:STDOUT: import_ir_insts: {} // CHECK:STDOUT: clang_decls: {} // CHECK:STDOUT: clang_decl_signatures: {} +// CHECK:STDOUT: default_values: {} // CHECK:STDOUT: name_scopes: // CHECK:STDOUT: name_scope0: {inst: inst10, parent_scope: name_scope, has_error: false, extended_scopes: [], names: {name0: inst50000011}} // CHECK:STDOUT: entity_names: {} @@ -161,6 +162,7 @@ fn B() { // CHECK:STDOUT: import_ir_inst1: {ir_id: import_ir70000002, inst_id: inst50000011} // CHECK:STDOUT: clang_decls: {} // CHECK:STDOUT: clang_decl_signatures: {} +// CHECK:STDOUT: default_values: {} // CHECK:STDOUT: name_scopes: // CHECK:STDOUT: name_scope0: {inst: inst10, parent_scope: name_scope, has_error: false, extended_scopes: [], names: {name1: inst70000012, name0: inst70000013}} // CHECK:STDOUT: name_scope70000001: {inst: inst70000012, parent_scope: name_scope0, has_error: false, extended_scopes: [], names: {name1: inst70000018}} diff --git a/toolchain/check/testdata/basics/raw_sem_ir/non_core_interfaces.carbon b/toolchain/check/testdata/basics/raw_sem_ir/non_core_interfaces.carbon index 69d46296a5b7..97d12f5359c3 100644 --- a/toolchain/check/testdata/basics/raw_sem_ir/non_core_interfaces.carbon +++ b/toolchain/check/testdata/basics/raw_sem_ir/non_core_interfaces.carbon @@ -47,6 +47,7 @@ fn UseLocalCopy[T: Copy](_: T.T1, _: T.T2) {} // CHECK:STDOUT: import_ir_insts: {} // CHECK:STDOUT: clang_decls: {} // CHECK:STDOUT: clang_decl_signatures: {} +// CHECK:STDOUT: default_values: {} // CHECK:STDOUT: name_scopes: // CHECK:STDOUT: name_scope0: {inst: inst10, parent_scope: name_scope, has_error: false, extended_scopes: [], names: {name1: inst60000011}} // CHECK:STDOUT: name_scope60000001: {inst: inst60000011, parent_scope: name_scope0, has_error: false, extended_scopes: [], names: {name(SelfType): inst60000013}} @@ -211,6 +212,7 @@ fn UseLocalCopy[T: Copy](_: T.T1, _: T.T2) {} // CHECK:STDOUT: import_ir_instC: {ir_id: import_ir50000002, inst_id: inst6000001D} // CHECK:STDOUT: clang_decls: {} // CHECK:STDOUT: clang_decl_signatures: {} +// CHECK:STDOUT: default_values: {} // CHECK:STDOUT: name_scopes: // CHECK:STDOUT: name_scope0: {inst: inst10, parent_scope: name_scope, has_error: false, extended_scopes: [], names: {name0: inst50000012, name1: inst50000013, name4: inst5000006B, name7: inst500000AA}} // CHECK:STDOUT: name_scope50000001: {inst: inst50000012, parent_scope: name_scope0, has_error: false, extended_scopes: [], names: {name6: inst50000026}} diff --git a/toolchain/check/testdata/basics/raw_sem_ir/one_file.carbon b/toolchain/check/testdata/basics/raw_sem_ir/one_file.carbon index 702281783fd5..4678f3a10849 100644 --- a/toolchain/check/testdata/basics/raw_sem_ir/one_file.carbon +++ b/toolchain/check/testdata/basics/raw_sem_ir/one_file.carbon @@ -339,6 +339,7 @@ fn Foo[T: type](p: T*) -> (T*, ()) { // CHECK:STDOUT: import_ir_inst129: {ir_id: import_ir78000004, inst_id: inst700002D4} // CHECK:STDOUT: clang_decls: {} // CHECK:STDOUT: clang_decl_signatures: {} +// CHECK:STDOUT: default_values: {} // CHECK:STDOUT: name_scopes: // CHECK:STDOUT: name_scope0: {inst: inst10, parent_scope: name_scope, has_error: false, extended_scopes: [], names: {name(Core): inst78000012, name0: inst78000049}} // CHECK:STDOUT: name_scope78000001: {inst: inst78000012, parent_scope: name_scope0, has_error: false, extended_scopes: [], names: {name3: inst78000059}} diff --git a/toolchain/check/testdata/basics/raw_sem_ir/one_file_with_textual_ir.carbon b/toolchain/check/testdata/basics/raw_sem_ir/one_file_with_textual_ir.carbon index 1c9543bb0060..74a9f94e86fb 100644 --- a/toolchain/check/testdata/basics/raw_sem_ir/one_file_with_textual_ir.carbon +++ b/toolchain/check/testdata/basics/raw_sem_ir/one_file_with_textual_ir.carbon @@ -29,6 +29,7 @@ fn Foo(n: ()) -> ((), ()) { // CHECK:STDOUT: import_ir_insts: {} // CHECK:STDOUT: clang_decls: {} // CHECK:STDOUT: clang_decl_signatures: {} +// CHECK:STDOUT: default_values: {} // CHECK:STDOUT: name_scopes: // CHECK:STDOUT: name_scope0: {inst: inst10, parent_scope: name_scope, has_error: false, extended_scopes: [], names: {name0: inst5000002F}} // CHECK:STDOUT: entity_names: diff --git a/toolchain/check/testdata/function/declaration/default_values.carbon b/toolchain/check/testdata/function/declaration/default_values.carbon index 6d653dc66839..4dc24c9e4456 100644 --- a/toolchain/check/testdata/function/declaration/default_values.carbon +++ b/toolchain/check/testdata/function/declaration/default_values.carbon @@ -170,7 +170,7 @@ fn F(x: C = {}); // CHECK:STDOUT: %a.patt: %pattern_type.d8d = wrapper_binding_pattern a, %a.param_patt [concrete] // CHECK:STDOUT: %empty_struct: %empty_struct_type = struct_value () [concrete] // CHECK:STDOUT: %C.val: %C = struct_value () [concrete] -// CHECK:STDOUT: %.68d: %pattern_type.d8d = default_value_pattern %a.patt, index: 0 [concrete] +// CHECK:STDOUT: %.e44: %pattern_type.d8d = default_value_pattern %a.patt, @F.%.loc10_16.7 [concrete] // CHECK:STDOUT: %C.as.ImplicitAs.impl.Convert.bound: = bound_method %C.val, %C.as.ImplicitAs.impl.Convert [concrete] // CHECK:STDOUT: %.115: ref %C = temporary invalid, %C.val [concrete] // CHECK:STDOUT: %F.type: type = fn_type @F [concrete] @@ -181,7 +181,7 @@ fn F(x: C = {}); // CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [concrete = constants.%F] { // CHECK:STDOUT: %a.param_patt: %pattern_type.d8d = value_param_pattern [concrete = constants.%a.param_patt] // CHECK:STDOUT: %a.patt: %pattern_type.d8d = wrapper_binding_pattern a, %a.param_patt [concrete = constants.%a.patt] -// CHECK:STDOUT: %.loc10_11: %pattern_type.d8d = default_value_pattern %a.patt, index: 0 [concrete = constants.%.68d] +// CHECK:STDOUT: %.loc10_11: %pattern_type.d8d = default_value_pattern %a.patt, %.loc10_16.7 [concrete = constants.%.e44] // CHECK:STDOUT: } { // CHECK:STDOUT: %.loc10_14.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct] // CHECK:STDOUT: %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C] @@ -203,10 +203,7 @@ fn F(x: C = {}); // CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @F(%a.param: %D) { -// CHECK:STDOUT: !default_values: -// CHECK:STDOUT: %.loc10_16.7: %D = acquire_value %.loc10_16.6 -// CHECK:STDOUT: } +// CHECK:STDOUT: fn @F(%a.param: %D); // CHECK:STDOUT: // CHECK:STDOUT: --- nested.carbon // CHECK:STDOUT: @@ -240,7 +237,7 @@ fn F(x: C = {}); // CHECK:STDOUT: %tuple.56c: %tuple.type.6ca = tuple_value (%empty_struct, %tuple.9a3) [concrete] // CHECK:STDOUT: %tuple.type.bcdf: type = tuple_type (%empty_struct_type, %tuple.type.6ca) [concrete] // CHECK:STDOUT: %tuple.4f4: %tuple.type.bcdf = tuple_value (%empty_struct, %tuple.56c) [concrete] -// CHECK:STDOUT: %.b6d: %pattern_type.f5f = default_value_pattern %.341, index: 0 [concrete] +// CHECK:STDOUT: %.391: %pattern_type.f5f = default_value_pattern %.341, @F.%.loc6_62.6 [concrete] // CHECK:STDOUT: %C.val: %C = struct_value () [concrete] // CHECK:STDOUT: %.115: ref %C = temporary invalid, %C.val [concrete] // CHECK:STDOUT: %tuple.d3e: %tuple.type.748 = tuple_value (%C.val, %C.val) [concrete] @@ -265,7 +262,7 @@ fn F(x: C = {}); // CHECK:STDOUT: %.loc6_37: %pattern_type.8b4 = tuple_pattern (%d.patt, %e.patt) [concrete = constants.%.fe8] // CHECK:STDOUT: %.loc6_38: %pattern_type.4fa = tuple_pattern (%c.patt, %.loc6_37) [concrete = constants.%.972] // CHECK:STDOUT: %.loc6_39: %pattern_type.f5f = tuple_pattern (%b.patt, %.loc6_38) [concrete = constants.%.341] -// CHECK:STDOUT: %.loc6_41: %pattern_type.f5f = default_value_pattern %.loc6_39, index: 0 [concrete = constants.%.b6d] +// CHECK:STDOUT: %.loc6_41: %pattern_type.f5f = default_value_pattern %.loc6_39, %.loc6_62.6 [concrete = constants.%.391] // CHECK:STDOUT: } { // CHECK:STDOUT: %.loc6_45.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct] // CHECK:STDOUT: %.loc6_50.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct] @@ -321,10 +318,7 @@ fn F(x: C = {}); // CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @F(%a.param: %C, %b.param: %C, %c.param: %C, %d.param: %C, %e.param: %C) { -// CHECK:STDOUT: !default_values: -// CHECK:STDOUT: %.loc6_62.6: %tuple.type.a40 = converted %.loc6_62.1, %tuple.loc6_62 [concrete = constants.%tuple.800] -// CHECK:STDOUT: } +// CHECK:STDOUT: fn @F(%a.param: %C, %b.param: %C, %c.param: %C, %d.param: %C, %e.param: %C); // CHECK:STDOUT: // CHECK:STDOUT: --- basic.carbon // CHECK:STDOUT: @@ -335,7 +329,7 @@ fn F(x: C = {}); // CHECK:STDOUT: %x.param_patt: %pattern_type = value_param_pattern [concrete] // CHECK:STDOUT: %x.patt: %pattern_type = wrapper_binding_pattern x, %x.param_patt [concrete] // CHECK:STDOUT: %empty_struct: %empty_struct_type = struct_value () [concrete] -// CHECK:STDOUT: %.015: %pattern_type = default_value_pattern %x.patt, index: 0 [concrete] +// CHECK:STDOUT: %.ff4: %pattern_type = default_value_pattern %x.patt, @F.%.loc6_14.6 [concrete] // CHECK:STDOUT: %C.val: %C = struct_value () [concrete] // CHECK:STDOUT: %.115: ref %C = temporary invalid, %C.val [concrete] // CHECK:STDOUT: %F.type: type = fn_type @F [concrete] @@ -346,7 +340,7 @@ fn F(x: C = {}); // CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [concrete = constants.%F] { // CHECK:STDOUT: %x.param_patt: %pattern_type = value_param_pattern [concrete = constants.%x.param_patt] // CHECK:STDOUT: %x.patt: %pattern_type = wrapper_binding_pattern x, %x.param_patt [concrete = constants.%x.patt] -// CHECK:STDOUT: %.loc6_11: %pattern_type = default_value_pattern %x.patt, index: 0 [concrete = constants.%.015] +// CHECK:STDOUT: %.loc6_11: %pattern_type = default_value_pattern %x.patt, %.loc6_14.6 [concrete = constants.%.ff4] // CHECK:STDOUT: } { // CHECK:STDOUT: %.loc6_14.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct] // CHECK:STDOUT: %x.param: %C = value_param call_param0 @@ -360,8 +354,5 @@ fn F(x: C = {}); // CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @F(%x.param: %C) { -// CHECK:STDOUT: !default_values: -// CHECK:STDOUT: %.loc6_14.6: %C = acquire_value %.loc6_14.5 [concrete = constants.%C.val] -// CHECK:STDOUT: } +// CHECK:STDOUT: fn @F(%x.param: %C); // CHECK:STDOUT: diff --git a/toolchain/check/testdata/function/definition/default_values.carbon b/toolchain/check/testdata/function/definition/default_values.carbon index 9218ece32e2b..8b965beef420 100644 --- a/toolchain/check/testdata/function/definition/default_values.carbon +++ b/toolchain/check/testdata/function/definition/default_values.carbon @@ -14,12 +14,12 @@ library "[[@TEST_NAME]]"; fn F(x: i32 = 0, y: i32 = 10); -// CHECK:STDERR: fail_defaults_different_values_redecl.carbon:[[@LINE+7]]:41: error: redeclaration syntax differs here [RedeclParamSyntaxDiffers] +// CHECK:STDERR: fail_defaults_different_values_redecl.carbon:[[@LINE+7]]:25: error: redeclaration differs at parameter 2 [RedeclParamDiffers] // CHECK:STDERR: fn F(unused x: i32 = 0, unused y: i32 = 22) { } -// CHECK:STDERR: ^~ -// CHECK:STDERR: fail_defaults_different_values_redecl.carbon:[[@LINE-4]]:27: note: comparing with previous declaration here [RedeclParamSyntaxPrevious] +// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~ +// CHECK:STDERR: fail_defaults_different_values_redecl.carbon:[[@LINE-4]]:18: note: previous declaration's corresponding parameter here [RedeclParamPrevious] // CHECK:STDERR: fn F(x: i32 = 0, y: i32 = 10); -// CHECK:STDERR: ^~ +// CHECK:STDERR: ^~~~~~~~~~~ // CHECK:STDERR: fn F(unused x: i32 = 0, unused y: i32 = 22) { } @@ -49,13 +49,13 @@ fn F(x: i32 = 0, y: i32 = 10); // --- fail_imported_defaults_different_values.impl.carbon impl library "[[@TEST_NAME]]"; -// CHECK:STDERR: fail_imported_defaults_different_values.impl.carbon:[[@LINE+8]]:41: error: default value of `22` differs from the previously declared default value of `10` [PatternDefaultValueDiffers] +// CHECK:STDERR: fail_imported_defaults_different_values.impl.carbon:[[@LINE+8]]:25: error: redeclaration differs at parameter 2 [RedeclParamDiffers] // CHECK:STDERR: fn F(unused x: i32 = 0, unused y: i32 = 22) { } -// CHECK:STDERR: ^~ +// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~ // CHECK:STDERR: fail_imported_defaults_different_values.impl.carbon:[[@LINE-5]]:1: in import [InImport] -// CHECK:STDERR: imported_defaults_different_values.carbon:3:27: note: different previous declaration here [PatternDefaultValueDiffersNote] +// CHECK:STDERR: imported_defaults_different_values.carbon:3:18: note: previous declaration's corresponding parameter here [RedeclParamPrevious] // CHECK:STDERR: fn F(x: i32 = 0, y: i32 = 10); -// CHECK:STDERR: ^~ +// CHECK:STDERR: ^~~~~~~~~~~ // CHECK:STDERR: fn F(unused x: i32 = 0, unused y: i32 = 22) { } @@ -104,7 +104,6 @@ fn F(x: i32 = _) -> i32 { return x; } // CHECK:STDOUT: %x.param_patt: %pattern_type.6b6 = value_param_pattern [concrete] // CHECK:STDOUT: %x.patt: %pattern_type.6b6 = wrapper_binding_pattern x, %x.param_patt [concrete] // CHECK:STDOUT: %int_0.5c6: Core.IntLiteral = int_value 0 [concrete] -// CHECK:STDOUT: %.e53: %pattern_type.6b6 = default_value_pattern %x.patt, index: 0 [concrete] // CHECK:STDOUT: %.795f: Core.Form = init_form %i32 [concrete] // CHECK:STDOUT: %return.param_patt.a9a: %pattern_type.6b6 = out_param_pattern [concrete] // CHECK:STDOUT: %return.patt.e1b: %pattern_type.6b6 = return_slot_pattern %return.param_patt.a9a, %i32 [concrete] @@ -126,6 +125,7 @@ fn F(x: i32 = _) -> i32 { return x; } // CHECK:STDOUT: %F: %F.type = struct_value () [concrete] // CHECK:STDOUT: %G.type: type = fn_type @G [concrete] // CHECK:STDOUT: %G: %G.type = struct_value () [concrete] +// CHECK:STDOUT: %.d3f: %pattern_type.6b6 = default_value_pattern %x.patt, @F.%.loc7_15.2 [concrete] // CHECK:STDOUT: %Copy.type: type = facet_type <@Copy> [concrete] // CHECK:STDOUT: %Int.as.Copy.impl.Op.type.ac8: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%N) [symbolic] // CHECK:STDOUT: %Int.as.Copy.impl.Op.5e0: %Int.as.Copy.impl.Op.type.ac8 = struct_value () [symbolic] @@ -137,6 +137,7 @@ fn F(x: i32 = _) -> i32 { return x; } // CHECK:STDOUT: %.737: type = fn_type_with_self_type %Copy.WithSelf.Op.type.381, %Copy.facet [concrete] // CHECK:STDOUT: %Int.as.Copy.impl.Op.specific_fn: = specific_function %Int.as.Copy.impl.Op.4f6, @Int.as.Copy.impl.Op(%int_32) [concrete] // CHECK:STDOUT: %.d49: = unspecified_value [concrete] +// CHECK:STDOUT: %.5aa: %pattern_type.6b6 = default_value_pattern %x.patt, [concrete] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { @@ -150,7 +151,7 @@ fn F(x: i32 = _) -> i32 { return x; } // CHECK:STDOUT: %F.decl.loc7: %F.type = fn_decl @F [concrete = constants.%F] { // CHECK:STDOUT: %x.param_patt: %pattern_type.6b6 = value_param_pattern [concrete = constants.%x.param_patt] // CHECK:STDOUT: %x.patt: %pattern_type.6b6 = wrapper_binding_pattern x, %x.param_patt [concrete = constants.%x.patt] -// CHECK:STDOUT: %.loc7_13: %pattern_type.6b6 = default_value_pattern %x.patt, index: 0 [concrete = constants.%.e53] +// CHECK:STDOUT: %.loc7_13: %pattern_type.6b6 = default_value_pattern %x.patt, %.loc7_15.2 [concrete = constants.%.d3f] // CHECK:STDOUT: %return.param_patt: %pattern_type.6b6 = out_param_pattern [concrete = constants.%return.param_patt.a9a] // CHECK:STDOUT: %return.patt: %pattern_type.6b6 = return_slot_pattern %return.param_patt, %i32.loc7_21 [concrete = constants.%return.patt.e1b] // CHECK:STDOUT: } { @@ -173,7 +174,7 @@ fn F(x: i32 = _) -> i32 { return x; } // CHECK:STDOUT: %G.decl.loc8: %G.type = fn_decl @G [concrete = constants.%G] { // CHECK:STDOUT: %x.param_patt: %pattern_type.6b6 = value_param_pattern [concrete = constants.%x.param_patt] // CHECK:STDOUT: %x.patt: %pattern_type.6b6 = wrapper_binding_pattern x, %x.param_patt [concrete = constants.%x.patt] -// CHECK:STDOUT: %.loc8_13: %pattern_type.6b6 = default_value_pattern %x.patt, index: 0 [concrete = constants.%.e53] +// CHECK:STDOUT: %.loc8_13: %pattern_type.6b6 = default_value_pattern %x.patt, [concrete = constants.%.5aa] // CHECK:STDOUT: %return.param_patt: %pattern_type.6b6 = out_param_pattern [concrete = constants.%return.param_patt.a9a] // CHECK:STDOUT: %return.patt: %pattern_type.6b6 = return_slot_pattern %return.param_patt, %i32.loc8_21 [concrete = constants.%return.patt.e1b] // CHECK:STDOUT: } { @@ -189,9 +190,6 @@ fn F(x: i32 = _) -> i32 { return x; } // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @F(%x.param.loc7: %i32) -> out %return.param.loc7: %i32 { -// CHECK:STDOUT: !default_values: -// CHECK:STDOUT: -// CHECK:STDOUT: // CHECK:STDOUT: !entry: // CHECK:STDOUT: %x.ref: %i32 = name_ref x, %x.loc7 // CHECK:STDOUT: %impl.elem0.loc7_34: %.737 = impl_witness_access constants.%Copy.impl_witness.b51, element0 [concrete = constants.%Int.as.Copy.impl.Op.4f6] @@ -203,9 +201,6 @@ fn F(x: i32 = _) -> i32 { return x; } // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @G(%x.param.loc8: %i32) -> out %return.param.loc8: %i32 { -// CHECK:STDOUT: !default_values: -// CHECK:STDOUT: -// CHECK:STDOUT: // CHECK:STDOUT: !entry: // CHECK:STDOUT: %x.ref: %i32 = name_ref x, %x.loc8 // CHECK:STDOUT: %impl.elem0.loc8: %.737 = impl_witness_access constants.%Copy.impl_witness.b51, element0 [concrete = constants.%Int.as.Copy.impl.Op.4f6] @@ -229,7 +224,7 @@ fn F(x: i32 = _) -> i32 { return x; } // CHECK:STDOUT: %x.param_patt: %pattern_type.6b6 = value_param_pattern [concrete] // CHECK:STDOUT: %x.patt: %pattern_type.6b6 = wrapper_binding_pattern x, %x.param_patt [concrete] // CHECK:STDOUT: %int_0.5c6: Core.IntLiteral = int_value 0 [concrete] -// CHECK:STDOUT: %.e53: %pattern_type.6b6 = default_value_pattern %x.patt, index: 0 [concrete] +// CHECK:STDOUT: %.3d1: %pattern_type.6b6 = default_value_pattern %x.patt, @F.%.loc4_15.2 [concrete] // CHECK:STDOUT: %.795f: Core.Form = init_form %i32 [concrete] // CHECK:STDOUT: %return.param_patt.a9a: %pattern_type.6b6 = out_param_pattern [concrete] // CHECK:STDOUT: %return.patt.e1b: %pattern_type.6b6 = return_slot_pattern %return.param_patt.a9a, %i32 [concrete] @@ -269,7 +264,7 @@ fn F(x: i32 = _) -> i32 { return x; } // CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [concrete = constants.%F] { // CHECK:STDOUT: %x.param_patt: %pattern_type.6b6 = value_param_pattern [concrete = constants.%x.param_patt] // CHECK:STDOUT: %x.patt: %pattern_type.6b6 = wrapper_binding_pattern x, %x.param_patt [concrete = constants.%x.patt] -// CHECK:STDOUT: %.loc4_13: %pattern_type.6b6 = default_value_pattern %x.patt, index: 0 [concrete = constants.%.e53] +// CHECK:STDOUT: %.loc4_13: %pattern_type.6b6 = default_value_pattern %x.patt, %.loc4_15.2 [concrete = constants.%.3d1] // CHECK:STDOUT: %return.param_patt: %pattern_type.6b6 = out_param_pattern [concrete = constants.%return.param_patt.a9a] // CHECK:STDOUT: %return.patt: %pattern_type.6b6 = return_slot_pattern %return.param_patt, %i32.loc4_21 [concrete = constants.%return.patt.e1b] // CHECK:STDOUT: } { @@ -292,9 +287,6 @@ fn F(x: i32 = _) -> i32 { return x; } // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @F(%x.param: %i32) -> out %return.param: %i32 [from "imported_repeated_defaults.carbon"] { -// CHECK:STDOUT: !default_values: -// CHECK:STDOUT: -// CHECK:STDOUT: // CHECK:STDOUT: !entry: // CHECK:STDOUT: %x.ref: %i32 = name_ref x, %x // CHECK:STDOUT: %impl.elem0.loc4_34: %.737 = impl_witness_access constants.%Copy.impl_witness.b51, element0 [concrete = constants.%Int.as.Copy.impl.Op.4f6] @@ -315,7 +307,7 @@ fn F(x: i32 = _) -> i32 { return x; } // CHECK:STDOUT: %x.param_patt: %pattern_type.6b6 = value_param_pattern [concrete] // CHECK:STDOUT: %x.patt: %pattern_type.6b6 = wrapper_binding_pattern x, %x.param_patt [concrete] // CHECK:STDOUT: %.d49: = unspecified_value [concrete] -// CHECK:STDOUT: %.e53: %pattern_type.6b6 = default_value_pattern %x.patt, index: 0 [concrete] +// CHECK:STDOUT: %.c5e: %pattern_type.6b6 = default_value_pattern %x.patt, [concrete] // CHECK:STDOUT: %.795f: Core.Form = init_form %i32 [concrete] // CHECK:STDOUT: %return.param_patt.a9a: %pattern_type.6b6 = out_param_pattern [concrete] // CHECK:STDOUT: %return.patt.e1b: %pattern_type.6b6 = return_slot_pattern %return.param_patt.a9a, %i32 [concrete] @@ -342,7 +334,7 @@ fn F(x: i32 = _) -> i32 { return x; } // CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [concrete = constants.%F] { // CHECK:STDOUT: %x.param_patt: %pattern_type.6b6 = value_param_pattern [concrete = constants.%x.param_patt] // CHECK:STDOUT: %x.patt: %pattern_type.6b6 = wrapper_binding_pattern x, %x.param_patt [concrete = constants.%x.patt] -// CHECK:STDOUT: %.loc4_13: %pattern_type.6b6 = default_value_pattern %x.patt, index: 0 [concrete = constants.%.e53] +// CHECK:STDOUT: %.loc4_13: %pattern_type.6b6 = default_value_pattern %x.patt, [concrete = constants.%.c5e] // CHECK:STDOUT: %return.param_patt: %pattern_type.6b6 = out_param_pattern [concrete = constants.%return.param_patt.a9a] // CHECK:STDOUT: %return.patt: %pattern_type.6b6 = return_slot_pattern %return.param_patt, %i32.loc4_21 [concrete = constants.%return.patt.e1b] // CHECK:STDOUT: } { @@ -358,9 +350,6 @@ fn F(x: i32 = _) -> i32 { return x; } // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @F(%x.param: %i32) -> out %return.param: %i32 [from "imported_elided_defaults_in_def.carbon"] { -// CHECK:STDOUT: !default_values: -// CHECK:STDOUT: -// CHECK:STDOUT: // CHECK:STDOUT: !entry: // CHECK:STDOUT: %x.ref: %i32 = name_ref x, %x // CHECK:STDOUT: %impl.elem0: %.737 = impl_witness_access constants.%Copy.impl_witness.b51, element0 [concrete = constants.%Int.as.Copy.impl.Op.4f6] diff --git a/toolchain/check/thunk.cpp b/toolchain/check/thunk.cpp index 61cbae832e94..e2577575d0ab 100644 --- a/toolchain/check/thunk.cpp +++ b/toolchain/check/thunk.cpp @@ -249,7 +249,6 @@ static auto CloneFunctionDecl(Context& context, SemIR::LocId loc_id, { .call_param_patterns_id = match_results.call_param_patterns_id, .call_params_id = match_results.call_params_id, - .call_param_default_values_id = SemIR::InstBlockId::Empty, .call_param_ranges = match_results.param_ranges, .return_type_inst_id = return_type_inst_id, .return_form_inst_id = return_form_inst_id, diff --git a/toolchain/diagnostics/kind.def b/toolchain/diagnostics/kind.def index e9ec0b695e3a..3e0e28f845ab 100644 --- a/toolchain/diagnostics/kind.def +++ b/toolchain/diagnostics/kind.def @@ -620,8 +620,6 @@ CARBON_DIAGNOSTIC_KIND(GenericMissingExplicitParameters) CARBON_DIAGNOSTIC_KIND(RequiredPatternDefaultValueMissing) CARBON_DIAGNOSTIC_KIND(RequiredPatternDefaultValueFirstDefault) CARBON_DIAGNOSTIC_KIND(RequiredPatternDefaultValueMissingAdditional) -CARBON_DIAGNOSTIC_KIND(PatternDefaultValueDiffers) -CARBON_DIAGNOSTIC_KIND(PatternDefaultValueDiffersNote) CARBON_DIAGNOSTIC_KIND(PatternDefaultValueNotConstant) CARBON_DIAGNOSTIC_KIND(PatternDefaultValueNotInParameterList) CARBON_DIAGNOSTIC_KIND(PatternDefaultValueNotSpecified) diff --git a/toolchain/driver/testdata/stdin.carbon b/toolchain/driver/testdata/stdin.carbon index e5857613b394..c8f4c5e83a01 100644 --- a/toolchain/driver/testdata/stdin.carbon +++ b/toolchain/driver/testdata/stdin.carbon @@ -33,6 +33,7 @@ // CHECK:STDOUT: import_ir_insts: {} // CHECK:STDOUT: clang_decls: {} // CHECK:STDOUT: clang_decl_signatures: {} +// CHECK:STDOUT: default_values: {} // CHECK:STDOUT: name_scopes: // CHECK:STDOUT: name_scope0: {inst: inst10, parent_scope: name_scope, has_error: false, extended_scopes: [], names: {}} // CHECK:STDOUT: entity_names: {} diff --git a/toolchain/sem_ir/BUILD b/toolchain/sem_ir/BUILD index c08c174cf2dc..83bc914226f1 100644 --- a/toolchain/sem_ir/BUILD +++ b/toolchain/sem_ir/BUILD @@ -100,6 +100,7 @@ cc_library( "cpp_initializer_list.cpp", "cpp_overload_set.cpp", "declared_facet_type.cpp", + "default_value.cpp", "entity_name.cpp", "field.cpp", "file.cpp", @@ -135,6 +136,7 @@ cc_library( "cpp_initializer_list.h", "cpp_overload_set.h", "declared_facet_type.h", + "default_value.h", "entity_name.h", "entity_with_params_base.h", "field.h", diff --git a/toolchain/sem_ir/default_value.cpp b/toolchain/sem_ir/default_value.cpp new file mode 100644 index 000000000000..7e968c6fdc3c --- /dev/null +++ b/toolchain/sem_ir/default_value.cpp @@ -0,0 +1,12 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include "toolchain/sem_ir/default_value.h" + +#include "toolchain/base/value_store_impl.h" + +namespace Carbon { +template class ValueStore>; +} // namespace Carbon diff --git a/toolchain/sem_ir/default_value.h b/toolchain/sem_ir/default_value.h new file mode 100644 index 000000000000..db2a67bf402c --- /dev/null +++ b/toolchain/sem_ir/default_value.h @@ -0,0 +1,45 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#ifndef CARBON_TOOLCHAIN_SEM_IR_DEFAULT_VALUE_H_ +#define CARBON_TOOLCHAIN_SEM_IR_DEFAULT_VALUE_H_ + +#include "toolchain/base/value_store.h" +#include "toolchain/sem_ir/ids.h" + +namespace Carbon::SemIR { + +// Information about a default value for a pattern, such as default values for +// function parameters. +struct DefaultValue : public Printable { + auto Print(llvm::raw_ostream& out) const -> void { + out << "{raw_id: " << raw_id << ", value_id: " << value_id + << ", is_unspecified: " << is_unspecified << "}"; + } + + // The instruction specifying the default value as specified by the developer, + // before conversion to the pattern scrutinee type is applied. + InstId raw_id; + + // The instruction specifying the default value in the same type as the + // scrutinee type. + InstId value_id; + + // Whether the user left this default value unspecified. The `value_id` will + // be `None` but the `raw_id` will contain the `UnspecifiedValue` instruction + // for use in diagnostics if needed. + bool is_unspecified; +}; + +using DefaultValueStore = + ValueStore>; + +} // namespace Carbon::SemIR + +namespace Carbon { +extern template class ValueStore>; +} + +#endif // CARBON_TOOLCHAIN_SEM_IR_DEFAULT_VALUE_H_ diff --git a/toolchain/sem_ir/dump.cpp b/toolchain/sem_ir/dump.cpp index 17fb69847f6f..6cc6443c55f3 100644 --- a/toolchain/sem_ir/dump.cpp +++ b/toolchain/sem_ir/dump.cpp @@ -255,17 +255,6 @@ LLVM_DUMP_METHOD auto Dump(const File& file, CppOverloadSetId overload_set_id) return out.TakeStr(); } -LLVM_DUMP_METHOD auto Dump(const File& file, EntityNameId entity_name_id) - -> std::string { - RawStringOstream out; - out << entity_name_id; - if (entity_name_id.has_value()) { - auto entity_name = file.entity_names().Get(entity_name_id); - out << ": " << entity_name << DumpNameOfEntityName(file, entity_name); - } - return out.TakeStr(); -} - LLVM_DUMP_METHOD auto Dump(const File& file, DeclaredFacetTypeId declared_facet_type_id) -> std::string { @@ -314,6 +303,30 @@ LLVM_DUMP_METHOD auto Dump(const File& file, return out.TakeStr(); } +LLVM_DUMP_METHOD auto Dump(const File& file, DefaultValueId value_id) + -> std::string { + RawStringOstream out; + out << value_id; + if (value_id.has_value()) { + const auto& default_value = file.default_values().Get(value_id); + out << ": " << default_value + << "\n - raw: " << DumpInstSummary(file, default_value.raw_id) + << "\n - value: " << DumpInstSummary(file, default_value.value_id); + } + return out.TakeStr(); +} + +LLVM_DUMP_METHOD auto Dump(const File& file, EntityNameId entity_name_id) + -> std::string { + RawStringOstream out; + out << entity_name_id; + if (entity_name_id.has_value()) { + auto entity_name = file.entity_names().Get(entity_name_id); + out << ": " << entity_name << DumpNameOfEntityName(file, entity_name); + } + return out.TakeStr(); +} + LLVM_DUMP_METHOD auto Dump(const File& file, FieldId field_id) -> std::string { RawStringOstream out; out << field_id; @@ -655,6 +668,9 @@ LLVM_DUMP_METHOD static auto MakeConstantId(int id) -> ConstantId { LLVM_DUMP_METHOD auto MakeSymbolicConstantId(int id) -> ConstantId { return ConstantId::ForSymbolicConstantId(ConstantId::SymbolicId(id)); } +LLVM_DUMP_METHOD static auto MakeDefaultValueId(int id) -> DefaultValueId { + return DefaultValueId(id); +} LLVM_DUMP_METHOD static auto MakeEntityNameId(int id) -> EntityNameId { return EntityNameId(id); } diff --git a/toolchain/sem_ir/dump.h b/toolchain/sem_ir/dump.h index 818b453355bd..36acbb5c77cc 100644 --- a/toolchain/sem_ir/dump.h +++ b/toolchain/sem_ir/dump.h @@ -28,9 +28,10 @@ auto Dump(const File& file, GeneratedFunctionId generated_function_id) auto Dump(const File& file, ClassId class_id) -> std::string; auto Dump(const File& file, ConstantId const_id) -> std::string; auto Dump(const File& file, CppOverloadSetId overload_set_id) -> std::string; -auto Dump(const File& file, EntityNameId entity_name_id) -> std::string; auto Dump(const File& file, DeclaredFacetTypeId declared_facet_type_id) -> std::string; +auto Dump(const File& file, DefaultValueId default_value_id) -> std::string; +auto Dump(const File& file, EntityNameId entity_name_id) -> std::string; auto Dump(const File& file, FieldId field_id) -> std::string; auto Dump(const File& file, FunctionId function_id) -> std::string; auto Dump(const File& file, GenericId generic_id) -> std::string; diff --git a/toolchain/sem_ir/file.cpp b/toolchain/sem_ir/file.cpp index 0b6fa2cb63a8..041c7efc3ead 100644 --- a/toolchain/sem_ir/file.cpp +++ b/toolchain/sem_ir/file.cpp @@ -40,6 +40,7 @@ File::File(const Parse::Tree* parse_tree, CheckIRId check_ir_id, value_stores_(&value_stores), filename_(std::move(filename)), entity_names_(check_ir_id), + default_values_(check_ir_id), functions_(check_ir_id), generated_functions_(check_ir_id), cpp_overload_sets_(check_ir_id), @@ -160,6 +161,7 @@ auto File::OutputYaml(bool include_singletons) const -> Yaml::OutputMapping { map.Add("import_ir_insts", import_ir_insts_.OutputYaml()); map.Add("clang_decls", clang_decls_.OutputYaml()); map.Add("clang_decl_signatures", clang_decl_signatures_.OutputYaml()); + map.Add("default_values", default_values_.OutputYaml()); map.Add("name_scopes", name_scopes_.OutputYaml()); map.Add("entity_names", entity_names_.OutputYaml()); map.Add("functions", functions_.OutputYaml()); @@ -200,6 +202,8 @@ auto File::CollectMemUsage(MemUsage& mem_usage, llvm::StringRef label) const mem_usage.Collect(MemUsage::ConcatLabel(label, "functions_"), functions_); mem_usage.Collect(MemUsage::ConcatLabel(label, "thunks_"), thunks_); mem_usage.Collect(MemUsage::ConcatLabel(label, "classes_"), classes_); + mem_usage.Collect(MemUsage::ConcatLabel(label, "default_values_"), + default_values_); mem_usage.Collect(MemUsage::ConcatLabel(label, "interfaces_"), interfaces_); mem_usage.Collect(MemUsage::ConcatLabel(label, "impls_"), impls_); mem_usage.Collect(MemUsage::ConcatLabel(label, "generics_"), generics_); diff --git a/toolchain/sem_ir/file.h b/toolchain/sem_ir/file.h index 5219747dc481..8328bb0b4dc9 100644 --- a/toolchain/sem_ir/file.h +++ b/toolchain/sem_ir/file.h @@ -25,6 +25,7 @@ #include "toolchain/sem_ir/cpp_file.h" #include "toolchain/sem_ir/cpp_overload_set.h" #include "toolchain/sem_ir/declared_facet_type.h" +#include "toolchain/sem_ir/default_value.h" #include "toolchain/sem_ir/entity_name.h" #include "toolchain/sem_ir/field.h" #include "toolchain/sem_ir/function.h" @@ -222,6 +223,10 @@ class File : public Printable { auto declared_facet_types() const -> const DeclaredFacetTypeStore& { return declared_facet_types_; } + auto default_values() const -> const DefaultValueStore& { + return default_values_; + } + auto default_values() -> DefaultValueStore& { return default_values_; } // If `class_id` is an imported C++ class, appends the Clang mangled name of // its type to `out` and returns true. Otherwise returns false and leaves @@ -365,6 +370,9 @@ class File : public Printable { // Storage for EntityNames. EntityNameStore entity_names_; + // Storage for DefaultValues. + DefaultValueStore default_values_; + // Storage for callable objects. FunctionStore functions_; diff --git a/toolchain/sem_ir/formatter.cpp b/toolchain/sem_ir/formatter.cpp index 65dc93792e56..670d891495d0 100644 --- a/toolchain/sem_ir/formatter.cpp +++ b/toolchain/sem_ir/formatter.cpp @@ -598,17 +598,10 @@ auto Formatter::FormatFunction(FunctionId id, const Function& fn) -> void { out() << "]"; } - if (!fn.body_block_ids.empty() || - fn.call_param_default_values_id != SemIR::InstBlockId::Empty) { + if (!fn.body_block_ids.empty()) { out() << ' '; OpenBrace(); - if (fn.call_param_default_values_id != SemIR::InstBlockId::Empty) { - IndentLabel(); - out() << "!default_values:\n"; - FormatCodeBlock(fn.call_param_default_values_id); - } - for (auto block_id : fn.body_block_ids) { IndentLabel(); FormatLabel(block_id); @@ -1646,7 +1639,12 @@ auto Formatter::FormatArg(DeclaredFacetTypeId id) -> void { } auto Formatter::FormatArg(DefaultValueId id) -> void { - out() << "index: " << id.index; + const auto& default_value = sem_ir_->default_values().Get(id); + if (default_value.is_unspecified) { + out() << ""; + } else { + FormatArg(default_value.value_id); + } } auto Formatter::FormatArg(FieldId id) -> void { diff --git a/toolchain/sem_ir/function.h b/toolchain/sem_ir/function.h index 18338ef0fe78..52ec547d89b3 100644 --- a/toolchain/sem_ir/function.h +++ b/toolchain/sem_ir/function.h @@ -82,9 +82,6 @@ struct FunctionFields { // because it is relevant only for a function definition. InstBlockId call_params_id; - // Instructions representing the default values for parameters. - InstBlockId call_param_default_values_id; - // The index ranges within the `Call` parameters that correspond to the // implicit parameters, explicit parameters, and return. // @@ -234,9 +231,6 @@ struct Function : public EntityWithParamsBase, if (call_params_id.has_value()) { out << ", call_params_id: " << call_params_id; } - if (call_param_default_values_id != SemIR::InstBlockId::Empty) { - out << ", call_param_default_values_id: " << call_param_default_values_id; - } if (return_type_inst_id.has_value()) { out << ", return_type_inst_id: " << return_type_inst_id; } diff --git a/toolchain/sem_ir/ids.h b/toolchain/sem_ir/ids.h index 93d5c0e4ad28..ba0539a3f63c 100644 --- a/toolchain/sem_ir/ids.h +++ b/toolchain/sem_ir/ids.h @@ -116,11 +116,11 @@ class AbsoluteInstId : public InstId { using InstId::InstId; }; -// An id representing the index of the default value constant instruction in -// a default values instruction block. +// The ID of a default value. class DefaultValueId : public IdBase { public: - static constexpr llvm::StringLiteral Label = "default_value_id"; + static constexpr llvm::StringLiteral Label = "default_value"; + using IdBase::IdBase; }; diff --git a/toolchain/sem_ir/yaml_test.cpp b/toolchain/sem_ir/yaml_test.cpp index 38da393cd779..f5e0b447e75f 100644 --- a/toolchain/sem_ir/yaml_test.cpp +++ b/toolchain/sem_ir/yaml_test.cpp @@ -62,6 +62,7 @@ TEST(SemIRTest, Yaml) { Pair("import_ir_insts", Yaml::Mapping(SizeIs(0))), Pair("clang_decls", Yaml::Mapping(SizeIs(0))), Pair("clang_decl_signatures", Yaml::Mapping(SizeIs(0))), + Pair("default_values", Yaml::Mapping(SizeIs(0))), Pair("name_scopes", Yaml::Mapping(SizeIs(1))), Pair("entity_names", Yaml::Mapping(SizeIs(1))), Pair("functions", Yaml::Mapping(SizeIs(1))),