Use non-canonical instructions in default values. (#7737)

Per feedback on #7665, this PR switches the default value
table storage from canonical constant inst_ids to
non-canonical.

Furthermore, this PR simplifies the default value support in
check by requiring that the first owned declaration of a
function completely specify all of its default values.
Updates the diagnostic code and tests to reflect this new
stricter requirement.
This commit is contained in:
Lucile Rose Nihlen
2026-09-17 22:04:43 +00:00
committed by GitHub
parent ae4be1be14
commit 994bad5143
17 changed files with 555 additions and 571 deletions
+1 -1
View File
@@ -1982,7 +1982,7 @@ static auto ImportFunction(Context& context, SemIR::LocId loc_id,
.call_param_patterns_id = .call_param_patterns_id =
function_params_insts->call_param_patterns_id, function_params_insts->call_param_patterns_id,
.call_params_id = function_params_insts->call_params_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, .call_param_ranges = function_params_insts->param_ranges,
.return_type_inst_id = function_params_insts->return_type_inst_id, .return_type_inst_id = function_params_insts->return_type_inst_id,
.return_form_inst_id = function_params_insts->return_form_inst_id, .return_form_inst_id = function_params_insts->return_form_inst_id,
+49 -15
View File
@@ -121,7 +121,8 @@ class FullPatternStack {
CARBON_CHECK(kind_stack_.back() == Kind::NotInEitherParamList, "{0}", CARBON_CHECK(kind_stack_.back() == Kind::NotInEitherParamList, "{0}",
kind_stack_.back()); kind_stack_.back());
kind_stack_.back() = Kind::ExplicitParamList; 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 // Marks the end of the current parameterized entity's explicit parameter
@@ -149,7 +150,8 @@ class FullPatternStack {
"`GetLocalVarStorage` not called for all var patterns"); "`GetLocalVarStorage` not called for all var patterns");
var_pattern_stack_.PopArray(); var_pattern_stack_.PopArray();
if (kind == Kind::ExplicitParamList) { 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()); kind_stack_.size());
} }
// Adds the inst id for a constant value provided as a default value for // Adds the inst id for a default value for any subpattern in the
// any subpattern in the full-pattern. Returns the index of that element // 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 // as a `DefaultValueId`. Note default values are only supported for
// explicit parameter lists. // explicit parameter lists.
auto AddDefaultValue(SemIR::InstId inst_id) -> SemIR::DefaultValueId { auto AddRawDefaultValue(SemIR::InstId inst_id) -> SemIR::DefaultValueId {
auto index = SemIR::FromRaw<SemIR::DefaultValueId>(
static_cast<int32_t>(default_values_stack_.PeekArray().size()));
CARBON_CHECK(kind_stack_.back() == Kind::ExplicitParamList); CARBON_CHECK(kind_stack_.back() == Kind::ExplicitParamList);
default_values_stack_.AppendToTop(inst_id); return AddDefaultValue(inst_id, raw_default_values_stack_);
return index;
} }
// Returns a reference to the array of default value inst ids at the top of // Adds the inst id for a default value after conversion to the pattern type.
// the stack. Note default values are only supported for explicit parameter // 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. // lists.
auto GetDefaultValues() -> llvm::ArrayRef<SemIR::InstId> { auto GetRawDefaultValues() -> llvm::ArrayRef<SemIR::InstId> {
return default_values_stack_.PeekArray(); return raw_default_values_stack_.empty()
? llvm::ArrayRef<SemIR::InstId>()
: 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<SemIR::InstId> {
return converted_default_values_stack_.empty()
? llvm::ArrayRef<SemIR::InstId>()
: converted_default_values_stack_.PeekArray();
} }
private: private:
// TODO: move default value InstIds to a value store and remove them from the
// pattern stack.
auto AddDefaultValue(SemIR::InstId inst_id, ArrayStack<SemIR::InstId>& stack)
-> SemIR::DefaultValueId {
auto index =
SemIR::DefaultValueId(static_cast<int32_t>(stack.PeekArray().size()));
stack.AppendToTop(inst_id);
return index;
}
LexicalLookup* lookup_; LexicalLookup* lookup_;
// The stack of pending full-patterns is organized as a struct of arrays, with // The stack of pending full-patterns is organized as a struct of arrays, with
@@ -257,8 +284,15 @@ class FullPatternStack {
llvm::SmallVector<int> next_var_index_stack_; llvm::SmallVector<int> next_var_index_stack_;
// The stack of instructions specifying default values for subpatterns // The stack of instructions specifying default values for subpatterns
// within this full-pattern. // within this full-pattern. These instructions are as they are written by
ArrayStack<SemIR::InstId> default_values_stack_; // the developer, with no type conversions applied. They are indexed by
// `DefaultValueId` values.
ArrayStack<SemIR::InstId> 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<SemIR::InstId> converted_default_values_stack_;
}; };
} // namespace Carbon::Check } // namespace Carbon::Check
+45 -85
View File
@@ -91,7 +91,7 @@ struct FunctionSignatureInsts {
SemIR::InstBlockId param_patterns_id = SemIR::InstBlockId::None; SemIR::InstBlockId param_patterns_id = SemIR::InstBlockId::None;
SemIR::InstBlockId call_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_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 call_param_ranges =
SemIR::Function::CallParamIndexRanges::Empty; SemIR::Function::CallParamIndexRanges::Empty;
SemIR::TypeInstId return_type_inst_id = SemIR::TypeInstId::None; SemIR::TypeInstId return_type_inst_id = SemIR::TypeInstId::None;
@@ -305,100 +305,60 @@ static auto CheckFunctionEvaluationModeMatches(
return false; return false;
} }
// Given a parameter patterns block, extracts the locations of all // Checks that if `new_id` has a specified value, it has the same value as
// `SemIR::DefaultValuePattern` instructions and returns them in an array. // specified by `prev_id`. If `diagnose` is true this will issue a diagnostic
static auto ExtractDefaultValueLocations(Context& context, // if it detects a difference. Returns true if the values are the same or
SemIR::InstBlockId param_patterns_id) // `new_id` is unspecified.
-> llvm::SmallVector<SemIR::LocId> { //
llvm::SmallVector<SemIR::LocId> locations; // Note: this function is only called on the function's first owning
for (auto inst_id : context.inst_blocks().GetOrEmpty(param_patterns_id)) { // declaration, as that is the declaration with this requirement.
if (context.insts().Is<SemIR::DefaultValuePattern>(inst_id)) { static auto CheckDefaultValueIsSame(Context& context, SemIR::InstId new_id,
locations.push_back(SemIR::LocId(inst_id)); SemIR::InstId prev_id, bool diagnose)
-> bool {
CARBON_CHECK(!context.insts().Is<SemIR::UnspecifiedValue>(prev_id));
if (!context.insts().Is<SemIR::UnspecifiedValue>(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 // 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 // both specify a default value those values are identical. If `diagnose` is
// one has an unspecified default value. If `diagnose` is true, issues // true, issues diagnostics when that condition is violated. Returns true if
// diagnostics where either condition is violated. Returns true if every // every parameter met the condition.
// parameter met both criteria.
static auto CheckDefaultValueConsistency(Context& context, static auto CheckDefaultValueConsistency(Context& context,
const SemIR::Function& new_function, const SemIR::Function& new_function,
const SemIR::Function& prev_function, const SemIR::Function& prev_function,
bool diagnose) -> bool { bool diagnose) -> bool {
// Both functions must either have defaults or not. auto new_default_value_ids = context.inst_blocks().GetOrEmpty(
CARBON_CHECK(prev_function.call_param_default_values_id.has_value() == new_function.call_param_default_values_id);
new_function.call_param_default_values_id.has_value()); 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 llvm::all_of(
return true; llvm::zip_equal(new_default_value_ids, prev_default_value_ids),
} [&context, diagnose](auto id_pair) -> bool {
auto [new_id, prev_id] = id_pair;
auto prev_value_inst_ids = return CheckDefaultValueIsSame(context, new_id, prev_id, diagnose);
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<size_t> indices_without_values;
llvm::SmallVector<size_t> indices_with_different_values;
for (size_t i = 0; i < prev_value_inst_ids.size(); ++i) {
bool prev_value_specified =
!context.insts().Is<SemIR::UnspecifiedValue>(prev_value_inst_ids[i]);
bool new_value_specified =
!context.insts().Is<SemIR::UnspecifiedValue>(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;
} }
auto CheckFunctionTypeMatches(Context& context, auto CheckFunctionTypeMatches(Context& context,
+1 -1
View File
@@ -51,7 +51,7 @@ auto GlobalInit::Finalize() -> void {
.first_owning_decl_id = SemIR::InstId::None}, .first_owning_decl_id = SemIR::InstId::None},
{.call_param_patterns_id = SemIR::InstBlockId::Empty, {.call_param_patterns_id = SemIR::InstBlockId::Empty,
.call_params_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, .call_param_ranges = SemIR::Function::CallParamIndexRanges::Empty,
.return_type_inst_id = SemIR::TypeInstId::None, .return_type_inst_id = SemIR::TypeInstId::None,
.return_form_inst_id = SemIR::InstId::None, .return_form_inst_id = SemIR::InstId::None,
+23
View File
@@ -373,6 +373,25 @@ static auto DiagnosePositionalParams(Context& context,
function_info.param_patterns_id = SemIR::InstBlockId::Empty; 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<SemIR::UnspecifiedValue>(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 // Build a FunctionDecl describing the signature of a function. This
// handles the common logic shared by function declaration syntax and function // handles the common logic shared by function declaration syntax and function
// definition syntax. // definition syntax.
@@ -457,6 +476,10 @@ static auto BuildFunctionDecl(Context& context,
} }
DiagnosePositionalParams(context, function_info); DiagnosePositionalParams(context, function_info);
if (name_context.state != DeclNameStack::NameContext::State::Poisoned &&
!name_context.prev_inst_id().has_value()) {
CheckDefaultValuesCompletelySpecified(context, function_info);
}
TryMergeRedecl( TryMergeRedecl(
context, name_context, std::nullopt, context, name_context, std::nullopt,
+1 -1
View File
@@ -200,7 +200,7 @@ static auto PopImplIntroducerAndParamsAsNameComponent(
.param_patterns_id = SemIR::InstBlockId::None, .param_patterns_id = SemIR::InstBlockId::None,
.call_param_patterns_id = SemIR::InstBlockId::None, .call_param_patterns_id = SemIR::InstBlockId::None,
.call_params_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, .param_ranges = SemIR::Function::CallParamIndexRanges::Empty,
.pattern_block_id = pattern_block_id}; .pattern_block_id = pattern_block_id};
} }
+4 -9
View File
@@ -172,8 +172,6 @@ auto HandleParseNode(Context& context,
auto HandleParseNode(Context& context, Parse::DefaultValuePatternId node_id) auto HandleParseNode(Context& context, Parse::DefaultValuePatternId node_id)
-> bool { -> 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(); auto [expr_node_id, expr_inst_id] = context.node_stack().PopExprWithNodeId();
// Ensure we are in an explicit parameter list, otherwise issue a diagnostic. // 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; return false;
} }
// Evaluate the default value constant.
auto expr_const_id = TryEvalInst(context, expr_inst_id); auto expr_const_id = TryEvalInst(context, expr_inst_id);
if (expr_const_id == SemIR::ConstantId::NotConstant) { if (expr_const_id == SemIR::ConstantId::NotConstant) {
CARBON_DIAGNOSTIC(PatternDefaultValueNotConstant, Error, CARBON_DIAGNOSTIC(PatternDefaultValueNotConstant, Error,
"default value for pattern must be constant"); "default value is not a constant");
context.emitter().Emit( context.emitter().Emit(
LocIdForDiagnostics(context.insts().GetCanonicalLocId(expr_inst_id)), LocIdForDiagnostics(context.insts().GetCanonicalLocId(expr_inst_id)),
PatternDefaultValueNotConstant); PatternDefaultValueNotConstant);
return false; 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 // 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 = 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 // 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 // specified. We pop that so we can issue the DefaultValuePattern in its
+2 -11
View File
@@ -2425,7 +2425,7 @@ static auto ImportFunctionDecl(
{GetIncompleteLocalEntityBase(context, function_decl_id, import_function), {GetIncompleteLocalEntityBase(context, function_decl_id, import_function),
{.call_param_patterns_id = SemIR::InstBlockId::None, {.call_param_patterns_id = SemIR::InstBlockId::None,
.call_params_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, .call_param_ranges = import_function.call_param_ranges,
.return_type_inst_id = SemIR::TypeInstId::None, .return_type_inst_id = SemIR::TypeInstId::None,
.return_form_inst_id = SemIR::InstId::None, .return_form_inst_id = SemIR::InstId::None,
@@ -2573,15 +2573,6 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver,
resolver, import_function.call_param_patterns_id); resolver, import_function.call_param_patterns_id);
auto call_param_default_values = GetLocalBlockImportRefInfo( auto call_param_default_values = GetLocalBlockImportRefInfo(
resolver, import_function.call_param_default_values_id); resolver, import_function.call_param_default_values_id);
llvm::SmallVector<SemIR::InstId> 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; auto return_type_const_id = SemIR::ConstantId::None;
if (import_function.return_type_inst_id.has_value()) { if (import_function.return_type_inst_id.has_value()) {
return_type_const_id = return_type_const_id =
@@ -2633,7 +2624,7 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver,
AddLoadedImportRefBlock(resolver, call_param_patterns); AddLoadedImportRefBlock(resolver, call_param_patterns);
if (call_param_default_values.has_value()) { if (call_param_default_values.has_value()) {
new_function.call_param_default_values_id = 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.parent_scope_id = parent_scope_id;
new_function.implicit_param_patterns_id = new_function.implicit_param_patterns_id =
-41
View File
@@ -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<SemIR::InstId> 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<SemIR::UnspecifiedValue>(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<SemIR::UnspecifiedValue>(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 <typename EntityT> template <typename EntityT>
auto TryMergeRedecl(Context& context, auto TryMergeRedecl(Context& context,
const DeclNameStack::NameContext& name_context, const DeclNameStack::NameContext& name_context,
@@ -904,10 +867,6 @@ auto TryMergeRedecl(Context& context,
if (is_definition) { if (is_definition) {
prev_entity.MergeDefinition(entity_info.new_entity); 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(); auto replace_prev_inst = prev_import_ir_id.has_value();
+6 -5
View File
@@ -13,7 +13,6 @@ auto PopNameComponent(Context& context, SemIR::InstId return_pattern_id)
-> NameComponent { -> NameComponent {
Parse::NodeId first_param_node_id = Parse::NoneNodeId(); Parse::NodeId first_param_node_id = Parse::NoneNodeId();
Parse::NodeId last_param_node_id = Parse::NoneNodeId(); Parse::NodeId last_param_node_id = Parse::NoneNodeId();
auto call_param_default_values_id = SemIR::InstBlockId::None;
// Explicit params. // Explicit params.
auto [params_node_id, param_patterns_id] = auto [params_node_id, param_patterns_id] =
@@ -24,10 +23,6 @@ auto PopNameComponent(Context& context, SemIR::InstId return_pattern_id)
context.node_stack() context.node_stack()
.PopForSoloNodeId<Parse::NodeKind::ExplicitParamListStart>(); .PopForSoloNodeId<Parse::NodeKind::ExplicitParamListStart>();
last_param_node_id = params_node_id; 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 { } else {
param_patterns_id = SemIR::InstBlockId::None; 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_patterns_id = SemIR::InstBlockId::None;
auto call_param_default_values_id = SemIR::InstBlockId::Empty;
auto call_params_id = SemIR::InstBlockId::None; auto call_params_id = SemIR::InstBlockId::None;
auto param_ranges = SemIR::Function::CallParamIndexRanges::Empty; auto param_ranges = SemIR::Function::CallParamIndexRanges::Empty;
auto pattern_block_id = SemIR::InstBlockId::None; 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_param_patterns_id = results.call_param_patterns_id;
call_params_id = results.call_params_id; call_params_id = results.call_params_id;
param_ranges = results.param_ranges; 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(); pattern_block_id = context.pattern_block_stack().Pop();
context.full_pattern_stack().PopFullPattern(); context.full_pattern_stack().PopFullPattern();
} }
+16 -22
View File
@@ -952,7 +952,7 @@ auto MatchContext::DoPreWork(State state,
auto MatchContext::DoPostWork(State state, auto MatchContext::DoPostWork(State state,
SemIR::DefaultValuePattern default_value_pattern, SemIR::DefaultValuePattern default_value_pattern,
WorkItem entry) -> void { WorkItem /*entry*/) -> void {
if (!std::holds_alternative<CalleeState*>(state)) { if (!std::holds_alternative<CalleeState*>(state)) {
CARBON_FATAL("Unhandled state kind in DefaultValuePattern post-work"); 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_inst_id = results_stack_.PeekArray().back();
auto param_type_id = context_.insts().Get(param_inst_id).type_id(); 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 // If a constant was specified, we should be able to convert it into the
// type of the parameter. // type of the parameter.
if (!context_.insts().Is<SemIR::UnspecifiedValue>(default_value_inst_id)) { auto raw_default_value_inst_id =
// We should be able to convert the supplied constant into the type of context_.full_pattern_stack()
// the parameter. .GetRawDefaultValues()[default_value_pattern.default_value_id.index];
auto converted_id = auto converted_inst_id =
TryConvertToValueOfType(context_, SemIR::LocId(default_value_inst_id), context_.insts().Is<SemIR::UnspecifiedValue>(raw_default_value_inst_id)
default_value_inst_id, param_type_id); ? raw_default_value_inst_id
if (converted_id == SemIR::ErrorInst::InstId) { : ConvertToValueOfType(context_,
CARBON_DIAGNOSTIC( SemIR::LocId(raw_default_value_inst_id),
PatternDefaultValueTypeMismatch, Error, raw_default_value_inst_id, param_type_id);
"default value expression type {0} doesn't match pattern type {1}",
TypeOfInstId, TypeOfInstId); // 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(); results_stack_.PopArray();
// If something at a higher level in the stack needed these results, bubble // If something at a higher level in the stack needed these results, bubble
@@ -2,8 +2,7 @@
// Exceptions. See /LICENSE for license information. // Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
// //
// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/primitives.carbon // INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon
// EXTRA-ARGS: --dump-sem-ir-ranges=only
// //
// AUTOUPDATE // AUTOUPDATE
// TIP: To test this file alone, run: // TIP: To test this file alone, run:
@@ -14,206 +13,355 @@
// --- fail_value_not_constant.carbon // --- fail_value_not_constant.carbon
library "[[@TEST_NAME]]"; library "[[@TEST_NAME]]";
// CHECK:STDERR: fail_value_not_constant.carbon:[[@LINE+4]]:23: error: default value for pattern must be constant [PatternDefaultValueNotConstant] class C {}
// CHECK:STDERR: fn H(x: i32, y: i32 = x);
// CHECK:STDERR: ^ // 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: // CHECK:STDERR:
fn H(x: i32, y: i32 = x); fn H(x: C, y: C = x);
// --- fail_type_mismatch.carbon // --- fail_type_mismatch.carbon
library "[[@TEST_NAME]]"; 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] class C {}
// CHECK:STDERR: fn K(x: i32 = "bazz"); class D {}
// CHECK:STDERR: ^~~~~~~~~~~~~~~
// 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: // CHECK:STDERR:
fn K(x: i32 = "bazz"); fn K(x: C = {} as D);
// --- fail_pattern_defaults_not_in_parameter_list.carbon // --- fail_pattern_defaults_not_in_parameter_list.carbon
library "[[@TEST_NAME]]"; 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] class C {}
// CHECK:STDERR: let (y: i32, x: i32 = 0) = (1, 2);
// CHECK:STDERR: ^ // 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: // 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 // --- fail_required_default_values_missing.carbon
library "[[@TEST_NAME]]"; library "[[@TEST_NAME]]";
// CHECK:STDERR: fail_required_default_values_missing.carbon:[[@LINE+17]]:39: error: this pattern is missing a required default value. [RequiredPatternDefaultValueMissing] class C {}
// 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+17]]:35: error: this pattern is missing a required default value. [RequiredPatternDefaultValueMissing]
// 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: C, x: C = {}, (y: C = {}, z: C), w: C = {}, k: C);
// CHECK:STDERR: fn Z(v: i32, x: i32 = 3, (y: i32 = 2, z: i32), w: i32 = 4, k: i32); // CHECK:STDERR: ^~~~
// 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:
// CHECK:STDERR: fail_required_default_values_missing.carbon:[[@LINE+10]]:26: error: this pattern is missing a required default value. [RequiredPatternDefaultValueMissing] // 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: i32, x: i32 = 3, (y: i32 = 2, z: i32), w: i32 = 4, k: i32); // 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+7]]:60: note: this pattern is also missing a required default value. [RequiredPatternDefaultValueMissingAdditional] // 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: i32, x: i32 = 3, (y: i32 = 2, z: i32), w: i32 = 4, k: i32); // 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+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: 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: i32, x: i32 = 3, (y: i32 = 2, z: i32), w: i32 = 4, k: i32); // CHECK:STDERR: fn Z(v: C, x: C = {}, (y: C = {}, z: C), w: C = {}, k: C);
// CHECK:STDERR: ^~~~~~ // CHECK:STDERR: ^~~~
// 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 // --- fail_nesting_required_default_values_missing.carbon
library "[[@TEST_NAME]]"; 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] class C {}
// 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+14]]:36: error: this pattern is missing a required default value. [RequiredPatternDefaultValueMissing]
// 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: C, (b: C = {}, (c: C = {}, (d: C, e: C))));
// CHECK:STDERR: fn F(a: i32, (b: i32 = 0, (c: i32 = 0, (d: i32, e: i32)))); // CHECK:STDERR: ^~~~~~~~~~~~
// 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:
// CHECK:STDERR: fail_nesting_required_default_values_missing.carbon:[[@LINE+7]]:27: error: this pattern is missing a required default value. [RequiredPatternDefaultValueMissing] // 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: i32, (b: i32 = 0, (c: i32 = 0, (d: i32, e: i32)))); // 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+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: 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: i32, (b: i32 = 0, (c: i32 = 0, (d: i32, e: i32)))); // CHECK:STDERR: fn F(a: C, (b: C = {}, (c: C = {}, (d: C, e: C))));
// CHECK:STDERR: ^~~~~~ // CHECK:STDERR: ^~~~
// 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 // --- nested.carbon
library "[[@TEST_NAME]]"; library "[[@TEST_NAME]]";
class C {}
//@dump-sem-ir-begin //@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 //@dump-sem-ir-end
// --- basic.carbon // --- basic.carbon
library "[[@TEST_NAME]]"; library "[[@TEST_NAME]]";
class C {}
//@dump-sem-ir-begin //@dump-sem-ir-begin
fn F(x: i32 = 0); fn F(x: C = {});
//@dump-sem-ir-end //@dump-sem-ir-end
// CHECK:STDOUT: --- nested.carbon // CHECK:STDOUT: --- implicit.carbon
// CHECK:STDOUT: // CHECK:STDOUT:
// CHECK:STDOUT: constants { // CHECK:STDOUT: constants {
// CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete] // CHECK:STDOUT: %C: type = class_type @C [concrete]
// CHECK:STDOUT: %i32: type = class_type @Int, @Int(%int_32) [concrete] // CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete]
// CHECK:STDOUT: %pattern_type.6b6: type = pattern_type %i32 [concrete] // CHECK:STDOUT: %D: type = class_type @D [concrete]
// CHECK:STDOUT: %a.param_patt: %pattern_type.6b6 = value_param_pattern [concrete] // CHECK:STDOUT: %ImplicitAs.type.2be: type = facet_type <@ImplicitAs, @ImplicitAs(%D)> [concrete]
// CHECK:STDOUT: %a.patt: %pattern_type.6b6 = wrapper_binding_pattern a, %a.param_patt [concrete] // CHECK:STDOUT: %ImplicitAs.impl_witness: <witness> = impl_witness @C.as.ImplicitAs.impl.%ImplicitAs.impl_witness_table [concrete]
// CHECK:STDOUT: %b.param_patt: %pattern_type.6b6 = value_param_pattern [concrete] // CHECK:STDOUT: %pattern_type.d8d: type = pattern_type %D [concrete]
// CHECK:STDOUT: %b.patt: %pattern_type.6b6 = wrapper_binding_pattern b, %b.param_patt [concrete] // CHECK:STDOUT: %C.as.ImplicitAs.impl.Convert.type: type = fn_type @C.as.ImplicitAs.impl.Convert [concrete]
// CHECK:STDOUT: %c.param_patt: %pattern_type.6b6 = value_param_pattern [concrete] // CHECK:STDOUT: %C.as.ImplicitAs.impl.Convert: %C.as.ImplicitAs.impl.Convert.type = struct_value () [concrete]
// CHECK:STDOUT: %c.patt: %pattern_type.6b6 = wrapper_binding_pattern c, %c.param_patt [concrete] // CHECK:STDOUT: %ImplicitAs.facet: %ImplicitAs.type.2be = facet_value %C, (%ImplicitAs.impl_witness) [concrete]
// CHECK:STDOUT: %d.param_patt: %pattern_type.6b6 = value_param_pattern [concrete] // CHECK:STDOUT: %ImplicitAs.WithSelf.Convert.type.6cd: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%D, %ImplicitAs.facet) [concrete]
// CHECK:STDOUT: %d.patt: %pattern_type.6b6 = wrapper_binding_pattern d, %d.param_patt [concrete] // CHECK:STDOUT: %.ee7: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.6cd, %ImplicitAs.facet [concrete]
// CHECK:STDOUT: %e.param_patt: %pattern_type.6b6 = value_param_pattern [concrete] // CHECK:STDOUT: %a.param_patt: %pattern_type.d8d = value_param_pattern [concrete]
// CHECK:STDOUT: %e.patt: %pattern_type.6b6 = wrapper_binding_pattern e, %e.param_patt [concrete] // CHECK:STDOUT: %a.patt: %pattern_type.d8d = wrapper_binding_pattern a, %a.param_patt [concrete]
// CHECK:STDOUT: %tuple.type.e55: type = tuple_type (%i32, %i32) [concrete] // CHECK:STDOUT: %empty_struct: %empty_struct_type = struct_value () [concrete]
// CHECK:STDOUT: %pattern_type.394: type = pattern_type %tuple.type.e55 [concrete] // CHECK:STDOUT: %C.val: %C = struct_value () [concrete]
// CHECK:STDOUT: %.70d: %pattern_type.394 = tuple_pattern (%d.patt, %e.patt) [concrete] // CHECK:STDOUT: %.68d: %pattern_type.d8d = default_value_pattern %a.patt, index: 0 [concrete]
// CHECK:STDOUT: %tuple.type.920: type = tuple_type (%i32, %tuple.type.e55) [concrete] // CHECK:STDOUT: %C.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %C.val, %C.as.ImplicitAs.impl.Convert [concrete]
// CHECK:STDOUT: %pattern_type.e87: type = pattern_type %tuple.type.920 [concrete] // CHECK:STDOUT: %.115: ref %C = temporary invalid, %C.val [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: %F.type: type = fn_type @F [concrete] // CHECK:STDOUT: %F.type: type = fn_type @F [concrete]
// CHECK:STDOUT: %F: %F.type = struct_value () [concrete] // CHECK:STDOUT: %F: %F.type = struct_value () [concrete]
// CHECK:STDOUT: } // CHECK:STDOUT: }
// CHECK:STDOUT: // CHECK:STDOUT:
// CHECK:STDOUT: file { // CHECK:STDOUT: file {
// CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [concrete = constants.%F] { // 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.param_patt: %pattern_type.d8d = 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: %a.patt: %pattern_type.d8d = 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: %.loc10_11: %pattern_type.d8d = default_value_pattern %a.patt, index: 0 [concrete = constants.%.68d]
// 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: } { // CHECK:STDOUT: } {
// CHECK:STDOUT: %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8] // CHECK:STDOUT: %.loc10_14.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]
// CHECK:STDOUT: %int_2: Core.IntLiteral = int_value 2 [concrete = constants.%int_2.ecc] // CHECK:STDOUT: %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]
// CHECK:STDOUT: %int_3: Core.IntLiteral = int_value 3 [concrete = constants.%int_3.1ba] // CHECK:STDOUT: %.loc10_14.2: ref %C = temporary_storage
// CHECK:STDOUT: %int_4: Core.IntLiteral = int_value 4 [concrete = constants.%int_4.0c1] // CHECK:STDOUT: %.loc10_14.3: init %C to %.loc10_14.2 = class_init () [concrete = constants.%C.val]
// CHECK:STDOUT: %.loc4_66: %tuple.type.f94 = tuple_literal (%int_3, %int_4) [concrete = constants.%tuple.302] // CHECK:STDOUT: %.loc10_16.1: init %C = converted %.loc10_14.1, %.loc10_14.3 [concrete = constants.%C.val]
// CHECK:STDOUT: %.loc4_67: %tuple.type.bd0 = tuple_literal (%int_2, %.loc4_66) [concrete = constants.%tuple.b26] // CHECK:STDOUT: %a.param: %D = value_param call_param0
// CHECK:STDOUT: %.loc4_68: %tuple.type.c4f = tuple_literal (%int_1, %.loc4_67) [concrete = constants.%tuple.326] // CHECK:STDOUT: %D.ref: type = name_ref D, file.%D.decl [concrete = constants.%D]
// CHECK:STDOUT: %a.param: %i32 = value_param call_param0 // CHECK:STDOUT: %a: %D = wrapper_binding a, %a.param
// CHECK:STDOUT: %i32.loc4_9: type = type_literal constants.%i32 [concrete = constants.%i32] // CHECK:STDOUT: %impl.elem0: %.ee7 = impl_witness_access constants.%ImplicitAs.impl_witness, element0 [concrete = constants.%C.as.ImplicitAs.impl.Convert]
// CHECK:STDOUT: %a: %i32 = wrapper_binding a, %a.param // CHECK:STDOUT: %bound_method: <bound method> = bound_method %.loc10_16.1, %impl.elem0 [concrete = constants.%C.as.ImplicitAs.impl.Convert.bound]
// CHECK:STDOUT: %b.param: %i32 = value_param call_param1 // CHECK:STDOUT: %.loc10_16.2: ref %D = temporary_storage
// CHECK:STDOUT: %i32.loc4_18: type = type_literal constants.%i32 [concrete = constants.%i32] // CHECK:STDOUT: %.loc10_16.3: ref %C = temporary %.loc10_14.2, %.loc10_16.1 [concrete = constants.%.115]
// CHECK:STDOUT: %b: %i32 = wrapper_binding b, %b.param // CHECK:STDOUT: %.loc10_16.4: %C = acquire_value %.loc10_16.3 [concrete = constants.%C.val]
// CHECK:STDOUT: %c.param: %i32 = value_param call_param2 // CHECK:STDOUT: %C.as.ImplicitAs.impl.Convert.call: init %D to %.loc10_16.2 = call %bound_method(%.loc10_16.4)
// CHECK:STDOUT: %i32.loc4_27: type = type_literal constants.%i32 [concrete = constants.%i32] // CHECK:STDOUT: %.loc10_16.5: init %D = converted %.loc10_16.1, %C.as.ImplicitAs.impl.Convert.call
// CHECK:STDOUT: %c: %i32 = wrapper_binding c, %c.param // CHECK:STDOUT: %.loc10_16.6: ref %D = temporary %.loc10_16.2, %.loc10_16.5
// CHECK:STDOUT: %d.param: %i32 = value_param call_param3 // CHECK:STDOUT: %.loc10_16.7: %D = acquire_value %.loc10_16.6
// 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: <elided>
// CHECK:STDOUT: } // CHECK:STDOUT: }
// CHECK:STDOUT: } // 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: !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: // CHECK:STDOUT:
// CHECK:STDOUT: --- basic.carbon // CHECK:STDOUT: --- basic.carbon
// CHECK:STDOUT: // CHECK:STDOUT:
// CHECK:STDOUT: constants { // CHECK:STDOUT: constants {
// CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete] // CHECK:STDOUT: %C: type = class_type @C [concrete]
// CHECK:STDOUT: %i32: type = class_type @Int, @Int(%int_32) [concrete] // CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete]
// CHECK:STDOUT: %pattern_type.6b6: type = pattern_type %i32 [concrete] // CHECK:STDOUT: %pattern_type: type = pattern_type %C [concrete]
// CHECK:STDOUT: %x.param_patt: %pattern_type.6b6 = value_param_pattern [concrete] // CHECK:STDOUT: %x.param_patt: %pattern_type = value_param_pattern [concrete]
// CHECK:STDOUT: %x.patt: %pattern_type.6b6 = wrapper_binding_pattern x, %x.param_patt [concrete] // CHECK:STDOUT: %x.patt: %pattern_type = wrapper_binding_pattern x, %x.param_patt [concrete]
// CHECK:STDOUT: %int_0.5c6: Core.IntLiteral = int_value 0 [concrete] // CHECK:STDOUT: %empty_struct: %empty_struct_type = struct_value () [concrete]
// CHECK:STDOUT: %.e53: %pattern_type.6b6 = default_value_pattern %x.patt, index: 0 [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.type: type = fn_type @F [concrete]
// CHECK:STDOUT: %F: %F.type = struct_value () [concrete] // CHECK:STDOUT: %F: %F.type = struct_value () [concrete]
// CHECK:STDOUT: } // CHECK:STDOUT: }
// CHECK:STDOUT: // CHECK:STDOUT:
// CHECK:STDOUT: file { // CHECK:STDOUT: file {
// CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [concrete = constants.%F] { // 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.param_patt: %pattern_type = 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: %x.patt: %pattern_type = 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: %.loc6_11: %pattern_type = default_value_pattern %x.patt, index: 0 [concrete = constants.%.015]
// CHECK:STDOUT: } { // CHECK:STDOUT: } {
// CHECK:STDOUT: %int_0: Core.IntLiteral = int_value 0 [concrete = constants.%int_0.5c6] // CHECK:STDOUT: %.loc6_14.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]
// CHECK:STDOUT: %x.param: %i32 = value_param call_param0 // CHECK:STDOUT: %x.param: %C = value_param call_param0
// CHECK:STDOUT: %i32: type = type_literal constants.%i32 [concrete = constants.%i32] // CHECK:STDOUT: %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]
// CHECK:STDOUT: %x: %i32 = wrapper_binding x, %x.param // CHECK:STDOUT: %x: %C = wrapper_binding x, %x.param
// CHECK:STDOUT: <elided> // 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: }
// CHECK:STDOUT: // CHECK:STDOUT:
// CHECK:STDOUT: fn @F(%x.param: %i32) { // CHECK:STDOUT: fn @F(%x.param: %C) {
// CHECK:STDOUT: !default_values: // 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: }
// CHECK:STDOUT: // CHECK:STDOUT:
@@ -3,7 +3,6 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
// //
// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon // INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon
// EXTRA-ARGS: --dump-sem-ir-ranges=only
// //
// AUTOUPDATE // AUTOUPDATE
// TIP: To test this file alone, run: // TIP: To test this file alone, run:
@@ -11,19 +10,6 @@
// TIP: To dump output, run: // TIP: To dump output, run:
// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/definition/default_values.carbon // 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 // --- fail_defaults_different_values_redecl.carbon
library "[[@TEST_NAME]]"; library "[[@TEST_NAME]]";
@@ -37,114 +23,77 @@ fn F(x: i32 = 0, y: i32 = 10);
// CHECK:STDERR: // CHECK:STDERR:
fn F(unused x: i32 = 0, unused y: i32 = 22) { } fn F(unused x: i32 = 0, unused y: i32 = 22) { }
// --- fail_defaults_never_specified_redecl.carbon // --- imported_default_presence_mismatch.carbon
library "[[@TEST_NAME]]"; library "[[@TEST_NAME]]";
fn F(x: i32 = _); fn F(x: i32 = 0, y: i32 = 1, z: i32 = 2);
// 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 = _) { }
// --- default_presence_mismatch.carbon // --- fail_imported_default_presence_mismatch.impl.carbon
library "[[@TEST_NAME]]";
fn F(x: i32 = 0, y: i32 = _, z: i32 = _);
// --- fail_default_presence_mismatch.impl.carbon
impl library "[[@TEST_NAME]]"; impl library "[[@TEST_NAME]]";
// CHECK:STDERR: fail_default_presence_mismatch.impl.carbon:[[@LINE+8]]:13: error: redeclaration differs at parameter 1 [RedeclParamDiffers] // 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 = 1, unused z: i32 = 2) { } // CHECK:STDERR: fn F(unused x: i32, unused y: i32 = _, unused z: i32 = _) { }
// CHECK:STDERR: ^~~~~~ // CHECK:STDERR: ^~~~~~
// CHECK:STDERR: fail_default_presence_mismatch.impl.carbon:[[@LINE-5]]:1: in import [InImport] // CHECK:STDERR: fail_imported_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: imported_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: fn F(x: i32 = 0, y: i32 = 1, z: i32 = 2);
// CHECK:STDERR: ^~~~~~~~~~ // CHECK:STDERR: ^~~~~~~~~~
// 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]]"; library "[[@TEST_NAME]]";
fn F(x: i32 = 0, y: i32 = 10); 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]]"; 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: 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: // CHECK:STDERR:
fn F(unused x: i32 = 0, unused y: i32 = 22) { } 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 // --- redecl.carbon
library "[[@TEST_NAME]]"; library "[[@TEST_NAME]]";
fn F(x: i32 = 0) -> i32; fn F(x: i32 = 0) -> i32;
fn G(x: i32 = _) -> i32; fn G(x: i32 = 0) -> i32;
fn H(x: i32 = 0) -> i32;
//@dump-sem-ir-begin //@dump-sem-ir-begin
fn F(x: i32 = 0) -> i32 { return x; } fn F(x: i32 = 0) -> i32 { return x; }
fn G(x: i32 = 0) -> i32 { return x; } fn G(x: i32 = _) -> i32 { return x; }
fn H(x: i32 = _) -> i32 { return x; }
//@dump-sem-ir-end //@dump-sem-ir-end
// --- repeated_defaults.carbon // --- imported_repeated_defaults.carbon
library "[[@TEST_NAME]]"; library "[[@TEST_NAME]]";
fn F(x: i32 = 0) -> i32; fn F(x: i32 = 0) -> i32;
// --- repeated_defaults.impl.carbon // --- imported_repeated_defaults.impl.carbon
impl library "[[@TEST_NAME]]"; impl library "[[@TEST_NAME]]";
//@dump-sem-ir-begin //@dump-sem-ir-begin
fn F(x: i32 = 0) -> i32 { return x; } fn F(x: i32 = 0) -> i32 { return x; }
//@dump-sem-ir-end //@dump-sem-ir-end
// --- elided_defaults_in_def.carbon // --- imported_elided_defaults_in_def.carbon
library "[[@TEST_NAME]]"; library "[[@TEST_NAME]]";
fn F(x: i32 = 0) -> i32; fn F(x: i32 = 0) -> i32;
// --- elided_defaults_in_def.impl.carbon // --- imported_elided_defaults_in_def.impl.carbon
impl library "[[@TEST_NAME]]"; impl library "[[@TEST_NAME]]";
//@dump-sem-ir-begin //@dump-sem-ir-begin
fn F(x: i32 = _) -> i32 { return x; } fn F(x: i32 = _) -> i32 { return x; }
//@dump-sem-ir-end //@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: --- redecl.carbon
// CHECK:STDOUT: // CHECK:STDOUT:
// CHECK:STDOUT: constants { // 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: %.795f: Core.Form = init_form %i32 [concrete]
// CHECK:STDOUT: %return.param_patt.a9a: %pattern_type.6b6 = out_param_pattern [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: %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: <witness> = 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> = 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> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.e39, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]
// CHECK:STDOUT: %bound_method: <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.type: type = fn_type @F [concrete]
// CHECK:STDOUT: %F: %F.type = struct_value () [concrete] // CHECK:STDOUT: %F: %F.type = struct_value () [concrete]
// CHECK:STDOUT: %.d49: <unspecified_value> = unspecified_value [concrete]
// CHECK:STDOUT: %G.type: type = fn_type @G [concrete] // CHECK:STDOUT: %G.type: type = fn_type @G [concrete]
// CHECK:STDOUT: %G: %G.type = struct_value () [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: %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.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: %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: %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: %.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> = specific_function %Int.as.Copy.impl.Op.4f6, @Int.as.Copy.impl.Op(%int_32) [concrete] // CHECK:STDOUT: %Int.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %Int.as.Copy.impl.Op.4f6, @Int.as.Copy.impl.Op(%int_32) [concrete]
// CHECK:STDOUT: %.d49: <unspecified_value> = unspecified_value [concrete]
// CHECK:STDOUT: } // CHECK:STDOUT: }
// CHECK:STDOUT: // CHECK:STDOUT:
// CHECK:STDOUT: imports { // 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: %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: %Copy.impl_witness_table.8d2 = impl_witness_table (%Core.import_ref.cd6), @Int.as.Copy.impl [concrete]
// CHECK:STDOUT: } // CHECK:STDOUT: }
// CHECK:STDOUT: // CHECK:STDOUT:
// CHECK:STDOUT: file { // 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> = 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> = 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> = 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.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: %x.patt: %pattern_type.6b6 = wrapper_binding_pattern x, %x.param_patt [concrete = constants.%x.patt]
// CHECK:STDOUT: %.loc8_13: %pattern_type.6b6 = default_value_pattern %x.patt, index: 0 [concrete = constants.%.e53] // CHECK:STDOUT: %.loc8_13: %pattern_type.6b6 = default_value_pattern %x.patt, 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.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: %return.patt: %pattern_type.6b6 = return_slot_pattern %return.param_patt, %i32.loc8_21 [concrete = constants.%return.patt.e1b]
// CHECK:STDOUT: } { // CHECK:STDOUT: } {
// CHECK:STDOUT: %int_0.loc8: Core.IntLiteral = int_value 0 [concrete = constants.%int_0.5c6] // CHECK:STDOUT: %.loc8_15: <unspecified_value> = unspecified_value [concrete = constants.%.d49]
// CHECK:STDOUT: %i32.loc8_21: type = type_literal constants.%i32 [concrete = constants.%i32] // 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: %.loc8_21: Core.Form = init_form %i32.loc8_21 [concrete = constants.%.795f]
// CHECK:STDOUT: %x.param.loc8: %i32 = value_param call_param0 // 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: %i32.loc8_9: type = type_literal constants.%i32 [concrete = constants.%i32]
// CHECK:STDOUT: %x.loc8: %i32 = wrapper_binding x, %x.param.loc8 // CHECK:STDOUT: %x.loc8: %i32 = wrapper_binding x, %x.param.loc8
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %return.param.loc8: ref %i32 = out_param call_param1 // CHECK:STDOUT: %return.param.loc8: ref %i32 = out_param call_param1
// CHECK:STDOUT: %return.loc8: ref %i32 = return_slot %return.param.loc8 // CHECK:STDOUT: %return.loc8: ref %i32 = return_slot %return.param.loc8
// CHECK:STDOUT: } // 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: <elided>
// 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> = 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: // 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: !default_values:
// CHECK:STDOUT: constants.%int_0.5c6: Core.IntLiteral = int_value 0 [concrete] // CHECK:STDOUT: <elided>
// 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> = bound_method %x.ref, %impl.elem0.loc7_34
// CHECK:STDOUT: %specific_fn.loc7_34: <specific function> = 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> = 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: <elided>
// CHECK:STDOUT: // CHECK:STDOUT:
// CHECK:STDOUT: !entry: // CHECK:STDOUT: !entry:
// CHECK:STDOUT: %x.ref: %i32 = name_ref x, %x.loc8 // 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: return %Int.as.Copy.impl.Op.call
// CHECK:STDOUT: } // CHECK:STDOUT: }
// CHECK:STDOUT: // CHECK:STDOUT:
// CHECK:STDOUT: fn @G(%x.param.loc9: %i32) -> out %return.param.loc9: %i32 { // CHECK:STDOUT: --- imported_repeated_defaults.impl.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.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> = bound_method %x.ref, %impl.elem0.loc9
// CHECK:STDOUT: %specific_fn.loc9: <specific function> = 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> = 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> = bound_method %x.ref, %impl.elem0.loc10
// CHECK:STDOUT: %specific_fn.loc10: <specific function> = 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> = 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: // CHECK:STDOUT:
// CHECK:STDOUT: constants { // 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: %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: %int_32: Core.IntLiteral = int_value 32 [concrete]
// CHECK:STDOUT: %i32: type = class_type @Int, @Int(%int_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: %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: %.795f: Core.Form = init_form %i32 [concrete]
// CHECK:STDOUT: %return.param_patt.a9a: %pattern_type.6b6 = out_param_pattern [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: %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: <witness> = 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> = 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> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.e39, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]
// CHECK:STDOUT: %bound_method: <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.type: type = fn_type @F [concrete]
// CHECK:STDOUT: %F: %F.type = struct_value () [concrete] // CHECK:STDOUT: %F: %F.type = struct_value () [concrete]
// CHECK:STDOUT: %Copy.type: type = facet_type <@Copy> [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: // CHECK:STDOUT:
// CHECK:STDOUT: imports { // 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: %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: %Copy.impl_witness_table.8d2 = impl_witness_table (%Core.import_ref.cd6), @Int.as.Copy.impl [concrete]
// CHECK:STDOUT: } // 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: %x.param: %i32 = value_param call_param0
// CHECK:STDOUT: %i32.loc4_9: type = type_literal constants.%i32 [concrete = constants.%i32] // CHECK:STDOUT: %i32.loc4_9: type = type_literal constants.%i32 [concrete = constants.%i32]
// CHECK:STDOUT: %x: %i32 = wrapper_binding x, %x.param // CHECK:STDOUT: %x: %i32 = wrapper_binding x, %x.param
// CHECK:STDOUT: <elided> // 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> = 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> = 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> = 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.param: ref %i32 = out_param call_param1
// CHECK:STDOUT: %return: ref %i32 = return_slot %return.param // CHECK:STDOUT: %return: ref %i32 = return_slot %return.param
// CHECK:STDOUT: } // CHECK:STDOUT: }
// CHECK:STDOUT: } // 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: !default_values:
// CHECK:STDOUT: constants.%int_0.5c6: Core.IntLiteral = int_value 0 [concrete] // CHECK:STDOUT: <elided>
// CHECK:STDOUT: // CHECK:STDOUT:
// CHECK:STDOUT: !entry: // CHECK:STDOUT: !entry:
// CHECK:STDOUT: %x.ref: %i32 = name_ref x, %x // 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: %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> = bound_method %x.ref, %impl.elem0.loc4 // CHECK:STDOUT: %bound_method.loc4_34.1: <bound method> = bound_method %x.ref, %impl.elem0.loc4_34
// CHECK:STDOUT: %specific_fn.loc4: <specific function> = specific_function %impl.elem0.loc4, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn] // CHECK:STDOUT: %specific_fn.loc4_34: <specific function> = 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> = bound_method %x.ref, %specific_fn.loc4 // CHECK:STDOUT: %bound_method.loc4_34.2: <bound method> = 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: %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: return %Int.as.Copy.impl.Op.call
// CHECK:STDOUT: } // CHECK:STDOUT: }
// 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:
// CHECK:STDOUT: constants { // CHECK:STDOUT: constants {
// CHECK:STDOUT: %N: Core.IntLiteral = symbolic_binding N, 0 [symbolic] // 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: %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.type: type = fn_type @F [concrete]
// CHECK:STDOUT: %F: %F.type = struct_value () [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: %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.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: %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: }
// 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: !default_values:
// CHECK:STDOUT: constants.%int_0: Core.IntLiteral = int_value 0 [concrete] // CHECK:STDOUT: <elided>
// CHECK:STDOUT: // CHECK:STDOUT:
// CHECK:STDOUT: !entry: // CHECK:STDOUT: !entry:
// CHECK:STDOUT: %x.ref: %i32 = name_ref x, %x // 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: return %Int.as.Copy.impl.Op.call
// CHECK:STDOUT: } // CHECK:STDOUT: }
// 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: <witness> = 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> = 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: <elided>
// 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> = bound_method %x.ref, %impl.elem0.loc4
// CHECK:STDOUT: %specific_fn.loc4: <specific function> = 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> = 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:
+1 -1
View File
@@ -246,7 +246,7 @@ static auto CloneFunctionDecl(Context& context, SemIR::LocId loc_id,
{ {
.call_param_patterns_id = match_results.call_param_patterns_id, .call_param_patterns_id = match_results.call_param_patterns_id,
.call_params_id = match_results.call_params_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, .call_param_ranges = match_results.param_ranges,
.return_type_inst_id = return_type_inst_id, .return_type_inst_id = return_type_inst_id,
.return_form_inst_id = return_form_inst_id, .return_form_inst_id = return_form_inst_id,
+2 -3
View File
@@ -621,11 +621,10 @@ CARBON_DIAGNOSTIC_KIND(RequiredPatternDefaultValueMissing)
CARBON_DIAGNOSTIC_KIND(RequiredPatternDefaultValueFirstDefault) CARBON_DIAGNOSTIC_KIND(RequiredPatternDefaultValueFirstDefault)
CARBON_DIAGNOSTIC_KIND(RequiredPatternDefaultValueMissingAdditional) CARBON_DIAGNOSTIC_KIND(RequiredPatternDefaultValueMissingAdditional)
CARBON_DIAGNOSTIC_KIND(PatternDefaultValueDiffers) CARBON_DIAGNOSTIC_KIND(PatternDefaultValueDiffers)
CARBON_DIAGNOSTIC_KIND(PatternDefaultValueDiffersNote)
CARBON_DIAGNOSTIC_KIND(PatternDefaultValueNotConstant) CARBON_DIAGNOSTIC_KIND(PatternDefaultValueNotConstant)
CARBON_DIAGNOSTIC_KIND(PatternDefaultValueNotInParameterList) CARBON_DIAGNOSTIC_KIND(PatternDefaultValueNotInParameterList)
CARBON_DIAGNOSTIC_KIND(PatternDefaultValueTypeMismatch) CARBON_DIAGNOSTIC_KIND(PatternDefaultValueNotSpecified)
CARBON_DIAGNOSTIC_KIND(PatternDefaultValueNeverSpecified)
CARBON_DIAGNOSTIC_KIND(PatternDefaultValueNeverSpecifiedNote)
CARBON_DIAGNOSTIC_KIND(TuplePatternSizeDoesntMatchLiteral) CARBON_DIAGNOSTIC_KIND(TuplePatternSizeDoesntMatchLiteral)
// Unused diagnostics. // Unused diagnostics.
+2 -13
View File
@@ -599,25 +599,14 @@ auto Formatter::FormatFunction(FunctionId id, const Function& fn) -> void {
} }
if (!fn.body_block_ids.empty() || if (!fn.body_block_ids.empty() ||
fn.call_param_default_values_id.has_value()) { fn.call_param_default_values_id != SemIR::InstBlockId::Empty) {
out() << ' '; out() << ' ';
OpenBrace(); OpenBrace();
if (fn.call_param_default_values_id.has_value()) { if (fn.call_param_default_values_id != SemIR::InstBlockId::Empty) {
IndentLabel(); IndentLabel();
out() << "!default_values:\n"; 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); FormatCodeBlock(fn.call_param_default_values_id);
use_dump_sem_ir_ranges_ = format_mask;
} }
for (auto block_id : fn.body_block_ids) { for (auto block_id : fn.body_block_ids) {
+2 -3
View File
@@ -82,8 +82,7 @@ struct FunctionFields {
// because it is relevant only for a function definition. // because it is relevant only for a function definition.
InstBlockId call_params_id; InstBlockId call_params_id;
// Instructions representing the canonical default values for parameters. // Instructions representing the default values for parameters.
// TODO: Change this to non-canonical values.
InstBlockId call_param_default_values_id; InstBlockId call_param_default_values_id;
// The index ranges within the `Call` parameters that correspond to the // 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()) { if (call_params_id.has_value()) {
out << ", call_params_id: " << call_params_id; 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; out << ", call_param_default_values_id: " << call_param_default_values_id;
} }
if (return_type_inst_id.has_value()) { if (return_type_inst_id.has_value()) {