Skip to content

Commit feaa8f6

Browse files
authored
[move][move-compiler] Allow braced module definitions after labeld module definitions (#24350)
## Description Enhances the Move compiler's handling around multiple modules in a single file, plus improves diagnostics around that. This better-supports `extend module` definitions within the same file as the module itself, etc. ## Test plan Added new tests for valid and invalid uses of `extend module`, including cases with multiple modules and extensions, and updated expected outputs to match the improved diagnostics. --- ## 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): - [ ] gRPC: - [ ] JSON-RPC: - [ ] GraphQL: - [ ] CLI: - [ ] Rust SDK: - [ ] Indexing Framework:
1 parent fe7d7f3 commit feaa8f6

19 files changed

+175
-47
lines changed

external-crates/move/crates/move-compiler/src/parser/syntax.rs

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4547,10 +4547,12 @@ fn parse_module(
45474547
let mut stop_parsing = false;
45484548
while context.tokens.peek() != Tok::RBrace {
45494549
// If we are in semicolon mode, EOF is a fine place to stop.
4550-
// If we see the `module` keyword, this is most-likely someone defining a second module
4551-
// (erroneously), so we also bail in that case.
4550+
// If we see the `module` keyword, we are defining a second module, so bail
45524551
if matches!(definition_mode, ModuleDefinitionMode::Semicolon)
4553-
&& (context.tokens.peek() == Tok::EOF || context.tokens.peek() == Tok::Module)
4552+
&& (context.tokens.peek() == Tok::EOF
4553+
|| context.tokens.peek() == Tok::Module
4554+
|| (context.tokens.peek() == Tok::Identifier
4555+
&& context.tokens.content() == EXTEND_MODIFIER))
45544556
{
45554557
stop_parsing = true;
45564558
break;
@@ -4671,6 +4673,11 @@ fn parse_module_member(context: &mut Context) -> Result<ModuleMember, ErrCase> {
46714673
}
46724674
}
46734675
}
4676+
// If we find `extend` or `module`, bail out.
4677+
Tok::Module => Err(ErrCase::ContinueToModule(attributes)),
4678+
Tok::Identifier if context.tokens.content() == EXTEND_MODIFIER => {
4679+
Err(ErrCase::ContinueToModule(attributes))
4680+
}
46744681
// Regular move constructs
46754682
Tok::Friend => Ok(ModuleMember::Friend(parse_friend_decl(
46764683
attributes, context,
@@ -4755,14 +4762,7 @@ fn parse_module_member(context: &mut Context) -> Result<ModuleMember, ErrCase> {
47554762
),
47564763
)
47574764
};
4758-
if tok == Tok::Module
4759-
|| (tok == Tok::Identifier && context.tokens.content() == EXTEND_MODIFIER)
4760-
{
4761-
context.add_diag(*diag);
4762-
Err(ErrCase::ContinueToModule(attributes))
4763-
} else {
4764-
Err(ErrCase::Unknown(diag))
4765-
}
4765+
Err(ErrCase::Unknown(diag))
47664766
}
47674767
}
47684768
}
@@ -4860,12 +4860,12 @@ fn parse_file_def(
48604860
if matches!(module.definition_mode, ModuleDefinitionMode::Semicolon)
48614861
&& let Some(prev) = defs.last()
48624862
{
4863-
let msg = "Cannot define a 'module' label form in a file with multiple modules";
4863+
let msg = "Cannot define an additional 'module' via label in a file with multiple modules";
48644864
let mut diag = diag!(Declarations::InvalidModule, (module.name.loc(), msg));
4865-
diag.add_secondary_label((prev.name_loc(), "Previous definition here"));
4865+
diag.add_secondary_label((prev.name_loc(), "Previous module defined here"));
48664866
diag.add_note(
4867-
"Either move each 'module' label and definitions into its own file or \
4868-
define each as 'module <name> { contents }'",
4867+
"Either move each 'module' into its own file or \
4868+
define each addiitional module as 'module <name> { contents }'",
48694869
);
48704870
context.add_diag(diag);
48714871
}

external-crates/move/crates/move-compiler/tests/move_2024/extensions/empty_extension.snap

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,4 @@ info:
55
edition: 2024.alpha
66
lint: false
77
---
8-
error[E01002]: unexpected token
9-
┌─ tests/move_2024/extensions/empty_extension.move:4:1
10-
11-
4extend module a::test_extend_module {}
12-
^^^^^^
13-
│ │
14-
Unexpected 'extend'
15-
Expected a module member: 'use', 'friend', 'const', 'fun', 'struct', or 'enum'
8+
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
module a::m;
2+
3+
public struct S { x: u64 }
4+
5+
#[mode(test)]
6+
extend module a::m {
7+
fun get_x(s: &S): u64 { s.x }
8+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
source: crates/move-compiler/tests/move_check_testsuite.rs
3+
info:
4+
flavor: core
5+
edition: 2024.alpha
6+
lint: false
7+
---
8+
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
module a::m;
2+
3+
public struct S { x: u64 }
4+
5+
#[mode(test)]
6+
extend module a::m;
7+
8+
fun get_x(s: &S): u64 { s.x }
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
---
2+
source: crates/move-compiler/tests/move_check_testsuite.rs
3+
info:
4+
flavor: core
5+
edition: 2024.alpha
6+
lint: false
7+
---
8+
error[E02004]: invalid 'module' declaration
9+
┌─ tests/move_2024/parser/extend_module_invalid_semicolon.move:6:18
10+
11+
1module a::m;
12+
- Previous module defined here
13+
·
14+
6extend module a::m;
15+
^ Cannot define an additional 'module' via label in a file with multiple modules
16+
17+
= Either move each 'module' into its own file or define each addiitional module as 'module <name> { contents }'
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module a::m { }
2+
3+
module a::n;
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
---
2+
source: crates/move-compiler/tests/move_check_testsuite.rs
3+
info:
4+
flavor: core
5+
edition: 2024.alpha
6+
lint: false
7+
---
8+
error[E02004]: invalid 'module' declaration
9+
┌─ tests/move_2024/parser/multi_module_invalid_0.move:3:11
10+
11+
1module a::m { }
12+
- Previous module defined here
13+
2
14+
3module a::n;
15+
^ Cannot define an additional 'module' via label in a file with multiple modules
16+
17+
= Either move each 'module' into its own file or define each addiitional module as 'module <name> { contents }'
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
module a::m;
2+
3+
#[mode(test)]
4+
extend module a::n { }
5+
6+
#[mode(test)]
7+
extend module a::p;
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
---
2+
source: crates/move-compiler/tests/move_check_testsuite.rs
3+
info:
4+
flavor: core
5+
edition: 2024.alpha
6+
lint: false
7+
---
8+
error[E02004]: invalid 'module' declaration
9+
┌─ tests/move_2024/parser/multi_module_invalid_1.move:7:18
10+
11+
4extend module a::n { }
12+
- Previous module defined here
13+
·
14+
7extend module a::p;
15+
^ Cannot define an additional 'module' via label in a file with multiple modules
16+
17+
= Either move each 'module' into its own file or define each addiitional module as 'module <name> { contents }'

0 commit comments

Comments
 (0)