Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Superficial support for template modifier on symbolic bindings. #4948

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions toolchain/check/deduce.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,7 @@ auto DeductionContext::Deduce() -> bool {
// compile-time constant.
case CARBON_KIND(SemIR::SymbolicBindingPattern bind): {
auto& entity_name = context().entity_names().Get(bind.entity_name_id);
auto index = entity_name.bind_index;
auto index = entity_name.bind_index();
if (!index.has_value()) {
break;
}
Expand Down Expand Up @@ -396,7 +396,7 @@ auto DeductionContext::Deduce() -> bool {
// deducing `[T:! type](x: T)` against `("foo")` deduces `T` as `String`.
case CARBON_KIND(SemIR::BindSymbolicName bind): {
auto& entity_name = context().entity_names().Get(bind.entity_name_id);
auto index = entity_name.bind_index;
auto index = entity_name.bind_index();
if (!index.has_value() || index < first_deduced_index_ ||
non_deduced_indexes_[index.index - first_deduced_index_.index]) {
break;
Expand Down
6 changes: 4 additions & 2 deletions toolchain/check/eval.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1862,7 +1862,7 @@ static auto TryEvalInstInContext(EvalContext& eval_context,
// argument of that specific, its constant value is the corresponding
// argument value.
if (auto value =
eval_context.GetCompileTimeBindValue(bind_name.bind_index);
eval_context.GetCompileTimeBindValue(bind_name.bind_index());
value.has_value()) {
return value;
}
Expand All @@ -1871,6 +1871,7 @@ static auto TryEvalInstInContext(EvalContext& eval_context,
// original, with no equivalent value.
bind.entity_name_id =
eval_context.entity_names().MakeCanonical(bind.entity_name_id);
// TODO: Propagate the `is_template` flag into the phase.
return MakeConstantResult(eval_context.context(), bind, Phase::Symbolic);
}
case CARBON_KIND(SemIR::BindSymbolicName bind): {
Expand All @@ -1885,10 +1886,11 @@ static auto TryEvalInstInContext(EvalContext& eval_context,
// argument of that specific, its constant value is the corresponding
// argument value.
if (auto value =
eval_context.GetCompileTimeBindValue(bind_name.bind_index);
eval_context.GetCompileTimeBindValue(bind_name.bind_index());
value.has_value()) {
return value;
}
// TODO: Propagate the `is_template` flag into the phase.
phase = Phase::Symbolic;
}
// The constant form of a symbolic binding is an idealized form of the
Expand Down
3 changes: 2 additions & 1 deletion toolchain/check/generic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,8 @@ class RebuildGenericConstantInEvalBlockCallbacks final
context_.insts().TryGetAs<SemIR::BindSymbolicName>(inst_id)) {
if (context_.entity_names()
.Get(binding->entity_name_id)
.bind_index.has_value()) {
.bind_index()
.has_value()) {
inst_id = Rebuild(inst_id, *binding);
return true;
}
Expand Down
3 changes: 1 addition & 2 deletions toolchain/check/handle_alias.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,7 @@ auto HandleParseNode(Context& context, Parse::AliasId /*node_id*/) -> bool {

auto entity_name_id = context.entity_names().Add(
{.name_id = name_context.name_id_for_new_inst(),
.parent_scope_id = name_context.parent_scope_id,
.bind_index = SemIR::CompileTimeBindIndex::None});
.parent_scope_id = name_context.parent_scope_id});

auto alias_type_id = SemIR::TypeId::None;
auto alias_value_id = SemIR::InstId::None;
Expand Down
62 changes: 29 additions & 33 deletions toolchain/check/handle_binding_pattern.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,22 +28,16 @@ static auto HandleAnyBindingPattern(Context& context, Parse::NodeId node_id,
SemIR::ExprRegionId type_expr_region_id =
EndSubpatternAsExpr(context, cast_type_inst_id);

// Every other kind of pattern binding has a name.
auto [name_node, name_id] = context.node_stack().PopNameWithNodeId();

// Determine whether we're handling an associated constant. These share the
// syntax for a compile-time binding, but don't behave like other compile-time
// bindings.
// TODO: Consider using a different parse node kind to make this easier.
bool is_associated_constant = false;
// The name in a template binding may be wrapped in `template`.
bool is_generic = node_kind == Parse::NodeKind::CompileTimeBindingPattern;
if (is_generic) {
auto inst_id = context.scope_stack().PeekInstId();
is_associated_constant = inst_id.has_value() &&
context.insts().Is<SemIR::InterfaceDecl>(inst_id);
}
auto is_template =
context.node_stack()
.PopAndDiscardSoloNodeIdIf<Parse::NodeKind::TemplateBindingName>();
// A non-generic template binding is diagnosed by the parser.
is_template &= is_generic;

bool needs_compile_time_binding = is_generic && !is_associated_constant;
// Every other kind of pattern binding has a name.
auto [name_node, name_id] = context.node_stack().PopNameWithNodeId();

const DeclIntroducerState& introducer =
context.decl_introducer_state_stack().innermost();
Expand All @@ -53,16 +47,12 @@ static auto HandleAnyBindingPattern(Context& context, Parse::NodeId node_id,
auto binding_pattern_id = SemIR::InstId::None;
// TODO: Eventually the name will need to support associations with other
// scopes, but right now we don't support qualified names here.
auto entity_name_id = context.entity_names().Add(
{.name_id = name_id,
.parent_scope_id = context.scope_stack().PeekNameScopeId(),
// TODO: Don't allocate a compile-time binding index for an associated
// constant declaration.
.bind_index = needs_compile_time_binding
? context.scope_stack().AddCompileTimeBinding()
: SemIR::CompileTimeBindIndex::None});
auto entity_name_id = context.entity_names().AddSymbolicBindingName(
name_id, context.scope_stack().PeekNameScopeId(),
is_generic ? context.scope_stack().AddCompileTimeBinding()
: SemIR::CompileTimeBindIndex::None,
is_template);
if (is_generic) {
// TODO: Create a `BindTemplateName` instead inside a `template` pattern.
bind_id = context.AddInstInNoBlock(SemIR::LocIdAndInst(
name_node, SemIR::BindSymbolicName{.type_id = cast_type_id,
.entity_name_id = entity_name_id,
Expand All @@ -83,7 +73,7 @@ static auto HandleAnyBindingPattern(Context& context, Parse::NodeId node_id,

// Add name to lookup immediately, so it can be used in the rest of the
// enclosing pattern.
if (needs_compile_time_binding) {
if (is_generic) {
context.scope_stack().PushCompileTimeBinding(bind_id);
}
auto name_context =
Expand Down Expand Up @@ -114,7 +104,7 @@ static auto HandleAnyBindingPattern(Context& context, Parse::NodeId node_id,
// so we handle it separately.
if (auto parent_class_decl =
context.scope_stack().GetCurrentScopeAs<SemIR::ClassDecl>();
parent_class_decl.has_value() &&
parent_class_decl.has_value() && !is_generic &&
node_kind == Parse::NodeKind::VarBindingPattern) {
cast_type_id = AsConcreteType(
context, cast_type_id, type_node,
Expand All @@ -131,9 +121,7 @@ static auto HandleAnyBindingPattern(Context& context, Parse::NodeId node_id,
cast_type_id);
});
auto binding_id =
is_generic
? Parse::NodeId::None
: context.parse_tree().As<Parse::VarBindingPatternId>(node_id);
context.parse_tree().As<Parse::VarBindingPatternId>(node_id);
auto& class_info = context.classes().Get(parent_class_decl->class_id);
auto field_type_id =
context.GetUnboundElementType(class_info.self_type_id, cast_type_id);
Expand All @@ -157,12 +145,18 @@ static auto HandleAnyBindingPattern(Context& context, Parse::NodeId node_id,
context.scope_stack().GetCurrentScopeAs<SemIR::InterfaceDecl>();
parent_interface_decl.has_value() && is_generic) {
cast_type_id = AsCompleteType(context, cast_type_id, type_node, [&] {
CARBON_DIAGNOSTIC(IncompleteTypeInAssociatedDecl, Error,
CARBON_DIAGNOSTIC(IncompleteTypeInAssociatedConstantDecl, Error,
"associated constant has incomplete type {0}",
SemIR::TypeId);
return context.emitter().Build(type_node, IncompleteTypeInAssociatedDecl,
cast_type_id);
return context.emitter().Build(
type_node, IncompleteTypeInAssociatedConstantDecl, cast_type_id);
});
if (is_template) {
CARBON_DIAGNOSTIC(TemplateBindingInAssociatedConstantDecl, Error,
"associated constant has `template` binding");
context.emitter().Emit(type_node,
TemplateBindingInAssociatedConstantDecl);
}

SemIR::AssociatedConstantDecl assoc_const_decl = {
.type_id = cast_type_id,
Expand Down Expand Up @@ -357,8 +351,10 @@ auto HandleParseNode(Context& context, Parse::AddrId node_id) -> bool {
return true;
}

auto HandleParseNode(Context& context, Parse::TemplateId node_id) -> bool {
return context.TODO(node_id, "HandleTemplate");
auto HandleParseNode(Context& context, Parse::TemplateBindingNameId node_id)
-> bool {
context.node_stack().Push(node_id);
return true;
}

} // namespace Carbon::Check
8 changes: 4 additions & 4 deletions toolchain/check/handle_interface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -169,10 +169,10 @@ auto HandleParseNode(Context& context,
// We model `Self` as a symbolic binding whose type is the interface.
// Because there is no equivalent non-symbolic value, we use `None` as
// the `value_id` on the `BindSymbolicName`.
auto entity_name_id = context.entity_names().Add(
{.name_id = SemIR::NameId::SelfType,
.parent_scope_id = interface_info.scope_id,
.bind_index = context.scope_stack().AddCompileTimeBinding()});
auto entity_name_id = context.entity_names().AddSymbolicBindingName(
SemIR::NameId::SelfType, interface_info.scope_id,
context.scope_stack().AddCompileTimeBinding(),
/*is_template=*/false);
interface_info.self_param_id =
context.AddInst(SemIR::LocIdAndInst::NoLoc<SemIR::BindSymbolicName>(
{.type_id = self_type_id,
Expand Down
4 changes: 1 addition & 3 deletions toolchain/check/handle_where.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,7 @@ auto HandleParseNode(Context& context, Parse::WhereOperandId node_id) -> bool {
// expression to the left of `where`, so `MyInterface` in the example above.
auto entity_name_id = context.entity_names().Add(
{.name_id = SemIR::NameId::PeriodSelf,
.parent_scope_id = context.scope_stack().PeekNameScopeId(),
// `None` because this is not the parameter of a generic.
.bind_index = SemIR::CompileTimeBindIndex::None});
.parent_scope_id = context.scope_stack().PeekNameScopeId()});
auto inst_id =
context.AddInst(SemIR::LocIdAndInst::NoLoc<SemIR::BindSymbolicName>(
{.type_id = self_type_id,
Expand Down
12 changes: 3 additions & 9 deletions toolchain/check/import.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -179,9 +179,7 @@ static auto CopySingleNameScopeFromImportIR(
// Produce the namespace for the entry.
auto make_import_id = [&]() {
auto entity_name_id = context.entity_names().Add(
{.name_id = name_id,
.parent_scope_id = parent_scope_id,
.bind_index = SemIR::CompileTimeBindIndex::None});
{.name_id = name_id, .parent_scope_id = parent_scope_id});
auto import_ir_inst_id = context.import_ir_insts().Add(
{.ir_id = ir_id, .inst_id = import_inst_id});
auto inst_id = context.AddInstInNoBlock(
Expand Down Expand Up @@ -273,9 +271,7 @@ static auto AddImportRefOrMerge(Context& context, SemIR::ImportIRId ir_id,
auto& entry = parent_scope.GetEntry(entry_id);
if (inserted) {
auto entity_name_id = context.entity_names().Add(
{.name_id = name_id,
.parent_scope_id = parent_scope_id,
.bind_index = SemIR::CompileTimeBindIndex::None});
{.name_id = name_id, .parent_scope_id = parent_scope_id});
entry.result = SemIR::ScopeLookupResult::MakeFound(
AddImportRef(context, {.ir_id = ir_id, .inst_id = import_inst_id},
entity_name_id),
Expand Down Expand Up @@ -313,9 +309,7 @@ static auto AddScopedImportRef(Context& context,
SemIR::AccessKind access_kind) -> SemIR::InstId {
// Add an ImportRef for other instructions.
auto impl_entity_name_id = context.entity_names().Add(
{.name_id = name_id,
.parent_scope_id = parent_scope_id,
.bind_index = SemIR::CompileTimeBindIndex::None});
{.name_id = name_id, .parent_scope_id = parent_scope_id});
auto import_ref_id = AddImportRef(context, import_inst, impl_entity_name_id);
parent_scope.AddRequired({.name_id = name_id,
.result = SemIR::ScopeLookupResult::MakeFound(
Expand Down
26 changes: 12 additions & 14 deletions toolchain/check/import_ref.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1024,9 +1024,7 @@ static auto GetLocalParamPatternsId(ImportContext& context,
switch (binding.kind) {
case SemIR::BindingPattern::Kind: {
auto entity_name_id = context.local_entity_names().Add(
{.name_id = name_id,
.parent_scope_id = SemIR::NameScopeId::None,
.bind_index = SemIR::CompileTimeBindIndex::None});
{.name_id = name_id, .parent_scope_id = SemIR::NameScopeId::None});
new_param_id =
context.local_context().AddInstInNoBlock<SemIR::BindingPattern>(
AddImportIRInst(context, binding_id),
Expand Down Expand Up @@ -1279,9 +1277,7 @@ static auto AddAssociatedEntities(ImportContext& context,
}
auto name_id = GetLocalNameId(context, import_name_id);
auto entity_name_id = context.local_entity_names().Add(
{.name_id = name_id,
.parent_scope_id = local_name_scope_id,
.bind_index = SemIR::CompileTimeBindIndex::None});
{.name_id = name_id, .parent_scope_id = local_name_scope_id});
new_associated_entities.push_back(
AddImportRef(context, inst_id, entity_name_id));
}
Expand Down Expand Up @@ -1531,10 +1527,11 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver,
const auto& import_entity_name =
resolver.import_entity_names().Get(inst.entity_name_id);
auto name_id = GetLocalNameId(resolver, import_entity_name.name_id);
auto entity_name_id = resolver.local_entity_names().Add(
{.name_id = name_id,
.parent_scope_id = SemIR::NameScopeId::None,
.bind_index = import_entity_name.bind_index});
// TODO: Use the same `EntityName` for the `SymbolicBindingPattern` and the
// `BindSymbolicName`.
auto entity_name_id = resolver.local_entity_names().AddSymbolicBindingName(
name_id, SemIR::NameScopeId::None, import_entity_name.bind_index(),
import_entity_name.is_template);
return ResolveAs<SemIR::BindSymbolicName>(
resolver,
{.type_id = resolver.local_context().GetTypeIdForTypeConstant(type_id),
Expand All @@ -1553,10 +1550,11 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver,
const auto& import_entity_name =
resolver.import_entity_names().Get(inst.entity_name_id);
auto name_id = GetLocalNameId(resolver, import_entity_name.name_id);
auto entity_name_id = resolver.local_entity_names().Add(
{.name_id = name_id,
.parent_scope_id = SemIR::NameScopeId::None,
.bind_index = import_entity_name.bind_index});
// TODO: Use the same `EntityName` for the `SymbolicBindingPattern` and the
// `BindSymbolicName`.
auto entity_name_id = resolver.local_entity_names().AddSymbolicBindingName(
name_id, SemIR::NameScopeId::None, import_entity_name.bind_index(),
import_entity_name.is_template);
return ResolveAs<SemIR::SymbolicBindingPattern>(
resolver,
{.type_id = resolver.local_context().GetTypeIdForTypeConstant(type_id),
Expand Down
2 changes: 1 addition & 1 deletion toolchain/check/node_stack.h
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,7 @@ class NodeStack {
case Parse::NodeKind::StructLiteralStart:
case Parse::NodeKind::StructTypeLiteralField:
case Parse::NodeKind::StructTypeLiteralStart:
case Parse::NodeKind::TemplateBindingName:
case Parse::NodeKind::TupleLiteralStart:
case Parse::NodeKind::TuplePatternStart:
case Parse::NodeKind::VariableInitializer:
Expand Down Expand Up @@ -508,7 +509,6 @@ class NodeStack {
case Parse::NodeKind::StructLiteralComma:
case Parse::NodeKind::StructFieldDesignator:
case Parse::NodeKind::StructTypeLiteralComma:
case Parse::NodeKind::Template:
case Parse::NodeKind::TupleLiteralComma:
return Id::Kind::Invalid;
default:
Expand Down
2 changes: 1 addition & 1 deletion toolchain/check/subst.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,7 @@ class SubstConstantCallbacks final : public SubstInstCallbacks {
// TODO: Consider building a hash map for substitutions. We might have a
// lot of them.
for (auto [bind_index, replacement_id] : substitutions_) {
if (context_.entity_names().Get(entity_name_id).bind_index ==
if (context_.entity_names().Get(entity_name_id).bind_index() ==
bind_index) {
// This is the binding we're replacing. Perform substitution.
inst_id = context_.constant_values().GetInstId(replacement_id);
Expand Down
Loading