diff --git a/toolchain/check/cpp/import.cpp b/toolchain/check/cpp/import.cpp index fa56ed9e8529..753303875f24 100644 --- a/toolchain/check/cpp/import.cpp +++ b/toolchain/check/cpp/import.cpp @@ -1982,7 +1982,7 @@ 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::None, + .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/full_pattern_stack.h b/toolchain/check/full_pattern_stack.h index 479d832effe7..ba30486e8ea3 100644 --- a/toolchain/check/full_pattern_stack.h +++ b/toolchain/check/full_pattern_stack.h @@ -121,7 +121,8 @@ class FullPatternStack { CARBON_CHECK(kind_stack_.back() == Kind::NotInEitherParamList, "{0}", kind_stack_.back()); kind_stack_.back() = Kind::ExplicitParamList; - default_values_stack_.PushArray(); + raw_default_values_stack_.PushArray(); + converted_default_values_stack_.PushArray(); } // Marks the end of the current parameterized entity's explicit parameter @@ -149,7 +150,8 @@ class FullPatternStack { "`GetLocalVarStorage` not called for all var patterns"); var_pattern_stack_.PopArray(); if (kind == Kind::ExplicitParamList) { - default_values_stack_.PopArray(); + raw_default_values_stack_.PopArray(); + converted_default_values_stack_.PopArray(); } } @@ -205,26 +207,51 @@ class FullPatternStack { kind_stack_.size()); } - // Adds the inst id for a constant value provided as a default value for - // any subpattern in the full-pattern. Returns the index of that element + // 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 AddDefaultValue(SemIR::InstId inst_id) -> SemIR::DefaultValueId { - auto index = SemIR::FromRaw( - static_cast(default_values_stack_.PeekArray().size())); + auto AddRawDefaultValue(SemIR::InstId inst_id) -> SemIR::DefaultValueId { CARBON_CHECK(kind_stack_.back() == Kind::ExplicitParamList); - default_values_stack_.AppendToTop(inst_id); - return index; + return AddDefaultValue(inst_id, raw_default_values_stack_); } - // Returns a reference to the array of default value inst ids at the top of - // the stack. Note default values are only supported for explicit parameter + // 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 GetDefaultValues() -> llvm::ArrayRef { - return default_values_stack_.PeekArray(); + 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(); } 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 @@ -257,8 +284,15 @@ class FullPatternStack { llvm::SmallVector next_var_index_stack_; // The stack of instructions specifying default values for subpatterns - // within this full-pattern. - ArrayStack default_values_stack_; + // 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_; }; } // namespace Carbon::Check diff --git a/toolchain/check/function.cpp b/toolchain/check/function.cpp index 83cc40d4f4a8..b5229c9af9c1 100644 --- a/toolchain/check/function.cpp +++ b/toolchain/check/function.cpp @@ -91,7 +91,7 @@ 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::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; @@ -305,100 +305,60 @@ static auto CheckFunctionEvaluationModeMatches( return false; } -// Given a parameter patterns block, extracts the locations of all -// `SemIR::DefaultValuePattern` instructions and returns them in an array. -static auto ExtractDefaultValueLocations(Context& context, - SemIR::InstBlockId param_patterns_id) - -> llvm::SmallVector { - llvm::SmallVector locations; - for (auto inst_id : context.inst_blocks().GetOrEmpty(param_patterns_id)) { - if (context.insts().Is(inst_id)) { - locations.push_back(SemIR::LocId(inst_id)); +// 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 locations; + + return true; } // Checks every parameter in `prev_function` and `new_function`, that if they -// both specify a default value those values are identical, or that at most -// one has an unspecified default value. If `diagnose` is true, issues -// diagnostics where either condition is violated. Returns true if every -// parameter met both criteria. +// 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 { - // Both functions must either have defaults or not. - CARBON_CHECK(prev_function.call_param_default_values_id.has_value() == - new_function.call_param_default_values_id.has_value()); + 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); - if (!prev_function.call_param_default_values_id.has_value()) { - return true; - } - - auto prev_value_inst_ids = - context.inst_blocks().Get(prev_function.call_param_default_values_id); - auto new_value_inst_ids = - context.inst_blocks().Get(new_function.call_param_default_values_id); - CARBON_CHECK(prev_value_inst_ids.size() == new_value_inst_ids.size()); - - llvm::SmallVector indices_without_values; - llvm::SmallVector indices_with_different_values; - for (size_t i = 0; i < prev_value_inst_ids.size(); ++i) { - bool prev_value_specified = - !context.insts().Is(prev_value_inst_ids[i]); - bool new_value_specified = - !context.insts().Is(new_value_inst_ids[i]); - if (!prev_value_specified && !new_value_specified) { - indices_without_values.push_back(i); - } else if (prev_value_specified && new_value_specified) { - auto prev_constant_id = TryEvalInst(context, prev_value_inst_ids[i]); - CARBON_CHECK(prev_constant_id != SemIR::ConstantId::NotConstant); - auto new_constant_id = TryEvalInst(context, new_value_inst_ids[i]); - CARBON_CHECK(new_constant_id != SemIR::ConstantId::NotConstant); - if (prev_constant_id != new_constant_id) { - indices_with_different_values.push_back(i); - } - } - } - - bool check_ok = - indices_without_values.empty() && indices_with_different_values.empty(); - - if (check_ok || !diagnose) { - return check_ok; - } - - // TODO: for imported functions we don't seem to have the previous parameter - // pattern block, so we can't add their locations to the diagnostic. - auto prev_param_locations = - ExtractDefaultValueLocations(context, prev_function.param_patterns_id); - auto new_param_locations = - ExtractDefaultValueLocations(context, new_function.param_patterns_id); - - for (auto index : indices_without_values) { - CARBON_DIAGNOSTIC(PatternDefaultValueNeverSpecified, Error, - "no value for default number {0} is ever specified.", - size_t); - CARBON_DIAGNOSTIC(PatternDefaultValueNeverSpecifiedNote, Note, - "previous declaration here."); - auto builder = context.emitter().Build( - new_param_locations[index], PatternDefaultValueNeverSpecified, index); - if (index < prev_param_locations.size()) { - builder.Note(prev_param_locations[index], - PatternDefaultValueNeverSpecifiedNote); - } - builder.Emit(); - } - - for (auto index : indices_with_different_values) { - CARBON_DIAGNOSTIC(PatternDefaultValueDiffers, Error, - "default value differs from the previous declaration."); - context.emitter().Emit(new_param_locations[index], - PatternDefaultValueDiffers); - } - - return false; + 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, diff --git a/toolchain/check/global_init.cpp b/toolchain/check/global_init.cpp index 25700d0a35f0..f95ccfef9d45 100644 --- a/toolchain/check/global_init.cpp +++ b/toolchain/check/global_init.cpp @@ -51,7 +51,7 @@ 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::None, + .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 a325d718c7ba..0eb5af6f1464 100644 --- a/toolchain/check/handle_function.cpp +++ b/toolchain/check/handle_function.cpp @@ -373,6 +373,25 @@ static auto DiagnosePositionalParams(Context& context, function_info.param_patterns_id = SemIR::InstBlockId::Empty; } +// Diagnoses that the default values for function parameters have 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) { + CARBON_DIAGNOSTIC(PatternDefaultValueNotSpecified, Error, + "found unspecified default parameter value in the " + "function's first owning declaration"); + context.emitter().Emit(inst_id, PatternDefaultValueNotSpecified); + } +} + // Build a FunctionDecl describing the signature of a function. This // handles the common logic shared by function declaration syntax and function // definition syntax. @@ -457,6 +476,10 @@ 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); + } TryMergeRedecl( context, name_context, std::nullopt, diff --git a/toolchain/check/handle_impl.cpp b/toolchain/check/handle_impl.cpp index d668cc3578dd..3b2d891f9246 100644 --- a/toolchain/check/handle_impl.cpp +++ b/toolchain/check/handle_impl.cpp @@ -200,7 +200,7 @@ 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::None, + .call_param_default_values_id = SemIR::InstBlockId::Empty, .param_ranges = SemIR::Function::CallParamIndexRanges::Empty, .pattern_block_id = pattern_block_id}; } diff --git a/toolchain/check/handle_pattern_list.cpp b/toolchain/check/handle_pattern_list.cpp index c6061f01d364..1f61a6099300 100644 --- a/toolchain/check/handle_pattern_list.cpp +++ b/toolchain/check/handle_pattern_list.cpp @@ -172,8 +172,6 @@ auto HandleParseNode(Context& context, auto HandleParseNode(Context& context, Parse::DefaultValuePatternId node_id) -> bool { - // On entry, the top of the node stack should have an expression for the - // default value. We evaluate it to get a constant. auto [expr_node_id, expr_inst_id] = context.node_stack().PopExprWithNodeId(); // Ensure we are in an explicit parameter list, otherwise issue a diagnostic. @@ -186,24 +184,21 @@ auto HandleParseNode(Context& context, Parse::DefaultValuePatternId node_id) return false; } - // Evaluate the default value constant. auto expr_const_id = TryEvalInst(context, expr_inst_id); if (expr_const_id == SemIR::ConstantId::NotConstant) { CARBON_DIAGNOSTIC(PatternDefaultValueNotConstant, Error, - "default value for pattern must be constant"); + "default value is not a constant"); context.emitter().Emit( LocIdForDiagnostics(context.insts().GetCanonicalLocId(expr_inst_id)), PatternDefaultValueNotConstant); return false; } - auto value_inst_id = context.constant_values().GetInstId(expr_const_id); - CARBON_CHECK(value_inst_id.has_value()); - // Add the value to the default values array in the full pattern stack, for - // recovery later in the NameComponent. + // recovery later in the NameComponent. 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().AddDefaultValue(value_inst_id); + context.full_pattern_stack().AddRawDefaultValue(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 56cac593ae7b..8900b155b80a 100644 --- a/toolchain/check/import_ref.cpp +++ b/toolchain/check/import_ref.cpp @@ -2425,7 +2425,7 @@ 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::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, @@ -2573,15 +2573,6 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver, resolver, import_function.call_param_patterns_id); auto call_param_default_values = GetLocalBlockImportRefInfo( resolver, import_function.call_param_default_values_id); - llvm::SmallVector imported_default_values; - if (call_param_default_values.has_value()) { - auto import_fn = [&resolver](const auto& import_info) { - return GetLocalConstantInstId(resolver, import_info.import_inst_id); - }; - llvm::append_range(imported_default_values, - llvm::map_range(*call_param_default_values, import_fn)); - } - auto return_type_const_id = SemIR::ConstantId::None; if (import_function.return_type_inst_id.has_value()) { return_type_const_id = @@ -2633,7 +2624,7 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver, AddLoadedImportRefBlock(resolver, call_param_patterns); if (call_param_default_values.has_value()) { new_function.call_param_default_values_id = - resolver.local_inst_blocks().Add(imported_default_values); + AddLoadedImportRefBlock(resolver, *call_param_default_values); } new_function.parent_scope_id = parent_scope_id; new_function.implicit_param_patterns_id = diff --git a/toolchain/check/merge.cpp b/toolchain/check/merge.cpp index d1e585019b35..296cb0a6beeb 100644 --- a/toolchain/check/merge.cpp +++ b/toolchain/check/merge.cpp @@ -693,43 +693,6 @@ static auto FillPrevEntityInfo(Context& context, } } -// Updates the default values in `prev_function` to include any of those not -// previously specified and that are now specified in `new_function`. -static auto MergeFunctionParamDefaultValues(Context& context, - SemIR::Function& prev_function, - const SemIR::Function& new_function) - -> void { - CARBON_CHECK(prev_function.call_param_default_values_id.has_value() == - new_function.call_param_default_values_id.has_value()); - if (!prev_function.call_param_default_values_id.has_value()) { - return; - } - - auto prev_value_inst_ids = - context.inst_blocks().Get(prev_function.call_param_default_values_id); - auto new_value_inst_ids = - context.inst_blocks().Get(new_function.call_param_default_values_id); - CARBON_CHECK(prev_value_inst_ids.size() == new_value_inst_ids.size()); - - llvm::SmallVector merged_value_inst_ids; - bool merge_has_new_info = false; - merged_value_inst_ids.reserve(prev_value_inst_ids.size()); - - for (size_t i = 0; i < prev_value_inst_ids.size(); ++i) { - bool had_value = - !context.insts().Is(prev_value_inst_ids[i]); - auto merged_id = had_value ? prev_value_inst_ids[i] : new_value_inst_ids[i]; - merge_has_new_info |= - !had_value && !context.insts().Is(merged_id); - merged_value_inst_ids.push_back(merged_id); - } - - if (merge_has_new_info) { - auto merged_block_id = context.inst_blocks().Add(merged_value_inst_ids); - prev_function.call_param_default_values_id = merged_block_id; - } -} - template auto TryMergeRedecl(Context& context, const DeclNameStack::NameContext& name_context, @@ -904,10 +867,6 @@ auto TryMergeRedecl(Context& context, if (is_definition) { prev_entity.MergeDefinition(entity_info.new_entity); - if constexpr (IsFunction) { - MergeFunctionParamDefaultValues(context, prev_entity, - entity_info.new_entity); - } } auto replace_prev_inst = prev_import_ir_id.has_value(); diff --git a/toolchain/check/name_component.cpp b/toolchain/check/name_component.cpp index 634d72772e42..89190863e256 100644 --- a/toolchain/check/name_component.cpp +++ b/toolchain/check/name_component.cpp @@ -13,7 +13,6 @@ auto PopNameComponent(Context& context, SemIR::InstId return_pattern_id) -> NameComponent { Parse::NodeId first_param_node_id = Parse::NoneNodeId(); Parse::NodeId last_param_node_id = Parse::NoneNodeId(); - auto call_param_default_values_id = SemIR::InstBlockId::None; // Explicit params. auto [params_node_id, param_patterns_id] = @@ -24,10 +23,6 @@ auto PopNameComponent(Context& context, SemIR::InstId return_pattern_id) context.node_stack() .PopForSoloNodeId(); last_param_node_id = params_node_id; - if (!context.full_pattern_stack().GetDefaultValues().empty()) { - call_param_default_values_id = context.inst_blocks().Add( - context.full_pattern_stack().GetDefaultValues()); - } } else { param_patterns_id = SemIR::InstBlockId::None; } @@ -50,6 +45,7 @@ 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; @@ -61,6 +57,11 @@ 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()); pattern_block_id = context.pattern_block_stack().Pop(); context.full_pattern_stack().PopFullPattern(); } diff --git a/toolchain/check/pattern_match.cpp b/toolchain/check/pattern_match.cpp index 5c54a7c4e50e..7c1218a857b1 100644 --- a/toolchain/check/pattern_match.cpp +++ b/toolchain/check/pattern_match.cpp @@ -952,7 +952,7 @@ auto MatchContext::DoPreWork(State state, auto MatchContext::DoPostWork(State state, SemIR::DefaultValuePattern default_value_pattern, - WorkItem entry) -> void { + WorkItem /*entry*/) -> void { if (!std::holds_alternative(state)) { CARBON_FATAL("Unhandled state kind in DefaultValuePattern post-work"); } @@ -960,30 +960,24 @@ auto MatchContext::DoPostWork(State state, auto param_inst_id = results_stack_.PeekArray().back(); auto param_type_id = context_.insts().Get(param_inst_id).type_id(); - auto default_value_inst_id = - context_.full_pattern_stack() - .GetDefaultValues()[default_value_pattern.default_value_id.index]; // If a constant was specified, we should be able to convert it into the // type of the parameter. - if (!context_.insts().Is(default_value_inst_id)) { - // We should be able to convert the supplied constant into the type of - // the parameter. - auto converted_id = - TryConvertToValueOfType(context_, SemIR::LocId(default_value_inst_id), - default_value_inst_id, param_type_id); - if (converted_id == SemIR::ErrorInst::InstId) { - CARBON_DIAGNOSTIC( - PatternDefaultValueTypeMismatch, Error, - "default value expression type {0} doesn't match pattern type {1}", - TypeOfInstId, TypeOfInstId); + 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); - // TODO: should be able to provide precise locations for both default - // value expression and the type of the pattern, but we can't because - // they are both constants. - context_.emitter().Emit(entry.pattern_id, PatternDefaultValueTypeMismatch, - default_value_inst_id, param_inst_id); - } - } results_stack_.PopArray(); // If something at a higher level in the stack needed these results, bubble diff --git a/toolchain/check/testdata/function/declaration/default_values.carbon b/toolchain/check/testdata/function/declaration/default_values.carbon index 19861710a2db..6d653dc66839 100644 --- a/toolchain/check/testdata/function/declaration/default_values.carbon +++ b/toolchain/check/testdata/function/declaration/default_values.carbon @@ -2,8 +2,7 @@ // Exceptions. See /LICENSE for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // -// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/primitives.carbon -// EXTRA-ARGS: --dump-sem-ir-ranges=only +// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon // // AUTOUPDATE // TIP: To test this file alone, run: @@ -14,206 +13,355 @@ // --- fail_value_not_constant.carbon library "[[@TEST_NAME]]"; -// CHECK:STDERR: fail_value_not_constant.carbon:[[@LINE+4]]:23: error: default value for pattern must be constant [PatternDefaultValueNotConstant] -// CHECK:STDERR: fn H(x: i32, y: i32 = x); -// CHECK:STDERR: ^ +class C {} + +// CHECK:STDERR: fail_value_not_constant.carbon:[[@LINE+4]]:19: error: default value is not a constant [PatternDefaultValueNotConstant] +// CHECK:STDERR: fn H(x: C, y: C = x); +// CHECK:STDERR: ^ // CHECK:STDERR: -fn H(x: i32, y: i32 = x); +fn H(x: C, y: C = x); // --- fail_type_mismatch.carbon library "[[@TEST_NAME]]"; -// CHECK:STDERR: fail_type_mismatch.carbon:[[@LINE+4]]:6: error: default value expression type `str` doesn't match pattern type `i32` [PatternDefaultValueTypeMismatch] -// CHECK:STDERR: fn K(x: i32 = "bazz"); -// CHECK:STDERR: ^~~~~~~~~~~~~~~ +class C {} +class D {} + +// CHECK:STDERR: fail_type_mismatch.carbon:[[@LINE+7]]:13: error: cannot implicitly convert expression of type `D` to `C` [ConversionFailure] +// CHECK:STDERR: fn K(x: C = {} as D); +// CHECK:STDERR: ^~~~~~~ +// CHECK:STDERR: fail_type_mismatch.carbon:[[@LINE+4]]:13: note: type `D` does not implement interface `Core.ImplicitAs(C)` [MissingImplInMemberAccessInContext] +// CHECK:STDERR: fn K(x: C = {} as D); +// CHECK:STDERR: ^~~~~~~ // CHECK:STDERR: -fn K(x: i32 = "bazz"); +fn K(x: C = {} as D); // --- fail_pattern_defaults_not_in_parameter_list.carbon library "[[@TEST_NAME]]"; -// CHECK:STDERR: fail_pattern_defaults_not_in_parameter_list.carbon:[[@LINE+4]]:23: error: default values are only supported in parameter lists [PatternDefaultValueNotInParameterList] -// CHECK:STDERR: let (y: i32, x: i32 = 0) = (1, 2); -// CHECK:STDERR: ^ +class C {} + +// CHECK:STDERR: fail_pattern_defaults_not_in_parameter_list.carbon:[[@LINE+4]]:19: error: default values are only supported in parameter lists [PatternDefaultValueNotInParameterList] +// CHECK:STDERR: let (y: C, x: C = {}) = ({}, {}); +// CHECK:STDERR: ^~ // CHECK:STDERR: -let (y: i32, x: i32 = 0) = (1, 2); +let (y: C, x: C = {}) = ({}, {}); + +// --- fail_default_values_unspecified.carbon +library "[[@TEST_NAME]]"; + +class C {} + +// CHECK:STDERR: fail_default_values_unspecified.carbon:[[@LINE+4]]:24: error: found unspecified default parameter value in the function's first owning declaration [PatternDefaultValueNotSpecified] +// CHECK:STDERR: fn Z(x: C = {}, y: C = _); +// CHECK:STDERR: ^ +// CHECK:STDERR: +fn Z(x: C = {}, y: C = _); // --- fail_required_default_values_missing.carbon library "[[@TEST_NAME]]"; -// CHECK:STDERR: fail_required_default_values_missing.carbon:[[@LINE+17]]:39: error: this pattern is missing a required default value. [RequiredPatternDefaultValueMissing] -// CHECK:STDERR: fn Z(v: i32, x: i32 = 3, (y: i32 = 2, z: i32), w: i32 = 4, k: i32); -// CHECK:STDERR: ^~~~~~ -// CHECK:STDERR: fail_required_default_values_missing.carbon:[[@LINE+14]]:27: note: all patterns to the right of this first pattern with a default value must also specify a default value. [RequiredPatternDefaultValueFirstDefault] -// CHECK:STDERR: fn Z(v: i32, x: i32 = 3, (y: i32 = 2, z: i32), w: i32 = 4, k: i32); -// CHECK:STDERR: ^~~~~~ +class C {} + +// CHECK:STDERR: fail_required_default_values_missing.carbon:[[@LINE+17]]:35: error: this pattern is missing a required default value. [RequiredPatternDefaultValueMissing] +// CHECK:STDERR: fn Z(v: C, x: C = {}, (y: C = {}, z: C), w: C = {}, k: C); +// CHECK:STDERR: ^~~~ +// CHECK:STDERR: fail_required_default_values_missing.carbon:[[@LINE+14]]:24: note: all patterns to the right of this first pattern with a default value must also specify a default value. [RequiredPatternDefaultValueFirstDefault] +// CHECK:STDERR: fn Z(v: C, x: C = {}, (y: C = {}, z: C), w: C = {}, k: C); +// CHECK:STDERR: ^~~~ // CHECK:STDERR: -// CHECK:STDERR: fail_required_default_values_missing.carbon:[[@LINE+10]]:26: error: this pattern is missing a required default value. [RequiredPatternDefaultValueMissing] -// CHECK:STDERR: fn Z(v: i32, x: i32 = 3, (y: i32 = 2, z: i32), w: i32 = 4, k: i32); -// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~ -// CHECK:STDERR: fail_required_default_values_missing.carbon:[[@LINE+7]]:60: note: this pattern is also missing a required default value. [RequiredPatternDefaultValueMissingAdditional] -// CHECK:STDERR: fn Z(v: i32, x: i32 = 3, (y: i32 = 2, z: i32), w: i32 = 4, k: i32); -// CHECK:STDERR: ^~~~~~ -// CHECK:STDERR: fail_required_default_values_missing.carbon:[[@LINE+4]]:14: note: all patterns to the right of this first pattern with a default value must also specify a default value. [RequiredPatternDefaultValueFirstDefault] -// CHECK:STDERR: fn Z(v: i32, x: i32 = 3, (y: i32 = 2, z: i32), w: i32 = 4, k: i32); -// CHECK:STDERR: ^~~~~~ +// CHECK:STDERR: fail_required_default_values_missing.carbon:[[@LINE+10]]:23: error: this pattern is missing a required default value. [RequiredPatternDefaultValueMissing] +// CHECK:STDERR: fn Z(v: C, x: C = {}, (y: C = {}, z: C), w: C = {}, k: C); +// CHECK:STDERR: ^~~~~~~~~~~~~~~~~ +// CHECK:STDERR: fail_required_default_values_missing.carbon:[[@LINE+7]]:53: note: this pattern is also missing a required default value. [RequiredPatternDefaultValueMissingAdditional] +// CHECK:STDERR: fn Z(v: C, x: C = {}, (y: C = {}, z: C), w: C = {}, k: C); +// CHECK:STDERR: ^~~~ +// CHECK:STDERR: fail_required_default_values_missing.carbon:[[@LINE+4]]:12: note: all patterns to the right of this first pattern with a default value must also specify a default value. [RequiredPatternDefaultValueFirstDefault] +// CHECK:STDERR: fn Z(v: C, x: C = {}, (y: C = {}, z: C), w: C = {}, k: C); +// CHECK:STDERR: ^~~~ // CHECK:STDERR: -fn Z(v: i32, x: i32 = 3, (y: i32 = 2, z: i32), w: i32 = 4, k: i32); +fn Z(v: C, x: C = {}, (y: C = {}, z: C), w: C = {}, k: C); // --- fail_nesting_required_default_values_missing.carbon library "[[@TEST_NAME]]"; -// CHECK:STDERR: fail_nesting_required_default_values_missing.carbon:[[@LINE+14]]:40: error: this pattern is missing a required default value. [RequiredPatternDefaultValueMissing] -// CHECK:STDERR: fn F(a: i32, (b: i32 = 0, (c: i32 = 0, (d: i32, e: i32)))); -// CHECK:STDERR: ^~~~~~~~~~~~~~~~ -// CHECK:STDERR: fail_nesting_required_default_values_missing.carbon:[[@LINE+11]]:28: note: all patterns to the right of this first pattern with a default value must also specify a default value. [RequiredPatternDefaultValueFirstDefault] -// CHECK:STDERR: fn F(a: i32, (b: i32 = 0, (c: i32 = 0, (d: i32, e: i32)))); -// CHECK:STDERR: ^~~~~~ +class C {} + +// CHECK:STDERR: fail_nesting_required_default_values_missing.carbon:[[@LINE+14]]:36: error: this pattern is missing a required default value. [RequiredPatternDefaultValueMissing] +// CHECK:STDERR: fn F(a: C, (b: C = {}, (c: C = {}, (d: C, e: C)))); +// CHECK:STDERR: ^~~~~~~~~~~~ +// CHECK:STDERR: fail_nesting_required_default_values_missing.carbon:[[@LINE+11]]:25: note: all patterns to the right of this first pattern with a default value must also specify a default value. [RequiredPatternDefaultValueFirstDefault] +// CHECK:STDERR: fn F(a: C, (b: C = {}, (c: C = {}, (d: C, e: C)))); +// CHECK:STDERR: ^~~~ // CHECK:STDERR: -// CHECK:STDERR: fail_nesting_required_default_values_missing.carbon:[[@LINE+7]]:27: error: this pattern is missing a required default value. [RequiredPatternDefaultValueMissing] -// CHECK:STDERR: fn F(a: i32, (b: i32 = 0, (c: i32 = 0, (d: i32, e: i32)))); -// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// CHECK:STDERR: fail_nesting_required_default_values_missing.carbon:[[@LINE+4]]:15: note: all patterns to the right of this first pattern with a default value must also specify a default value. [RequiredPatternDefaultValueFirstDefault] -// CHECK:STDERR: fn F(a: i32, (b: i32 = 0, (c: i32 = 0, (d: i32, e: i32)))); -// CHECK:STDERR: ^~~~~~ +// CHECK:STDERR: fail_nesting_required_default_values_missing.carbon:[[@LINE+7]]:24: error: this pattern is missing a required default value. [RequiredPatternDefaultValueMissing] +// CHECK:STDERR: fn F(a: C, (b: C = {}, (c: C = {}, (d: C, e: C)))); +// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~ +// CHECK:STDERR: fail_nesting_required_default_values_missing.carbon:[[@LINE+4]]:13: note: all patterns to the right of this first pattern with a default value must also specify a default value. [RequiredPatternDefaultValueFirstDefault] +// CHECK:STDERR: fn F(a: C, (b: C = {}, (c: C = {}, (d: C, e: C)))); +// CHECK:STDERR: ^~~~ // CHECK:STDERR: -fn F(a: i32, (b: i32 = 0, (c: i32 = 0, (d: i32, e: i32)))); +fn F(a: C, (b: C = {}, (c: C = {}, (d: C, e: C)))); + +// --- fail_explicit_conversion_not_supported.carbon +library "[[@TEST_NAME]]"; + +class C {} +class D {} +impl C as Core.As(D) { + fn Convert(unused self: C) -> D { return {} as D; } +} + +// CHECK:STDERR: fail_explicit_conversion_not_supported.carbon:[[@LINE+7]]:13: error: cannot implicitly convert expression of type `C` to `D` [ConversionFailure] +// CHECK:STDERR: fn F(a: D = {} as C); +// CHECK:STDERR: ^~~~~~~ +// CHECK:STDERR: fail_explicit_conversion_not_supported.carbon:[[@LINE+4]]:13: note: type `C` does not implement interface `Core.ImplicitAs(D)` [MissingImplInMemberAccessInContext] +// CHECK:STDERR: fn F(a: D = {} as C); +// CHECK:STDERR: ^~~~~~~ +// CHECK:STDERR: +fn F(a: D = {} as C); + +// --- implicit.carbon +library "[[@TEST_NAME]]"; + +class C {} +class D {} +impl C as Core.ImplicitAs(D) { + fn Convert(self: C) -> D { return self; } +} + +//@dump-sem-ir-begin +fn F(a: D = {} as C); +//@dump-sem-ir-end // --- nested.carbon library "[[@TEST_NAME]]"; +class C {} + //@dump-sem-ir-begin -fn F(a: i32, (b: i32, (c: i32, (d: i32, e: i32))) = (1, (2, (3, 4)))); +fn F(a: C, (b: C, (c: C, (d: C, e: C))) = ({}, ({}, ({}, {})))); //@dump-sem-ir-end // --- basic.carbon library "[[@TEST_NAME]]"; +class C {} + //@dump-sem-ir-begin -fn F(x: i32 = 0); +fn F(x: C = {}); //@dump-sem-ir-end -// CHECK:STDOUT: --- nested.carbon +// CHECK:STDOUT: --- implicit.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { -// CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete] -// CHECK:STDOUT: %i32: type = class_type @Int, @Int(%int_32) [concrete] -// CHECK:STDOUT: %pattern_type.6b6: type = pattern_type %i32 [concrete] -// CHECK:STDOUT: %a.param_patt: %pattern_type.6b6 = value_param_pattern [concrete] -// CHECK:STDOUT: %a.patt: %pattern_type.6b6 = wrapper_binding_pattern a, %a.param_patt [concrete] -// CHECK:STDOUT: %b.param_patt: %pattern_type.6b6 = value_param_pattern [concrete] -// CHECK:STDOUT: %b.patt: %pattern_type.6b6 = wrapper_binding_pattern b, %b.param_patt [concrete] -// CHECK:STDOUT: %c.param_patt: %pattern_type.6b6 = value_param_pattern [concrete] -// CHECK:STDOUT: %c.patt: %pattern_type.6b6 = wrapper_binding_pattern c, %c.param_patt [concrete] -// CHECK:STDOUT: %d.param_patt: %pattern_type.6b6 = value_param_pattern [concrete] -// CHECK:STDOUT: %d.patt: %pattern_type.6b6 = wrapper_binding_pattern d, %d.param_patt [concrete] -// CHECK:STDOUT: %e.param_patt: %pattern_type.6b6 = value_param_pattern [concrete] -// CHECK:STDOUT: %e.patt: %pattern_type.6b6 = wrapper_binding_pattern e, %e.param_patt [concrete] -// CHECK:STDOUT: %tuple.type.e55: type = tuple_type (%i32, %i32) [concrete] -// CHECK:STDOUT: %pattern_type.394: type = pattern_type %tuple.type.e55 [concrete] -// CHECK:STDOUT: %.70d: %pattern_type.394 = tuple_pattern (%d.patt, %e.patt) [concrete] -// CHECK:STDOUT: %tuple.type.920: type = tuple_type (%i32, %tuple.type.e55) [concrete] -// CHECK:STDOUT: %pattern_type.e87: type = pattern_type %tuple.type.920 [concrete] -// CHECK:STDOUT: %.aa9: %pattern_type.e87 = tuple_pattern (%c.patt, %.70d) [concrete] -// CHECK:STDOUT: %tuple.type.007: type = tuple_type (%i32, %tuple.type.920) [concrete] -// CHECK:STDOUT: %pattern_type.802: type = pattern_type %tuple.type.007 [concrete] -// CHECK:STDOUT: %.203: %pattern_type.802 = tuple_pattern (%b.patt, %.aa9) [concrete] -// CHECK:STDOUT: %int_1.5b8: Core.IntLiteral = int_value 1 [concrete] -// CHECK:STDOUT: %int_2.ecc: Core.IntLiteral = int_value 2 [concrete] -// CHECK:STDOUT: %int_3.1ba: Core.IntLiteral = int_value 3 [concrete] -// CHECK:STDOUT: %int_4.0c1: Core.IntLiteral = int_value 4 [concrete] -// CHECK:STDOUT: %tuple.type.f94: type = tuple_type (Core.IntLiteral, Core.IntLiteral) [concrete] -// CHECK:STDOUT: %tuple.302: %tuple.type.f94 = tuple_value (%int_3.1ba, %int_4.0c1) [concrete] -// CHECK:STDOUT: %tuple.type.bd0: type = tuple_type (Core.IntLiteral, %tuple.type.f94) [concrete] -// CHECK:STDOUT: %tuple.b26: %tuple.type.bd0 = tuple_value (%int_2.ecc, %tuple.302) [concrete] -// CHECK:STDOUT: %tuple.type.c4f: type = tuple_type (Core.IntLiteral, %tuple.type.bd0) [concrete] -// CHECK:STDOUT: %tuple.326: %tuple.type.c4f = tuple_value (%int_1.5b8, %tuple.b26) [concrete] -// CHECK:STDOUT: %.19b: %pattern_type.802 = default_value_pattern %.203, index: 0 [concrete] +// CHECK:STDOUT: %C: type = class_type @C [concrete] +// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] +// CHECK:STDOUT: %D: type = class_type @D [concrete] +// CHECK:STDOUT: %ImplicitAs.type.2be: type = facet_type <@ImplicitAs, @ImplicitAs(%D)> [concrete] +// CHECK:STDOUT: %ImplicitAs.impl_witness: = impl_witness @C.as.ImplicitAs.impl.%ImplicitAs.impl_witness_table [concrete] +// CHECK:STDOUT: %pattern_type.d8d: type = pattern_type %D [concrete] +// CHECK:STDOUT: %C.as.ImplicitAs.impl.Convert.type: type = fn_type @C.as.ImplicitAs.impl.Convert [concrete] +// CHECK:STDOUT: %C.as.ImplicitAs.impl.Convert: %C.as.ImplicitAs.impl.Convert.type = struct_value () [concrete] +// CHECK:STDOUT: %ImplicitAs.facet: %ImplicitAs.type.2be = facet_value %C, (%ImplicitAs.impl_witness) [concrete] +// CHECK:STDOUT: %ImplicitAs.WithSelf.Convert.type.6cd: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%D, %ImplicitAs.facet) [concrete] +// CHECK:STDOUT: %.ee7: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.6cd, %ImplicitAs.facet [concrete] +// CHECK:STDOUT: %a.param_patt: %pattern_type.d8d = value_param_pattern [concrete] +// 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: %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] // CHECK:STDOUT: %F: %F.type = struct_value () [concrete] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: file { // CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [concrete = constants.%F] { -// CHECK:STDOUT: %a.param_patt: %pattern_type.6b6 = value_param_pattern [concrete = constants.%a.param_patt] -// CHECK:STDOUT: %a.patt: %pattern_type.6b6 = wrapper_binding_pattern a, %a.param_patt [concrete = constants.%a.patt] -// CHECK:STDOUT: %b.param_patt: %pattern_type.6b6 = value_param_pattern [concrete = constants.%b.param_patt] -// CHECK:STDOUT: %b.patt: %pattern_type.6b6 = wrapper_binding_pattern b, %b.param_patt [concrete = constants.%b.patt] -// CHECK:STDOUT: %c.param_patt: %pattern_type.6b6 = value_param_pattern [concrete = constants.%c.param_patt] -// CHECK:STDOUT: %c.patt: %pattern_type.6b6 = wrapper_binding_pattern c, %c.param_patt [concrete = constants.%c.patt] -// CHECK:STDOUT: %d.param_patt: %pattern_type.6b6 = value_param_pattern [concrete = constants.%d.param_patt] -// CHECK:STDOUT: %d.patt: %pattern_type.6b6 = wrapper_binding_pattern d, %d.param_patt [concrete = constants.%d.patt] -// CHECK:STDOUT: %e.param_patt: %pattern_type.6b6 = value_param_pattern [concrete = constants.%e.param_patt] -// CHECK:STDOUT: %e.patt: %pattern_type.6b6 = wrapper_binding_pattern e, %e.param_patt [concrete = constants.%e.patt] -// CHECK:STDOUT: %.loc4_47: %pattern_type.394 = tuple_pattern (%d.patt, %e.patt) [concrete = constants.%.70d] -// CHECK:STDOUT: %.loc4_48: %pattern_type.e87 = tuple_pattern (%c.patt, %.loc4_47) [concrete = constants.%.aa9] -// CHECK:STDOUT: %.loc4_49: %pattern_type.802 = tuple_pattern (%b.patt, %.loc4_48) [concrete = constants.%.203] -// CHECK:STDOUT: %.loc4_51: %pattern_type.802 = default_value_pattern %.loc4_49, index: 0 [concrete = constants.%.19b] +// 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: } { -// CHECK:STDOUT: %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8] -// CHECK:STDOUT: %int_2: Core.IntLiteral = int_value 2 [concrete = constants.%int_2.ecc] -// CHECK:STDOUT: %int_3: Core.IntLiteral = int_value 3 [concrete = constants.%int_3.1ba] -// CHECK:STDOUT: %int_4: Core.IntLiteral = int_value 4 [concrete = constants.%int_4.0c1] -// CHECK:STDOUT: %.loc4_66: %tuple.type.f94 = tuple_literal (%int_3, %int_4) [concrete = constants.%tuple.302] -// CHECK:STDOUT: %.loc4_67: %tuple.type.bd0 = tuple_literal (%int_2, %.loc4_66) [concrete = constants.%tuple.b26] -// CHECK:STDOUT: %.loc4_68: %tuple.type.c4f = tuple_literal (%int_1, %.loc4_67) [concrete = constants.%tuple.326] -// CHECK:STDOUT: %a.param: %i32 = value_param call_param0 -// CHECK:STDOUT: %i32.loc4_9: type = type_literal constants.%i32 [concrete = constants.%i32] -// CHECK:STDOUT: %a: %i32 = wrapper_binding a, %a.param -// CHECK:STDOUT: %b.param: %i32 = value_param call_param1 -// CHECK:STDOUT: %i32.loc4_18: type = type_literal constants.%i32 [concrete = constants.%i32] -// CHECK:STDOUT: %b: %i32 = wrapper_binding b, %b.param -// CHECK:STDOUT: %c.param: %i32 = value_param call_param2 -// CHECK:STDOUT: %i32.loc4_27: type = type_literal constants.%i32 [concrete = constants.%i32] -// CHECK:STDOUT: %c: %i32 = wrapper_binding c, %c.param -// CHECK:STDOUT: %d.param: %i32 = value_param call_param3 -// CHECK:STDOUT: %i32.loc4_36: type = type_literal constants.%i32 [concrete = constants.%i32] -// CHECK:STDOUT: %d: %i32 = wrapper_binding d, %d.param -// CHECK:STDOUT: %e.param: %i32 = value_param call_param4 -// CHECK:STDOUT: %i32.loc4_44: type = type_literal constants.%i32 [concrete = constants.%i32] -// CHECK:STDOUT: %e: %i32 = wrapper_binding e, %e.param -// CHECK:STDOUT: %tuple.loc4_47: %tuple.type.e55 = tuple_value (%d.param, %e.param) -// CHECK:STDOUT: %tuple.loc4_48: %tuple.type.920 = tuple_value (%c.param, %tuple.loc4_47) -// CHECK:STDOUT: %tuple.loc4_49: %tuple.type.007 = tuple_value (%b.param, %tuple.loc4_48) -// 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] +// CHECK:STDOUT: %.loc10_14.2: ref %C = temporary_storage +// CHECK:STDOUT: %.loc10_14.3: init %C to %.loc10_14.2 = class_init () [concrete = constants.%C.val] +// CHECK:STDOUT: %.loc10_16.1: init %C = converted %.loc10_14.1, %.loc10_14.3 [concrete = constants.%C.val] +// CHECK:STDOUT: %a.param: %D = value_param call_param0 +// CHECK:STDOUT: %D.ref: type = name_ref D, file.%D.decl [concrete = constants.%D] +// CHECK:STDOUT: %a: %D = wrapper_binding a, %a.param +// CHECK:STDOUT: %impl.elem0: %.ee7 = impl_witness_access constants.%ImplicitAs.impl_witness, element0 [concrete = constants.%C.as.ImplicitAs.impl.Convert] +// CHECK:STDOUT: %bound_method: = bound_method %.loc10_16.1, %impl.elem0 [concrete = constants.%C.as.ImplicitAs.impl.Convert.bound] +// CHECK:STDOUT: %.loc10_16.2: ref %D = temporary_storage +// CHECK:STDOUT: %.loc10_16.3: ref %C = temporary %.loc10_14.2, %.loc10_16.1 [concrete = constants.%.115] +// CHECK:STDOUT: %.loc10_16.4: %C = acquire_value %.loc10_16.3 [concrete = constants.%C.val] +// CHECK:STDOUT: %C.as.ImplicitAs.impl.Convert.call: init %D to %.loc10_16.2 = call %bound_method(%.loc10_16.4) +// CHECK:STDOUT: %.loc10_16.5: init %D = converted %.loc10_16.1, %C.as.ImplicitAs.impl.Convert.call +// CHECK:STDOUT: %.loc10_16.6: ref %D = temporary %.loc10_16.2, %.loc10_16.5 +// CHECK:STDOUT: %.loc10_16.7: %D = acquire_value %.loc10_16.6 // CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @F(%a.param: %i32, %b.param: %i32, %c.param: %i32, %d.param: %i32, %e.param: %i32) { +// CHECK:STDOUT: fn @F(%a.param: %D) { // CHECK:STDOUT: !default_values: -// CHECK:STDOUT: constants.%tuple.326: %tuple.type.c4f = tuple_value (constants.%int_1.5b8, constants.%tuple.b26) [concrete] +// CHECK:STDOUT: %.loc10_16.7: %D = acquire_value %.loc10_16.6 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- nested.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [concrete] +// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] +// CHECK:STDOUT: %pattern_type.98b: type = pattern_type %C [concrete] +// CHECK:STDOUT: %a.param_patt: %pattern_type.98b = value_param_pattern [concrete] +// CHECK:STDOUT: %a.patt: %pattern_type.98b = wrapper_binding_pattern a, %a.param_patt [concrete] +// CHECK:STDOUT: %b.param_patt: %pattern_type.98b = value_param_pattern [concrete] +// CHECK:STDOUT: %b.patt: %pattern_type.98b = wrapper_binding_pattern b, %b.param_patt [concrete] +// CHECK:STDOUT: %c.param_patt: %pattern_type.98b = value_param_pattern [concrete] +// CHECK:STDOUT: %c.patt: %pattern_type.98b = wrapper_binding_pattern c, %c.param_patt [concrete] +// CHECK:STDOUT: %d.param_patt: %pattern_type.98b = value_param_pattern [concrete] +// CHECK:STDOUT: %d.patt: %pattern_type.98b = wrapper_binding_pattern d, %d.param_patt [concrete] +// CHECK:STDOUT: %e.param_patt: %pattern_type.98b = value_param_pattern [concrete] +// CHECK:STDOUT: %e.patt: %pattern_type.98b = wrapper_binding_pattern e, %e.param_patt [concrete] +// CHECK:STDOUT: %tuple.type.748: type = tuple_type (%C, %C) [concrete] +// CHECK:STDOUT: %pattern_type.8b4: type = pattern_type %tuple.type.748 [concrete] +// CHECK:STDOUT: %.fe8: %pattern_type.8b4 = tuple_pattern (%d.patt, %e.patt) [concrete] +// CHECK:STDOUT: %tuple.type.d76: type = tuple_type (%C, %tuple.type.748) [concrete] +// CHECK:STDOUT: %pattern_type.4fa: type = pattern_type %tuple.type.d76 [concrete] +// CHECK:STDOUT: %.972: %pattern_type.4fa = tuple_pattern (%c.patt, %.fe8) [concrete] +// CHECK:STDOUT: %tuple.type.a40: type = tuple_type (%C, %tuple.type.d76) [concrete] +// CHECK:STDOUT: %pattern_type.f5f: type = pattern_type %tuple.type.a40 [concrete] +// CHECK:STDOUT: %.341: %pattern_type.f5f = tuple_pattern (%b.patt, %.972) [concrete] +// CHECK:STDOUT: %empty_struct: %empty_struct_type = struct_value () [concrete] +// CHECK:STDOUT: %tuple.type.b6b: type = tuple_type (%empty_struct_type, %empty_struct_type) [concrete] +// CHECK:STDOUT: %tuple.9a3: %tuple.type.b6b = tuple_value (%empty_struct, %empty_struct) [concrete] +// CHECK:STDOUT: %tuple.type.6ca: type = tuple_type (%empty_struct_type, %tuple.type.b6b) [concrete] +// 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: %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] +// CHECK:STDOUT: %tuple.109: %tuple.type.d76 = tuple_value (%C.val, %tuple.d3e) [concrete] +// CHECK:STDOUT: %tuple.800: %tuple.type.a40 = tuple_value (%C.val, %tuple.109) [concrete] +// CHECK:STDOUT: %F.type: type = fn_type @F [concrete] +// CHECK:STDOUT: %F: %F.type = struct_value () [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [concrete = constants.%F] { +// CHECK:STDOUT: %a.param_patt: %pattern_type.98b = value_param_pattern [concrete = constants.%a.param_patt] +// CHECK:STDOUT: %a.patt: %pattern_type.98b = wrapper_binding_pattern a, %a.param_patt [concrete = constants.%a.patt] +// CHECK:STDOUT: %b.param_patt: %pattern_type.98b = value_param_pattern [concrete = constants.%b.param_patt] +// CHECK:STDOUT: %b.patt: %pattern_type.98b = wrapper_binding_pattern b, %b.param_patt [concrete = constants.%b.patt] +// CHECK:STDOUT: %c.param_patt: %pattern_type.98b = value_param_pattern [concrete = constants.%c.param_patt] +// CHECK:STDOUT: %c.patt: %pattern_type.98b = wrapper_binding_pattern c, %c.param_patt [concrete = constants.%c.patt] +// CHECK:STDOUT: %d.param_patt: %pattern_type.98b = value_param_pattern [concrete = constants.%d.param_patt] +// CHECK:STDOUT: %d.patt: %pattern_type.98b = wrapper_binding_pattern d, %d.param_patt [concrete = constants.%d.patt] +// CHECK:STDOUT: %e.param_patt: %pattern_type.98b = value_param_pattern [concrete = constants.%e.param_patt] +// CHECK:STDOUT: %e.patt: %pattern_type.98b = wrapper_binding_pattern e, %e.param_patt [concrete = constants.%e.patt] +// 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: } { +// 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] +// CHECK:STDOUT: %.loc6_55.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct] +// CHECK:STDOUT: %.loc6_59.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct] +// CHECK:STDOUT: %.loc6_60.1: %tuple.type.b6b = tuple_literal (%.loc6_55.1, %.loc6_59.1) [concrete = constants.%tuple.9a3] +// CHECK:STDOUT: %.loc6_61.1: %tuple.type.6ca = tuple_literal (%.loc6_50.1, %.loc6_60.1) [concrete = constants.%tuple.56c] +// CHECK:STDOUT: %.loc6_62.1: %tuple.type.bcdf = tuple_literal (%.loc6_45.1, %.loc6_61.1) [concrete = constants.%tuple.4f4] +// CHECK:STDOUT: %a.param: %C = value_param call_param0 +// CHECK:STDOUT: %C.ref.loc6_9: type = name_ref C, file.%C.decl [concrete = constants.%C] +// CHECK:STDOUT: %a: %C = wrapper_binding a, %a.param +// CHECK:STDOUT: %b.param: %C = value_param call_param1 +// CHECK:STDOUT: %C.ref.loc6_16: type = name_ref C, file.%C.decl [concrete = constants.%C] +// CHECK:STDOUT: %b: %C = wrapper_binding b, %b.param +// CHECK:STDOUT: %c.param: %C = value_param call_param2 +// CHECK:STDOUT: %C.ref.loc6_23: type = name_ref C, file.%C.decl [concrete = constants.%C] +// CHECK:STDOUT: %c: %C = wrapper_binding c, %c.param +// CHECK:STDOUT: %d.param: %C = value_param call_param3 +// CHECK:STDOUT: %C.ref.loc6_30: type = name_ref C, file.%C.decl [concrete = constants.%C] +// CHECK:STDOUT: %d: %C = wrapper_binding d, %d.param +// CHECK:STDOUT: %e.param: %C = value_param call_param4 +// CHECK:STDOUT: %C.ref.loc6_36: type = name_ref C, file.%C.decl [concrete = constants.%C] +// CHECK:STDOUT: %e: %C = wrapper_binding e, %e.param +// CHECK:STDOUT: %tuple.loc6_37: %tuple.type.748 = tuple_value (%d.param, %e.param) +// CHECK:STDOUT: %tuple.loc6_38: %tuple.type.d76 = tuple_value (%c.param, %tuple.loc6_37) +// CHECK:STDOUT: %tuple.loc6_39: %tuple.type.a40 = tuple_value (%b.param, %tuple.loc6_38) +// CHECK:STDOUT: %.loc6_45.2: ref %C = temporary_storage +// CHECK:STDOUT: %.loc6_45.3: init %C to %.loc6_45.2 = class_init () [concrete = constants.%C.val] +// CHECK:STDOUT: %.loc6_62.2: init %C = converted %.loc6_45.1, %.loc6_45.3 [concrete = constants.%C.val] +// CHECK:STDOUT: %.loc6_62.3: ref %C = temporary %.loc6_45.2, %.loc6_62.2 [concrete = constants.%.115] +// CHECK:STDOUT: %.loc6_62.4: %C = acquire_value %.loc6_62.3 [concrete = constants.%C.val] +// CHECK:STDOUT: %.loc6_50.2: ref %C = temporary_storage +// CHECK:STDOUT: %.loc6_50.3: init %C to %.loc6_50.2 = class_init () [concrete = constants.%C.val] +// CHECK:STDOUT: %.loc6_61.2: init %C = converted %.loc6_50.1, %.loc6_50.3 [concrete = constants.%C.val] +// CHECK:STDOUT: %.loc6_61.3: ref %C = temporary %.loc6_50.2, %.loc6_61.2 [concrete = constants.%.115] +// CHECK:STDOUT: %.loc6_61.4: %C = acquire_value %.loc6_61.3 [concrete = constants.%C.val] +// CHECK:STDOUT: %.loc6_55.2: ref %C = temporary_storage +// CHECK:STDOUT: %.loc6_55.3: init %C to %.loc6_55.2 = class_init () [concrete = constants.%C.val] +// CHECK:STDOUT: %.loc6_60.2: init %C = converted %.loc6_55.1, %.loc6_55.3 [concrete = constants.%C.val] +// CHECK:STDOUT: %.loc6_60.3: ref %C = temporary %.loc6_55.2, %.loc6_60.2 [concrete = constants.%.115] +// CHECK:STDOUT: %.loc6_60.4: %C = acquire_value %.loc6_60.3 [concrete = constants.%C.val] +// CHECK:STDOUT: %.loc6_59.2: ref %C = temporary_storage +// CHECK:STDOUT: %.loc6_59.3: init %C to %.loc6_59.2 = class_init () [concrete = constants.%C.val] +// CHECK:STDOUT: %.loc6_60.5: init %C = converted %.loc6_59.1, %.loc6_59.3 [concrete = constants.%C.val] +// CHECK:STDOUT: %.loc6_60.6: ref %C = temporary %.loc6_59.2, %.loc6_60.5 [concrete = constants.%.115] +// CHECK:STDOUT: %.loc6_60.7: %C = acquire_value %.loc6_60.6 [concrete = constants.%C.val] +// CHECK:STDOUT: %tuple.loc6_60: %tuple.type.748 = tuple_value (%.loc6_60.4, %.loc6_60.7) [concrete = constants.%tuple.d3e] +// CHECK:STDOUT: %.loc6_61.5: %tuple.type.748 = converted %.loc6_60.1, %tuple.loc6_60 [concrete = constants.%tuple.d3e] +// CHECK:STDOUT: %tuple.loc6_61: %tuple.type.d76 = tuple_value (%.loc6_61.4, %.loc6_61.5) [concrete = constants.%tuple.109] +// CHECK:STDOUT: %.loc6_62.5: %tuple.type.d76 = converted %.loc6_61.1, %tuple.loc6_61 [concrete = constants.%tuple.109] +// CHECK:STDOUT: %tuple.loc6_62: %tuple.type.a40 = tuple_value (%.loc6_62.4, %.loc6_62.5) [concrete = constants.%tuple.800] +// CHECK:STDOUT: %.loc6_62.6: %tuple.type.a40 = converted %.loc6_62.1, %tuple.loc6_62 [concrete = constants.%tuple.800] +// 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: // CHECK:STDOUT: --- basic.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { -// CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete] -// CHECK:STDOUT: %i32: type = class_type @Int, @Int(%int_32) [concrete] -// CHECK:STDOUT: %pattern_type.6b6: type = pattern_type %i32 [concrete] -// 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: %C: type = class_type @C [concrete] +// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] +// CHECK:STDOUT: %pattern_type: type = pattern_type %C [concrete] +// 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: %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] // CHECK:STDOUT: %F: %F.type = struct_value () [concrete] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: file { // 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: %pattern_type.6b6 = default_value_pattern %x.patt, index: 0 [concrete = constants.%.e53] +// 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: } { -// CHECK:STDOUT: %int_0: Core.IntLiteral = int_value 0 [concrete = constants.%int_0.5c6] -// CHECK:STDOUT: %x.param: %i32 = value_param call_param0 -// CHECK:STDOUT: %i32: type = type_literal constants.%i32 [concrete = constants.%i32] -// CHECK:STDOUT: %x: %i32 = wrapper_binding x, %x.param -// 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 +// CHECK:STDOUT: %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C] +// CHECK:STDOUT: %x: %C = wrapper_binding x, %x.param +// CHECK:STDOUT: %.loc6_14.2: ref %C = temporary_storage +// CHECK:STDOUT: %.loc6_14.3: init %C to %.loc6_14.2 = class_init () [concrete = constants.%C.val] +// CHECK:STDOUT: %.loc6_14.4: init %C = converted %.loc6_14.1, %.loc6_14.3 [concrete = constants.%C.val] +// CHECK:STDOUT: %.loc6_14.5: ref %C = temporary %.loc6_14.2, %.loc6_14.4 [concrete = constants.%.115] +// CHECK:STDOUT: %.loc6_14.6: %C = acquire_value %.loc6_14.5 [concrete = constants.%C.val] // CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @F(%x.param: %i32) { +// CHECK:STDOUT: fn @F(%x.param: %C) { // CHECK:STDOUT: !default_values: -// CHECK:STDOUT: constants.%int_0.5c6: Core.IntLiteral = int_value 0 [concrete] +// CHECK:STDOUT: %.loc6_14.6: %C = acquire_value %.loc6_14.5 [concrete = constants.%C.val] // CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/check/testdata/function/definition/default_values.carbon b/toolchain/check/testdata/function/definition/default_values.carbon index 4449aa94619c..9218ece32e2b 100644 --- a/toolchain/check/testdata/function/definition/default_values.carbon +++ b/toolchain/check/testdata/function/definition/default_values.carbon @@ -3,7 +3,6 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // // INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon -// EXTRA-ARGS: --dump-sem-ir-ranges=only // // AUTOUPDATE // TIP: To test this file alone, run: @@ -11,19 +10,6 @@ // TIP: To dump output, run: // TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/definition/default_values.carbon // -// --- fail_default_presence_mismatch_redecl.carbon -library "[[@TEST_NAME]]"; - -fn F(x: i32 = 0, y: i32 = _, z: i32 = _); -// CHECK:STDERR: fail_default_presence_mismatch_redecl.carbon:[[@LINE+7]]:13: error: redeclaration differs at parameter 1 [RedeclParamDiffers] -// CHECK:STDERR: fn F(unused x: i32, unused y: i32 = 1, unused z: i32 = 2) { } -// CHECK:STDERR: ^~~~~~ -// CHECK:STDERR: fail_default_presence_mismatch_redecl.carbon:[[@LINE-4]]:6: note: previous declaration's corresponding parameter here [RedeclParamPrevious] -// CHECK:STDERR: fn F(x: i32 = 0, y: i32 = _, z: i32 = _); -// CHECK:STDERR: ^~~~~~~~~~ -// CHECK:STDERR: -fn F(unused x: i32, unused y: i32 = 1, unused z: i32 = 2) { } - // --- fail_defaults_different_values_redecl.carbon library "[[@TEST_NAME]]"; @@ -37,114 +23,77 @@ fn F(x: i32 = 0, y: i32 = 10); // CHECK:STDERR: fn F(unused x: i32 = 0, unused y: i32 = 22) { } -// --- fail_defaults_never_specified_redecl.carbon +// --- imported_default_presence_mismatch.carbon library "[[@TEST_NAME]]"; -fn F(x: i32 = _); -// CHECK:STDERR: fail_defaults_never_specified_redecl.carbon:[[@LINE+7]]:6: error: no value for default number 0 is ever specified. [PatternDefaultValueNeverSpecified] -// CHECK:STDERR: fn F(unused x: i32 = _) { } -// CHECK:STDERR: ^~~~~~~~~~~~~~~~~ -// CHECK:STDERR: fail_defaults_never_specified_redecl.carbon:[[@LINE-4]]:6: note: previous declaration here. [PatternDefaultValueNeverSpecifiedNote] -// CHECK:STDERR: fn F(x: i32 = _); -// CHECK:STDERR: ^~~~~~~~~~ -// CHECK:STDERR: -fn F(unused x: i32 = _) { } +fn F(x: i32 = 0, y: i32 = 1, z: i32 = 2); -// --- default_presence_mismatch.carbon -library "[[@TEST_NAME]]"; - -fn F(x: i32 = 0, y: i32 = _, z: i32 = _); - -// --- fail_default_presence_mismatch.impl.carbon +// --- fail_imported_default_presence_mismatch.impl.carbon impl library "[[@TEST_NAME]]"; -// CHECK:STDERR: fail_default_presence_mismatch.impl.carbon:[[@LINE+8]]:13: error: redeclaration differs at parameter 1 [RedeclParamDiffers] -// CHECK:STDERR: fn F(unused x: i32, unused y: i32 = 1, unused z: i32 = 2) { } +// CHECK:STDERR: fail_imported_default_presence_mismatch.impl.carbon:[[@LINE+8]]:13: error: redeclaration differs at parameter 1 [RedeclParamDiffers] +// CHECK:STDERR: fn F(unused x: i32, unused y: i32 = _, unused z: i32 = _) { } // CHECK:STDERR: ^~~~~~ -// CHECK:STDERR: fail_default_presence_mismatch.impl.carbon:[[@LINE-5]]:1: in import [InImport] -// CHECK:STDERR: default_presence_mismatch.carbon:3:6: note: previous declaration's corresponding parameter here [RedeclParamPrevious] -// CHECK:STDERR: fn F(x: i32 = 0, y: i32 = _, z: i32 = _); +// CHECK:STDERR: fail_imported_default_presence_mismatch.impl.carbon:[[@LINE-5]]:1: in import [InImport] +// CHECK:STDERR: imported_default_presence_mismatch.carbon:3:6: note: previous declaration's corresponding parameter here [RedeclParamPrevious] +// CHECK:STDERR: fn F(x: i32 = 0, y: i32 = 1, z: i32 = 2); // CHECK:STDERR: ^~~~~~~~~~ // CHECK:STDERR: -fn F(unused x: i32, unused y: i32 = 1, unused z: i32 = 2) { } +fn F(unused x: i32, unused y: i32 = _, unused z: i32 = _) { } -// --- defaults_different_values.carbon +// --- imported_defaults_different_values.carbon library "[[@TEST_NAME]]"; fn F(x: i32 = 0, y: i32 = 10); -// --- fail_defaults_different_values.impl.carbon +// --- fail_imported_defaults_different_values.impl.carbon impl library "[[@TEST_NAME]]"; -// CHECK:STDERR: fail_defaults_different_values.impl.carbon:[[@LINE+4]]:25: error: default value differs from the previous declaration. [PatternDefaultValueDiffers] +// 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: 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: fn F(x: i32 = 0, y: i32 = 10); +// CHECK:STDERR: ^~ // CHECK:STDERR: fn F(unused x: i32 = 0, unused y: i32 = 22) { } -// --- defaults_never_specified.carbon -library "[[@TEST_NAME]]"; - -fn F(x: i32 = _); - -// --- fail_defaults_never_specified.impl.carbon -impl library "[[@TEST_NAME]]"; - -// CHECK:STDERR: fail_defaults_never_specified.impl.carbon:[[@LINE+4]]:6: error: no value for default number 0 is ever specified. [PatternDefaultValueNeverSpecified] -// CHECK:STDERR: fn F(unused x: i32 = _) { } -// CHECK:STDERR: ^~~~~~~~~~~~~~~~~ -// CHECK:STDERR: -fn F(unused x: i32 = _) { } - // --- redecl.carbon library "[[@TEST_NAME]]"; fn F(x: i32 = 0) -> i32; -fn G(x: i32 = _) -> i32; -fn H(x: i32 = 0) -> i32; +fn G(x: i32 = 0) -> i32; //@dump-sem-ir-begin fn F(x: i32 = 0) -> i32 { return x; } -fn G(x: i32 = 0) -> i32 { return x; } -fn H(x: i32 = _) -> i32 { return x; } +fn G(x: i32 = _) -> i32 { return x; } //@dump-sem-ir-end -// --- repeated_defaults.carbon +// --- imported_repeated_defaults.carbon library "[[@TEST_NAME]]"; fn F(x: i32 = 0) -> i32; -// --- repeated_defaults.impl.carbon +// --- imported_repeated_defaults.impl.carbon impl library "[[@TEST_NAME]]"; //@dump-sem-ir-begin fn F(x: i32 = 0) -> i32 { return x; } //@dump-sem-ir-end -// --- elided_defaults_in_def.carbon +// --- imported_elided_defaults_in_def.carbon library "[[@TEST_NAME]]"; fn F(x: i32 = 0) -> i32; -// --- elided_defaults_in_def.impl.carbon +// --- imported_elided_defaults_in_def.impl.carbon impl library "[[@TEST_NAME]]"; //@dump-sem-ir-begin fn F(x: i32 = _) -> i32 { return x; } //@dump-sem-ir-end -// --- elided_defaults_in_decl.carbon -library "[[@TEST_NAME]]"; - -fn F(x: i32 = _) -> i32; - -// --- elided_defaults_in_decl.impl.carbon -impl library "[[@TEST_NAME]]"; - -//@dump-sem-ir-begin -fn F(x: i32 = 0) -> i32 { return x; } -//@dump-sem-ir-end - // CHECK:STDOUT: --- redecl.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { @@ -159,13 +108,24 @@ fn F(x: i32 = 0) -> i32 { return x; } // 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] +// CHECK:STDOUT: %ImplicitAs.type.914: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete] +// CHECK:STDOUT: %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e74: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.845: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e74 = struct_value () [symbolic] +// CHECK:STDOUT: %ImplicitAs.impl_witness.a2a: = impl_witness imports.%ImplicitAs.impl_witness_table.1aa, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.2ba: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.e39: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.2ba = struct_value () [concrete] +// CHECK:STDOUT: %ImplicitAs.facet: %ImplicitAs.type.914 = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.a2a) [concrete] +// CHECK:STDOUT: %ImplicitAs.WithSelf.Convert.type.8eb: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete] +// CHECK:STDOUT: %.b7a: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.8eb, %ImplicitAs.facet [concrete] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound: = bound_method %int_0.5c6, %Core.IntLiteral.as.ImplicitAs.impl.Convert.e39 [concrete] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.e39, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete] +// CHECK:STDOUT: %bound_method: = bound_method %int_0.5c6, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete] +// CHECK:STDOUT: %int_0.3c0: %i32 = int_value 0 [concrete] // CHECK:STDOUT: %F.type: type = fn_type @F [concrete] // CHECK:STDOUT: %F: %F.type = struct_value () [concrete] -// CHECK:STDOUT: %.d49: = unspecified_value [concrete] // CHECK:STDOUT: %G.type: type = fn_type @G [concrete] // CHECK:STDOUT: %G: %G.type = struct_value () [concrete] -// CHECK:STDOUT: %H.type: type = fn_type @H [concrete] -// CHECK:STDOUT: %H: %H.type = struct_value () [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] @@ -176,69 +136,75 @@ fn F(x: i32 = 0) -> i32 { return x; } // CHECK:STDOUT: %Copy.WithSelf.Op.type.381: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [concrete] // 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: } // CHECK:STDOUT: // CHECK:STDOUT: imports { +// CHECK:STDOUT: %Core.import_ref.edf: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e74) = import_ref Core//prelude/parts/int, loc{{\d+_\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.845)] +// CHECK:STDOUT: %ImplicitAs.impl_witness_table.1aa = impl_witness_table (%Core.import_ref.edf), @Core.IntLiteral.as.ImplicitAs.impl [concrete] // CHECK:STDOUT: %Core.import_ref.cd6: @Int.as.Copy.impl.%Int.as.Copy.impl.Op.type (%Int.as.Copy.impl.Op.type.ac8) = import_ref Core//prelude/parts/int, loc{{\d+_\d+}}, loaded [symbolic = @Int.as.Copy.impl.%Int.as.Copy.impl.Op (constants.%Int.as.Copy.impl.Op.5e0)] // CHECK:STDOUT: %Copy.impl_witness_table.8d2 = impl_witness_table (%Core.import_ref.cd6), @Int.as.Copy.impl [concrete] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: file { -// CHECK:STDOUT: %F.decl.loc8: %F.type = fn_decl @F [concrete = constants.%F] { +// 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: %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: } { +// CHECK:STDOUT: %int_0.loc7: Core.IntLiteral = int_value 0 [concrete = constants.%int_0.5c6] +// CHECK:STDOUT: %i32.loc7_21: type = type_literal constants.%i32 [concrete = constants.%i32] +// CHECK:STDOUT: %.loc7_21: Core.Form = init_form %i32.loc7_21 [concrete = constants.%.795f] +// CHECK:STDOUT: %x.param.loc7: %i32 = value_param call_param0 +// CHECK:STDOUT: %i32.loc7_9: type = type_literal constants.%i32 [concrete = constants.%i32] +// CHECK:STDOUT: %x.loc7: %i32 = wrapper_binding x, %x.param.loc7 +// CHECK:STDOUT: %impl.elem0.loc7_15: %.b7a = impl_witness_access constants.%ImplicitAs.impl_witness.a2a, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.e39] +// CHECK:STDOUT: %bound_method.loc7_15.1: = bound_method %int_0.loc7, %impl.elem0.loc7_15 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound] +// CHECK:STDOUT: %specific_fn.loc7_15: = specific_function %impl.elem0.loc7_15, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn] +// CHECK:STDOUT: %bound_method.loc7_15.2: = bound_method %int_0.loc7, %specific_fn.loc7_15 [concrete = constants.%bound_method] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc7: init %i32 = call %bound_method.loc7_15.2(%int_0.loc7) [concrete = constants.%int_0.3c0] +// CHECK:STDOUT: %.loc7_15.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc7 [concrete = constants.%int_0.3c0] +// CHECK:STDOUT: %.loc7_15.2: %i32 = converted %int_0.loc7, %.loc7_15.1 [concrete = constants.%int_0.3c0] +// CHECK:STDOUT: %return.param.loc7: ref %i32 = out_param call_param1 +// CHECK:STDOUT: %return.loc7: ref %i32 = return_slot %return.param.loc7 +// CHECK:STDOUT: } +// 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: %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: } { -// CHECK:STDOUT: %int_0.loc8: Core.IntLiteral = int_value 0 [concrete = constants.%int_0.5c6] +// CHECK:STDOUT: %.loc8_15: = unspecified_value [concrete = constants.%.d49] // CHECK:STDOUT: %i32.loc8_21: type = type_literal constants.%i32 [concrete = constants.%i32] // CHECK:STDOUT: %.loc8_21: Core.Form = init_form %i32.loc8_21 [concrete = constants.%.795f] // CHECK:STDOUT: %x.param.loc8: %i32 = value_param call_param0 // CHECK:STDOUT: %i32.loc8_9: type = type_literal constants.%i32 [concrete = constants.%i32] // CHECK:STDOUT: %x.loc8: %i32 = wrapper_binding x, %x.param.loc8 -// CHECK:STDOUT: // CHECK:STDOUT: %return.param.loc8: ref %i32 = out_param call_param1 // CHECK:STDOUT: %return.loc8: ref %i32 = return_slot %return.param.loc8 // CHECK:STDOUT: } -// CHECK:STDOUT: %G.decl.loc9: %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: %.loc9_13: %pattern_type.6b6 = default_value_pattern %x.patt, index: 0 [concrete = constants.%.e53] -// 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.loc9_21 [concrete = constants.%return.patt.e1b] -// CHECK:STDOUT: } { -// CHECK:STDOUT: %int_0: Core.IntLiteral = int_value 0 [concrete = constants.%int_0.5c6] -// CHECK:STDOUT: %i32.loc9_21: type = type_literal constants.%i32 [concrete = constants.%i32] -// CHECK:STDOUT: %.loc9_21: Core.Form = init_form %i32.loc9_21 [concrete = constants.%.795f] -// CHECK:STDOUT: %x.param.loc9: %i32 = value_param call_param0 -// CHECK:STDOUT: %i32.loc9_9: type = type_literal constants.%i32 [concrete = constants.%i32] -// CHECK:STDOUT: %x.loc9: %i32 = wrapper_binding x, %x.param.loc9 -// CHECK:STDOUT: -// CHECK:STDOUT: %return.param.loc9: ref %i32 = out_param call_param1 -// CHECK:STDOUT: %return.loc9: ref %i32 = return_slot %return.param.loc9 -// CHECK:STDOUT: } -// CHECK:STDOUT: %H.decl.loc10: %H.type = fn_decl @H [concrete = constants.%H] { -// 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: %.loc10_13: %pattern_type.6b6 = default_value_pattern %x.patt, index: 0 [concrete = constants.%.e53] -// 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.loc10_21 [concrete = constants.%return.patt.e1b] -// CHECK:STDOUT: } { -// CHECK:STDOUT: %.loc10_15: = unspecified_value [concrete = constants.%.d49] -// CHECK:STDOUT: %i32.loc10_21: type = type_literal constants.%i32 [concrete = constants.%i32] -// CHECK:STDOUT: %.loc10_21: Core.Form = init_form %i32.loc10_21 [concrete = constants.%.795f] -// CHECK:STDOUT: %x.param.loc10: %i32 = value_param call_param0 -// CHECK:STDOUT: %i32.loc10_9: type = type_literal constants.%i32 [concrete = constants.%i32] -// CHECK:STDOUT: %x.loc10: %i32 = wrapper_binding x, %x.param.loc10 -// CHECK:STDOUT: %return.param.loc10: ref %i32 = out_param call_param1 -// CHECK:STDOUT: %return.loc10: ref %i32 = return_slot %return.param.loc10 -// CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @F(%x.param.loc8: %i32) -> out %return.param.loc8: %i32 { +// CHECK:STDOUT: fn @F(%x.param.loc7: %i32) -> out %return.param.loc7: %i32 { // CHECK:STDOUT: !default_values: -// CHECK:STDOUT: constants.%int_0.5c6: Core.IntLiteral = int_value 0 [concrete] +// 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] +// CHECK:STDOUT: %bound_method.loc7_34.1: = bound_method %x.ref, %impl.elem0.loc7_34 +// CHECK:STDOUT: %specific_fn.loc7_34: = specific_function %impl.elem0.loc7_34, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn] +// CHECK:STDOUT: %bound_method.loc7_34.2: = bound_method %x.ref, %specific_fn.loc7_34 +// CHECK:STDOUT: %Int.as.Copy.impl.Op.call: init %i32 = call %bound_method.loc7_34.2(%x.ref) +// CHECK:STDOUT: return %Int.as.Copy.impl.Op.call +// 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 @@ -250,38 +216,13 @@ fn F(x: i32 = 0) -> i32 { return x; } // CHECK:STDOUT: return %Int.as.Copy.impl.Op.call // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @G(%x.param.loc9: %i32) -> out %return.param.loc9: %i32 { -// CHECK:STDOUT: !default_values: -// CHECK:STDOUT: constants.%int_0.5c6: Core.IntLiteral = int_value 0 [concrete] -// CHECK:STDOUT: -// CHECK:STDOUT: !entry: -// CHECK:STDOUT: %x.ref: %i32 = name_ref x, %x.loc9 -// CHECK:STDOUT: %impl.elem0.loc9: %.737 = impl_witness_access constants.%Copy.impl_witness.b51, element0 [concrete = constants.%Int.as.Copy.impl.Op.4f6] -// CHECK:STDOUT: %bound_method.loc9_34.1: = bound_method %x.ref, %impl.elem0.loc9 -// CHECK:STDOUT: %specific_fn.loc9: = specific_function %impl.elem0.loc9, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn] -// CHECK:STDOUT: %bound_method.loc9_34.2: = bound_method %x.ref, %specific_fn.loc9 -// CHECK:STDOUT: %Int.as.Copy.impl.Op.call: init %i32 = call %bound_method.loc9_34.2(%x.ref) -// CHECK:STDOUT: return %Int.as.Copy.impl.Op.call -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: fn @H(%x.param.loc10: %i32) -> out %return.param.loc10: %i32 { -// CHECK:STDOUT: !default_values: -// CHECK:STDOUT: constants.%int_0.5c6: Core.IntLiteral = int_value 0 [concrete] -// CHECK:STDOUT: -// CHECK:STDOUT: !entry: -// CHECK:STDOUT: %x.ref: %i32 = name_ref x, %x.loc10 -// CHECK:STDOUT: %impl.elem0.loc10: %.737 = impl_witness_access constants.%Copy.impl_witness.b51, element0 [concrete = constants.%Int.as.Copy.impl.Op.4f6] -// CHECK:STDOUT: %bound_method.loc10_34.1: = bound_method %x.ref, %impl.elem0.loc10 -// CHECK:STDOUT: %specific_fn.loc10: = specific_function %impl.elem0.loc10, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn] -// CHECK:STDOUT: %bound_method.loc10_34.2: = bound_method %x.ref, %specific_fn.loc10 -// CHECK:STDOUT: %Int.as.Copy.impl.Op.call: init %i32 = call %bound_method.loc10_34.2(%x.ref) -// CHECK:STDOUT: return %Int.as.Copy.impl.Op.call -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: --- repeated_defaults.impl.carbon +// CHECK:STDOUT: --- imported_repeated_defaults.impl.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { +// CHECK:STDOUT: %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic] // CHECK:STDOUT: %N: Core.IntLiteral = symbolic_binding N, 0 [symbolic] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e74: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.845: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e74 = struct_value () [symbolic] // CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete] // CHECK:STDOUT: %i32: type = class_type @Int, @Int(%int_32) [concrete] // CHECK:STDOUT: %pattern_type.6b6: type = pattern_type %i32 [concrete] @@ -292,6 +233,17 @@ fn F(x: i32 = 0) -> i32 { return x; } // 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] +// CHECK:STDOUT: %ImplicitAs.type.914: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete] +// CHECK:STDOUT: %ImplicitAs.impl_witness.a2a: = impl_witness imports.%ImplicitAs.impl_witness_table.1aa, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.2ba: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.e39: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.2ba = struct_value () [concrete] +// CHECK:STDOUT: %ImplicitAs.facet: %ImplicitAs.type.914 = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.a2a) [concrete] +// CHECK:STDOUT: %ImplicitAs.WithSelf.Convert.type.8eb: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete] +// CHECK:STDOUT: %.b7a: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.8eb, %ImplicitAs.facet [concrete] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound: = bound_method %int_0.5c6, %Core.IntLiteral.as.ImplicitAs.impl.Convert.e39 [concrete] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.e39, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete] +// CHECK:STDOUT: %bound_method: = bound_method %int_0.5c6, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete] +// CHECK:STDOUT: %int_0.3c0: %i32 = int_value 0 [concrete] // CHECK:STDOUT: %F.type: type = fn_type @F [concrete] // CHECK:STDOUT: %F: %F.type = struct_value () [concrete] // CHECK:STDOUT: %Copy.type: type = facet_type <@Copy> [concrete] @@ -307,6 +259,8 @@ fn F(x: i32 = 0) -> i32 { return x; } // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { +// CHECK:STDOUT: %Main.import_ref.717: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e74) = import_ref Main//imported_repeated_defaults, inst{{[0-9A-F]+}} [indirect], loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.845)] +// CHECK:STDOUT: %ImplicitAs.impl_witness_table.1aa = impl_witness_table (%Main.import_ref.717), @Core.IntLiteral.as.ImplicitAs.impl [concrete] // CHECK:STDOUT: %Core.import_ref.cd6: @Int.as.Copy.impl.%Int.as.Copy.impl.Op.type (%Int.as.Copy.impl.Op.type.ac8) = import_ref Core//prelude/parts/int, loc{{\d+_\d+}}, loaded [symbolic = @Int.as.Copy.impl.%Int.as.Copy.impl.Op (constants.%Int.as.Copy.impl.Op.5e0)] // CHECK:STDOUT: %Copy.impl_witness_table.8d2 = impl_witness_table (%Core.import_ref.cd6), @Int.as.Copy.impl [concrete] // CHECK:STDOUT: } @@ -325,27 +279,33 @@ fn F(x: i32 = 0) -> i32 { return x; } // CHECK:STDOUT: %x.param: %i32 = value_param call_param0 // CHECK:STDOUT: %i32.loc4_9: type = type_literal constants.%i32 [concrete = constants.%i32] // CHECK:STDOUT: %x: %i32 = wrapper_binding x, %x.param -// CHECK:STDOUT: +// CHECK:STDOUT: %impl.elem0.loc4_15: %.b7a = impl_witness_access constants.%ImplicitAs.impl_witness.a2a, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.e39] +// CHECK:STDOUT: %bound_method.loc4_15.1: = bound_method %int_0, %impl.elem0.loc4_15 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound] +// CHECK:STDOUT: %specific_fn.loc4_15: = specific_function %impl.elem0.loc4_15, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn] +// CHECK:STDOUT: %bound_method.loc4_15.2: = bound_method %int_0, %specific_fn.loc4_15 [concrete = constants.%bound_method] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.call: init %i32 = call %bound_method.loc4_15.2(%int_0) [concrete = constants.%int_0.3c0] +// CHECK:STDOUT: %.loc4_15.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%int_0.3c0] +// CHECK:STDOUT: %.loc4_15.2: %i32 = converted %int_0, %.loc4_15.1 [concrete = constants.%int_0.3c0] // CHECK:STDOUT: %return.param: ref %i32 = out_param call_param1 // CHECK:STDOUT: %return: ref %i32 = return_slot %return.param // CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @F(%x.param: %i32) -> out %return.param: %i32 [from "repeated_defaults.carbon"] { +// CHECK:STDOUT: fn @F(%x.param: %i32) -> out %return.param: %i32 [from "imported_repeated_defaults.carbon"] { // CHECK:STDOUT: !default_values: -// CHECK:STDOUT: constants.%int_0.5c6: Core.IntLiteral = int_value 0 [concrete] +// CHECK:STDOUT: // CHECK:STDOUT: // CHECK:STDOUT: !entry: // CHECK:STDOUT: %x.ref: %i32 = name_ref x, %x -// CHECK:STDOUT: %impl.elem0.loc4: %.737 = impl_witness_access constants.%Copy.impl_witness.b51, element0 [concrete = constants.%Int.as.Copy.impl.Op.4f6] -// CHECK:STDOUT: %bound_method.loc4_34.1: = bound_method %x.ref, %impl.elem0.loc4 -// CHECK:STDOUT: %specific_fn.loc4: = specific_function %impl.elem0.loc4, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn] -// CHECK:STDOUT: %bound_method.loc4_34.2: = bound_method %x.ref, %specific_fn.loc4 +// CHECK:STDOUT: %impl.elem0.loc4_34: %.737 = impl_witness_access constants.%Copy.impl_witness.b51, element0 [concrete = constants.%Int.as.Copy.impl.Op.4f6] +// CHECK:STDOUT: %bound_method.loc4_34.1: = bound_method %x.ref, %impl.elem0.loc4_34 +// CHECK:STDOUT: %specific_fn.loc4_34: = specific_function %impl.elem0.loc4_34, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn] +// CHECK:STDOUT: %bound_method.loc4_34.2: = bound_method %x.ref, %specific_fn.loc4_34 // CHECK:STDOUT: %Int.as.Copy.impl.Op.call: init %i32 = call %bound_method.loc4_34.2(%x.ref) // CHECK:STDOUT: return %Int.as.Copy.impl.Op.call // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: --- elided_defaults_in_def.impl.carbon +// CHECK:STDOUT: --- imported_elided_defaults_in_def.impl.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { // CHECK:STDOUT: %N: Core.IntLiteral = symbolic_binding N, 0 [symbolic] @@ -361,7 +321,6 @@ fn F(x: i32 = 0) -> i32 { return x; } // CHECK:STDOUT: %return.patt.e1b: %pattern_type.6b6 = return_slot_pattern %return.param_patt.a9a, %i32 [concrete] // CHECK:STDOUT: %F.type: type = fn_type @F [concrete] // CHECK:STDOUT: %F: %F.type = struct_value () [concrete] -// CHECK:STDOUT: %int_0: Core.IntLiteral = int_value 0 [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] @@ -398,9 +357,9 @@ fn F(x: i32 = 0) -> i32 { return x; } // CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @F(%x.param: %i32) -> out %return.param: %i32 [from "elided_defaults_in_def.carbon"] { +// CHECK:STDOUT: fn @F(%x.param: %i32) -> out %return.param: %i32 [from "imported_elided_defaults_in_def.carbon"] { // CHECK:STDOUT: !default_values: -// CHECK:STDOUT: constants.%int_0: Core.IntLiteral = int_value 0 [concrete] +// CHECK:STDOUT: // CHECK:STDOUT: // CHECK:STDOUT: !entry: // CHECK:STDOUT: %x.ref: %i32 = name_ref x, %x @@ -412,70 +371,3 @@ fn F(x: i32 = 0) -> i32 { return x; } // CHECK:STDOUT: return %Int.as.Copy.impl.Op.call // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: --- elided_defaults_in_decl.impl.carbon -// CHECK:STDOUT: -// CHECK:STDOUT: constants { -// CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete] -// CHECK:STDOUT: %N: Core.IntLiteral = symbolic_binding N, 0 [symbolic] -// CHECK:STDOUT: %i32: type = class_type @Int, @Int(%int_32) [concrete] -// CHECK:STDOUT: %pattern_type.6b6: type = pattern_type %i32 [concrete] -// 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] -// CHECK:STDOUT: %F.type: type = fn_type @F [concrete] -// CHECK:STDOUT: %F: %F.type = struct_value () [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] -// CHECK:STDOUT: %Copy.impl_witness.b51: = impl_witness imports.%Copy.impl_witness_table.8d2, @Int.as.Copy.impl(%int_32) [concrete] -// CHECK:STDOUT: %Int.as.Copy.impl.Op.type.3f6: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%int_32) [concrete] -// CHECK:STDOUT: %Int.as.Copy.impl.Op.4f6: %Int.as.Copy.impl.Op.type.3f6 = struct_value () [concrete] -// CHECK:STDOUT: %Copy.facet: %Copy.type = facet_value %i32, (%Copy.impl_witness.b51) [concrete] -// CHECK:STDOUT: %Copy.WithSelf.Op.type.381: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [concrete] -// 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: } -// CHECK:STDOUT: -// CHECK:STDOUT: imports { -// CHECK:STDOUT: %Core.import_ref.cd6: @Int.as.Copy.impl.%Int.as.Copy.impl.Op.type (%Int.as.Copy.impl.Op.type.ac8) = import_ref Core//prelude/parts/int, loc{{\d+_\d+}}, loaded [symbolic = @Int.as.Copy.impl.%Int.as.Copy.impl.Op (constants.%Int.as.Copy.impl.Op.5e0)] -// CHECK:STDOUT: %Copy.impl_witness_table.8d2 = impl_witness_table (%Core.import_ref.cd6), @Int.as.Copy.impl [concrete] -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: file { -// 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: %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: } { -// CHECK:STDOUT: %int_0: Core.IntLiteral = int_value 0 [concrete = constants.%int_0.5c6] -// CHECK:STDOUT: %i32.loc4_21: type = type_literal constants.%i32 [concrete = constants.%i32] -// CHECK:STDOUT: %.loc4_21: Core.Form = init_form %i32.loc4_21 [concrete = constants.%.795f] -// CHECK:STDOUT: %x.param: %i32 = value_param call_param0 -// CHECK:STDOUT: %i32.loc4_9: type = type_literal constants.%i32 [concrete = constants.%i32] -// CHECK:STDOUT: %x: %i32 = wrapper_binding x, %x.param -// CHECK:STDOUT: -// CHECK:STDOUT: %return.param: ref %i32 = out_param call_param1 -// CHECK:STDOUT: %return: ref %i32 = return_slot %return.param -// CHECK:STDOUT: } -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: fn @F(%x.param: %i32) -> out %return.param: %i32 [from "elided_defaults_in_decl.carbon"] { -// CHECK:STDOUT: !default_values: -// CHECK:STDOUT: constants.%int_0.5c6: Core.IntLiteral = int_value 0 [concrete] -// CHECK:STDOUT: -// CHECK:STDOUT: !entry: -// CHECK:STDOUT: %x.ref: %i32 = name_ref x, %x -// CHECK:STDOUT: %impl.elem0.loc4: %.737 = impl_witness_access constants.%Copy.impl_witness.b51, element0 [concrete = constants.%Int.as.Copy.impl.Op.4f6] -// CHECK:STDOUT: %bound_method.loc4_34.1: = bound_method %x.ref, %impl.elem0.loc4 -// CHECK:STDOUT: %specific_fn.loc4: = specific_function %impl.elem0.loc4, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn] -// CHECK:STDOUT: %bound_method.loc4_34.2: = bound_method %x.ref, %specific_fn.loc4 -// CHECK:STDOUT: %Int.as.Copy.impl.Op.call: init %i32 = call %bound_method.loc4_34.2(%x.ref) -// CHECK:STDOUT: return %Int.as.Copy.impl.Op.call -// CHECK:STDOUT: } -// CHECK:STDOUT: diff --git a/toolchain/check/thunk.cpp b/toolchain/check/thunk.cpp index 4232926bad4d..987f13e7598d 100644 --- a/toolchain/check/thunk.cpp +++ b/toolchain/check/thunk.cpp @@ -246,7 +246,7 @@ 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::None, + .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 a608b07359a2..e9ec0b695e3a 100644 --- a/toolchain/diagnostics/kind.def +++ b/toolchain/diagnostics/kind.def @@ -621,11 +621,10 @@ 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(PatternDefaultValueTypeMismatch) -CARBON_DIAGNOSTIC_KIND(PatternDefaultValueNeverSpecified) -CARBON_DIAGNOSTIC_KIND(PatternDefaultValueNeverSpecifiedNote) +CARBON_DIAGNOSTIC_KIND(PatternDefaultValueNotSpecified) CARBON_DIAGNOSTIC_KIND(TuplePatternSizeDoesntMatchLiteral) // Unused diagnostics. diff --git a/toolchain/sem_ir/formatter.cpp b/toolchain/sem_ir/formatter.cpp index a2ad856db713..65dc93792e56 100644 --- a/toolchain/sem_ir/formatter.cpp +++ b/toolchain/sem_ir/formatter.cpp @@ -599,25 +599,14 @@ auto Formatter::FormatFunction(FunctionId id, const Function& fn) -> void { } if (!fn.body_block_ids.empty() || - fn.call_param_default_values_id.has_value()) { + fn.call_param_default_values_id != SemIR::InstBlockId::Empty) { out() << ' '; OpenBrace(); - if (fn.call_param_default_values_id.has_value()) { + if (fn.call_param_default_values_id != SemIR::InstBlockId::Empty) { IndentLabel(); out() << "!default_values:\n"; - // The default values are encoded as canonical instructions, - // and as such have no location, and so are normally elided when - // use_dump_sem_ir_ranges_ is true. However, if the function containing - // these default values is to be printed, it should also include these - // defaults, so we temporarily disable this flag to force the printing of - // the contents of this block. - // TODO: drop this code once default values are stored as non-canonical - // instructions. - auto format_mask = use_dump_sem_ir_ranges_; - use_dump_sem_ir_ranges_ = false; FormatCodeBlock(fn.call_param_default_values_id); - use_dump_sem_ir_ranges_ = format_mask; } for (auto block_id : fn.body_block_ids) { diff --git a/toolchain/sem_ir/function.h b/toolchain/sem_ir/function.h index 3a0fad5e4a25..18338ef0fe78 100644 --- a/toolchain/sem_ir/function.h +++ b/toolchain/sem_ir/function.h @@ -82,8 +82,7 @@ struct FunctionFields { // because it is relevant only for a function definition. InstBlockId call_params_id; - // Instructions representing the canonical default values for parameters. - // TODO: Change this to non-canonical values. + // Instructions representing the default values for parameters. InstBlockId call_param_default_values_id; // The index ranges within the `Call` parameters that correspond to the @@ -235,7 +234,7 @@ struct Function : public EntityWithParamsBase, if (call_params_id.has_value()) { out << ", call_params_id: " << call_params_id; } - if (call_param_default_values_id.has_value()) { + 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()) {