Skip to content

Commit 57f41eb

Browse files
authored
[move-2024][enums] Struct matching (#17172)
## Description This introduces struct matching in match expressions. The major changes include: 1. Extending path resolution to handle some cases more-generally. 1. Revising name resolution to combine a lot of the data structure name resolution machinery - This now discriminates results more-locally. - This also pulls out the previous positional versus named constructor misuse error machinery out into a helper function we can reuse in patterns and expressions, simplifying the expression logic and ensuring consistent message formats. 1. Revisions to how types are tracked in unpack statements in enums to match how they are handled in struct unpacks (that is, field types are never reference-wrapped, even if the unpack is a borrow-flavored unpack). This ensures consistent handling during match compilation, at the cost of some extra computation around fringe types during final match arm creation. 1. Finally, extending match completion to actually handle struct unpacking. This also make a few smaller fixes/changes: 1. Fixes a bug that occurred when unpacking empty struct borrows. 1. Revises some of the verbage around borrow error reporting for matching. 1. Struct fields carry if they were positional or not down into match compilation (though maybe all of that should go live in name resolution...). 1. Marks the recursive result builder in `match_compilation` as `#[growing_stack]` ## Test plan A set of new tests (though we always need more). --- ## 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:
1 parent d126653 commit 57f41eb

File tree

74 files changed

+3166
-736
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

74 files changed

+3166
-736
lines changed

crates/move-analyzer/src/symbols.rs

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1555,7 +1555,7 @@ fn get_mod_outer_defs(
15551555
// process field structs first
15561556
let mut field_defs = vec![];
15571557
let mut field_types = vec![];
1558-
if let StructFields::Defined(fields) = &def.fields {
1558+
if let StructFields::Defined(_positional, fields) = &def.fields {
15591559
for (fpos, fname, (_, t)) in fields {
15601560
let start = match get_start_loc(&fpos, files, file_id_mapping) {
15611561
Some(s) => s,
@@ -2244,7 +2244,7 @@ impl<'a> ParsingSymbolicator<'a> {
22442244

22452245
impl<'a> TypingSymbolicator<'a> {
22462246
/// Get symbols for the whole module
2247-
fn mod_symbols(&mut self, mod_def: &ModuleDefinition, mod_ident_str: &String) {
2247+
fn mod_symbols(&mut self, mod_def: &ModuleDefinition, mod_ident_str: &str) {
22482248
for (pos, name, fun) in &mod_def.functions {
22492249
// enter self-definition for function name (unwrap safe - done when inserting def)
22502250
let name_start = get_start_loc(&pos, self.files, self.file_id_mapping).unwrap();
@@ -2355,27 +2355,17 @@ impl<'a> TypingSymbolicator<'a> {
23552355
fn struct_symbols(
23562356
&mut self,
23572357
struct_def: &StructDefinition,
2358-
struct_name: &Symbol,
2359-
mod_ident_str: &String,
2358+
_struct_name: &Symbol,
2359+
_mod_ident_str: &str,
23602360
) {
23612361
// create scope designated to contain type parameters (if any)
23622362
let mut tp_scope = BTreeMap::new();
23632363
for stp in &struct_def.type_parameters {
23642364
self.add_type_param(&stp.param, &mut tp_scope);
23652365
}
23662366

2367-
let positional = self
2368-
.mod_outer_defs
2369-
.get(mod_ident_str)
2370-
.map_or(false, |mod_defs| {
2371-
mod_defs
2372-
.structs
2373-
.get(struct_name)
2374-
.map_or(false, |sdef| sdef.positional)
2375-
});
2376-
23772367
self.type_params = tp_scope;
2378-
if let StructFields::Defined(fields) = &struct_def.fields {
2368+
if let StructFields::Defined(positional, fields) = &struct_def.fields {
23792369
for (fpos, fname, (_, t)) in fields {
23802370
self.add_type_id_use_def(t);
23812371
if !positional {
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
processed 3 tasks
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
//# init --edition development
2+
3+
//# publish
4+
module 0x42::m {
5+
6+
public fun fib(n: u64): u64 {
7+
match (n) {
8+
0 => 0,
9+
1 => 1,
10+
n => fib(n-1) + fib(n-2)
11+
}
12+
}
13+
14+
}
15+
16+
//# run
17+
module 0x42::main {
18+
19+
fun main() {
20+
use 0x42::m::fib;
21+
assert!(fib(0) == 0, 0);
22+
assert!(fib(1) == 1, 1);
23+
assert!(fib(2) == 1, 2);
24+
assert!(fib(3) == 2, 3);
25+
assert!(fib(4) == 3, 4);
26+
assert!(fib(5) == 5, 5);
27+
assert!(fib(6) == 8, 6);
28+
assert!(fib(7) == 13, 7);
29+
assert!(fib(8) == 21, 8);
30+
assert!(fib(9) == 34, 9);
31+
assert!(fib(10) == 55, 10);
32+
}
33+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
processed 3 tasks

0 commit comments

Comments
 (0)