Move default value inst ids to a dedicated value store. (#7810)

Per #7737 we move the default value `InstId` storage from
a block in the `SemIR::Function` data structure to a
`SemIR::File` scoped `ValueStore`.

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