Connect impls to their containing match_first block (#7486)

When we check an `impl` decl, find the containing `match_first` block,
if any, and store a connection to it in the `SemIR::Impl` structure,
along with the impl's position in that `match_first` block so that we
can sort/prioritize the `SemIR::Impl`s later.

Also, update the `is_final` flag if the `match_first` block is modified
as `final`. But ensure we diagnose trying to put a `final impl`, or a
redeclaration of one, in a `match_first` block. Also diagnose if an impl
is attached to a `match_first` block more than once - either in two
different blocks or in the same block at different positions.

Putting the `match_first` connection on the `SemIR::Impl` structure
means we have to import it, so implement import and add a smoke test for
that, which ensures nothing explodes.

Drop the `scope_stack` entry for the `match_first` block, as it was not
needed. Once we started tracking the `match_first` size on the `Context`
class, it became more straightforward to just store the `match_first`
decl `InstId` in the same place. The `match_first` block is not supposed
to act like a different scope for the purpose of redecls anyhow, so it's
a bit simpler this way.
This commit is contained in:
Dana Jansens
2026-07-13 19:14:38 +00:00
committed by GitHub
parent d6f9559cfb
commit d46b040290
11 changed files with 596 additions and 41 deletions
-5
View File
@@ -128,11 +128,6 @@ auto ScopeStack::PushForFunctionBody(SemIR::InstId scope_inst_id) -> void {
destroy_id_stack_.PushArray();
}
auto ScopeStack::PushForMatchFirstBlock(SemIR::InstId scope_inst_id) -> void {
Push(scope_inst_id, SemIR::NameScopeId::None, SemIR::SpecificId::None,
/*lexical_lookup_has_load_error=*/false);
}
auto ScopeStack::Pop(bool check_unused) -> void {
auto scope = scope_stack_.pop_back_val();