mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-04 06:31:04 +01:00
Add a Field node for fields in a class. (#3332)
This replaces the use of `VarStorage` in this case. Add an `UnboundFieldType` type as the type of a field, in cases where it's referenced without an accompanying object. Add a `BindName` node to describe the name binding performed for both variables and fields so that we can handle them more uniformly.
This commit is contained in:
@@ -29,29 +29,50 @@ auto HandlePatternBinding(Context& context, Parse::Node parse_node) -> bool {
|
||||
|
||||
// Allocate a node of the appropriate kind, linked to the name for error
|
||||
// locations.
|
||||
// TODO: Each of these cases should create a `BindName` node.
|
||||
switch (auto context_parse_node_kind = context.parse_tree().node_kind(
|
||||
context.node_stack().PeekParseNode())) {
|
||||
case Parse::NodeKind::VariableIntroducer:
|
||||
case Parse::NodeKind::VariableIntroducer: {
|
||||
// A `var` declaration at class scope introduces a field.
|
||||
auto enclosing_class_decl =
|
||||
context.GetCurrentScopeAs<SemIR::ClassDeclaration>();
|
||||
if (!context.TryToCompleteType(cast_type_id, [&] {
|
||||
CARBON_DIAGNOSTIC(IncompleteTypeInVarDeclaration, Error,
|
||||
"Variable has incomplete type `{0}`.",
|
||||
"{0} has incomplete type `{1}`.", llvm::StringRef,
|
||||
std::string);
|
||||
return context.emitter().Build(
|
||||
type_node_copy, IncompleteTypeInVarDeclaration,
|
||||
enclosing_class_decl ? "Field" : "Variable",
|
||||
context.sem_ir().StringifyType(cast_type_id, true));
|
||||
})) {
|
||||
cast_type_id = SemIR::TypeId::Error;
|
||||
}
|
||||
SemIR::NodeId value_id = SemIR::NodeId::Invalid;
|
||||
SemIR::TypeId value_type_id = cast_type_id;
|
||||
if (enclosing_class_decl) {
|
||||
auto& class_info =
|
||||
context.classes().Get(enclosing_class_decl->class_id);
|
||||
auto field_type_node_id = context.AddNode(SemIR::UnboundFieldType{
|
||||
parse_node, context.GetBuiltinType(SemIR::BuiltinKind::TypeType),
|
||||
class_info.self_type_id, cast_type_id});
|
||||
value_type_id = context.CanonicalizeType(field_type_node_id);
|
||||
value_id =
|
||||
context.AddNode(SemIR::Field{parse_node, value_type_id, name_id});
|
||||
} else {
|
||||
value_id = context.AddNode(
|
||||
SemIR::VarStorage{name_node, value_type_id, name_id});
|
||||
}
|
||||
context.AddNodeAndPush(
|
||||
parse_node, SemIR::VarStorage{name_node, cast_type_id, name_id});
|
||||
parse_node,
|
||||
SemIR::BindName{name_node, value_type_id, name_id, value_id});
|
||||
break;
|
||||
}
|
||||
|
||||
case Parse::NodeKind::ParameterListStart:
|
||||
// Parameters can have incomplete types in a function declaration, but not
|
||||
// in a function definition. We don't know which kind we have here.
|
||||
context.AddNodeAndPush(
|
||||
parse_node, SemIR::Parameter{name_node, cast_type_id, name_id});
|
||||
// TODO: Create a `BindName` node.
|
||||
break;
|
||||
|
||||
case Parse::NodeKind::LetIntroducer:
|
||||
|
||||
Reference in New Issue
Block a user