Skip to content

Commit

Permalink
[move][move-2024][ide] Split up match in the compiler (#18179)
Browse files Browse the repository at this point in the history
## Description 

This make the following changes:

1. It moves some custom query information that was being maintained as
part of the typing context (and before that, as part of the HLIR
context) onto `ProgramInfo` to allow matching operations to query
information about the structure of datatypes for any program
information.
2. It splits the main `PatternMatrix` definitions (data + code) into
`shared/matching.rs`, along with a `MatchContext` trait that the matrix
specialization operations are now generic over.
3. It removes the actual match compilation code from typing, partially
reverting #17559 -- counterexample generation and IDE suggestion
analysis happens in typing as a visitor over function bodies, but
matches remain intact through all of typing now.
4. It reinstates the previous code for compiling `match` as part of HLIR
lowering.

Along the way, this code also cleaned up a bit of how struct and enum
information was being indexed in HLIR lowering, opting to reuse the
now-stored TypedProgramInfo (🎉 #17787) as opposed to recomputing this
information from scratch.

## Test plan 

All tests should still work as expected with no other changes.

---

## Release notes

Check each box that your changes affect. If none of the boxes relate to
your changes, release notes aren't required.

For each box you select, include information after the relevant heading
that describes the impact of your changes that a user might notice and
any actions they must take to implement updates.

- [ ] Protocol: 
- [ ] Nodes (Validators and Full nodes): 
- [ ] Indexer: 
- [ ] JSON-RPC: 
- [ ] GraphQL: 
- [ ] CLI: 
- [ ] Rust SDK:
  • Loading branch information
cgswords authored Jun 13, 2024
1 parent 1d3a1cb commit 07328eb
Show file tree
Hide file tree
Showing 12 changed files with 3,418 additions and 408 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -323,20 +323,22 @@ fn tail(context: &mut Context, e: &T::Exp) -> Option<ControlFlow> {
_ => None,
}
}
E::Match(_subject, _arms) => {
context
.env
.add_diag(ice!((*eloc, "Found match in detect_dead_code")));
None
}
E::VariantMatch(subject, _, arms) => {
E::Match(subject, arms) => {
if let Some(test_control_flow) = value(context, subject) {
context.report_value_error(test_control_flow);
return None;
};
let arm_somes = arms
.value
.iter()
.map(|(_, arm)| tail(context, arm))
.map(|sp!(_, arm)| {
arm.guard
.as_ref()
.and_then(|guard| value(context, guard))
.iter()
.for_each(|flow| context.report_value_error(*flow));
tail(context, &arm.rhs)
})
.collect::<Vec<_>>();
if arm_somes.iter().all(|arm_opt| arm_opt.is_some()) {
for arm_opt in arm_somes {
Expand All @@ -346,6 +348,12 @@ fn tail(context: &mut Context, e: &T::Exp) -> Option<ControlFlow> {
}
None
}
E::VariantMatch(..) => {
context
.env
.add_diag(ice!((*eloc, "Found variant match in detect_dead_code")));
None
}

// Whiles and loops Loops are currently moved to statement position
E::While(_, _, _) | E::Loop { .. } => statement(context, e),
Expand Down Expand Up @@ -444,20 +452,22 @@ fn value(context: &mut Context, e: &T::Exp) -> Option<ControlFlow> {
}
None
}
E::Match(_subject, _arms) => {
context
.env
.add_diag(ice!((*eloc, "Found match in detect_dead_code")));
None
}
E::VariantMatch(subject, _, arms) => {
E::Match(subject, arms) => {
if let Some(test_control_flow) = value(context, subject) {
context.report_value_error(test_control_flow);
return None;
};
let arm_somes = arms
.value
.iter()
.map(|(_, arm)| value(context, arm))
.map(|sp!(_, arm)| {
arm.guard
.as_ref()
.and_then(|guard| value(context, guard))
.iter()
.for_each(|flow| context.report_value_error(*flow));
value(context, &arm.rhs)
})
.collect::<Vec<_>>();
if arm_somes.iter().all(|arm_opt| arm_opt.is_some()) {
for arm_opt in arm_somes {
Expand All @@ -467,6 +477,12 @@ fn value(context: &mut Context, e: &T::Exp) -> Option<ControlFlow> {
}
None
}
E::VariantMatch(_subject, _, _arms) => {
context
.env
.add_diag(ice!((*eloc, "Found variant match in detect_dead_code")));
None
}
E::While(..) | E::Loop { .. } => statement(context, e),
E::NamedBlock(name, (_, seq)) => {
// a named block in value position checks if the body exits that block; if so, at least
Expand Down Expand Up @@ -614,25 +630,25 @@ fn statement(context: &mut Context, e: &T::Exp) -> Option<ControlFlow> {
}
}
}
E::Match(_subject, _arms) => {
context
.env
.add_diag(ice!((*eloc, "Found match in detect_dead_code")));
None
}
E::VariantMatch(subject, _, arms) => {
E::Match(subject, arms) => {
if let Some(test_control_flow) = value(context, subject) {
context.report_value_error(test_control_flow);
for (_, arm) in arms.iter() {
statement(context, arm);
for sp!(_, arm) in arms.value.iter() {
arm.guard
.as_ref()
.and_then(|guard| value(context, guard))
.iter()
.for_each(|flow| context.report_value_error(*flow));
statement(context, &arm.rhs);
}
already_reported(*eloc)
} else {
// if the test was okay but all arms both diverged, we need to report that for the
// purpose of trailing semicolons.
let arm_somes = arms
.value
.iter()
.map(|(_, arm)| statement(context, arm))
.map(|sp!(_, arm)| statement(context, &arm.rhs))
.collect::<Vec<_>>();
if arm_somes.iter().all(|arm_opt| arm_opt.is_some()) {
divergent(*eloc)
Expand All @@ -641,6 +657,12 @@ fn statement(context: &mut Context, e: &T::Exp) -> Option<ControlFlow> {
}
}
}
E::VariantMatch(_subject, _, _arms) => {
context
.env
.add_diag(ice!((*eloc, "Found variant match in detect_dead_code")));
None
}
E::While(_, test, body) => {
if let Some(test_control_flow) = value(context, test) {
context.report_value_error(test_control_flow);
Expand Down
Loading

0 comments on commit 07328eb

Please sign in to comment.