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

lazy field index #4514

Open
wants to merge 11 commits into
base: trunk
Choose a base branch
from
Open

Conversation

dwblaikie
Copy link
Contributor

@dwblaikie dwblaikie commented Nov 12, 2024

We considered a couple of other options for this:

But currently moving forward with this direction - of initializing field indexes with an invalid value until the end of the class definition, then assigning field indexes during construction of the class's object representation struct type. This direction might reinforce/help avoid premature access to the object representation before the class is complete, and give a single place where class layout is done (at class completion) if we want to add more options there, such as class layout optimizations, etc.

This patch still has problems with object initialization (that #4515 does not have/does address) but does address normal obj.member access correctly.

@dwblaikie dwblaikie marked this pull request as ready for review November 12, 2024 21:43
@dwblaikie
Copy link
Contributor Author

Ended up deciding maybe we could use this review as the central point for the design discussion - since the other two patches are a bit more drafty, so I'll leave them in draft mode, but linked from here for context - but maybe keeping the design discussion here in this PR.

This way if the type_id of the FieldDecl is anything other than Error or
UnboundElementType, this should check-fail at the
`GetAs<UnboundElementType>`. We could add a more explicit check, but I
tend to err towards relying on implicit checks to avoid making the code
too noisy
Copy link
Contributor

@zygoloid zygoloid left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Direction here looks good, thanks!

toolchain/check/handle_binding_pattern.cpp Outdated Show resolved Hide resolved
toolchain/check/handle_binding_pattern.cpp Outdated Show resolved Hide resolved
toolchain/check/handle_class.cpp Outdated Show resolved Hide resolved
Comment on lines 672 to 677
llvm::SmallVector<SemIR::StructTypeField> struct_type_fields;
struct_type_fields.reserve(context.field_decls_stack().PeekArray().size());

return CheckCompleteAdapterClassType(context, node_id, class_id, fields_id);
return CheckCompleteAdapterClassType(
context, node_id, class_id,
AddStructTypeFields(context, struct_type_fields));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're going to a bit of effort to build a collection of fields for an adapter here (and adapters can't have fields). I wonder if we could sink this field handling code down into CheckCompleteAdapterClassType and have it just look at and diagnose the first element in the top of field_decls_stack if it's non-empty (and in any case pop it).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, sure - b53b6b1 - it has a minor observable sem-ir output change, which is that the field decls for the adapter have invalid indexes, since they never get updated/set by AddstructTypeFields - since the fields are invalid anyway, that seems fine?

toolchain/check/handle_class.cpp Outdated Show resolved Hide resolved
auto field_decl = context.insts().GetAs<SemIR::FieldDecl>(field_decl_id);
field_decl.index =
SemIR::ElementIndex{static_cast<int>(struct_type_fields.size())};
context.sem_ir().insts().Set(field_decl_id, field_decl);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than directly setting the instruction, I think it'd be good to add something like auto Check::Context::ReplaceInstPreservingConstantValue(SemIR::InstId inst_id, SemIR::Inst inst) -> void, analogous to the existing ReplaceInstBeforeConstantUse. For extra safety, maybe we could make it recompute the constant value after the replacement and CHECK-fail if it's different.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, done in 89b88ff - at least a best guess at the requested assert/figuring out how the constant evaluation works. (since the constant value of a FieldDecl is currently just the inst_id itself, so it can't change, so I couldn't really think of anything to do to test the assertion works (like I tried modifying the FieldDecl's name_id or type_id, but those aren't part of the constant))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants