Skip to content

Commit a4f01c4

Browse files
authored
[move-compiler] Add public struct type support to the parser (#13917)
## Description Add support for `public struct` declarations in the Move 2024 edition. To my knowledge this is the first backwards incompatible change, so we need to split off a separate version of the move-stdlib that tracks the new 2024 edition as well. The bottom commit of this PR does this, and also refactors the test runner so we aren't passing so many fields all the time in the test runner. ## Test Plan Added additional tests. --- If your changes are not user-facing and not a breaking change, you can skip the following section. Otherwise, please indicate what changed, and then add to the Release Notes section as highlighted during the release process. ### Type of Change (Check all that apply) - [ ] protocol change - [X] user-visible impact - [ ] breaking change for a client SDKs - [ ] breaking change for FNs (FN binary must upgrade) - [ ] breaking change for validators or node operators (must upgrade binaries) - [ ] breaking change for on-chain data layout - [ ] necessitate either a data wipe or data migration ### Release notes Adds initial `public struct` type visibility support to Move 2024.alpha. When using the Move 2024.alpha edition you will be required to write `public` in front of the struct type which will keep the same semantics as `struct` with no visibility modifiers today (i.e., in the `legacy` edition), this is to allow for future support of private struct types.
1 parent 1f72142 commit a4f01c4

31 files changed

+220
-77
lines changed

move-compiler/src/editions/mod.rs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ pub struct Edition {
2929
pub enum FeatureGate {
3030
PublicPackage,
3131
PostFixAbilities,
32+
StructTypeVisibility,
3233
}
3334

3435
#[derive(PartialEq, Eq, Clone, Copy, Debug, PartialOrd, Ord, Default)]
@@ -48,7 +49,8 @@ pub fn check_feature(
4849
feature: &FeatureGate,
4950
loc: Loc,
5051
) -> bool {
51-
if !edition.supports(feature) {
52+
let supports_feature = edition.supports(feature);
53+
if !supports_feature {
5254
let valid_editions = valid_editions_for_feature(feature)
5355
.into_iter()
5456
.map(|e| e.to_string())
@@ -69,10 +71,8 @@ pub fn check_feature(
6971
or via command line flag if invoking the compiler directly.",
7072
);
7173
env.add_diag(diag);
72-
false
73-
} else {
74-
true
7574
}
75+
supports_feature
7676
}
7777

7878
pub fn valid_editions_for_feature(feature: &FeatureGate) -> Vec<Edition> {
@@ -90,8 +90,11 @@ pub fn valid_editions_for_feature(feature: &FeatureGate) -> Vec<Edition> {
9090
static SUPPORTED_FEATURES: Lazy<BTreeMap<Edition, BTreeSet<FeatureGate>>> =
9191
Lazy::new(|| BTreeMap::from_iter(Edition::ALL.iter().map(|e| (*e, e.features()))));
9292

93-
const E2024_ALPHA_FEATURES: &[FeatureGate] =
94-
&[FeatureGate::PublicPackage, FeatureGate::PostFixAbilities];
93+
const E2024_ALPHA_FEATURES: &[FeatureGate] = &[
94+
FeatureGate::PublicPackage,
95+
FeatureGate::PostFixAbilities,
96+
FeatureGate::StructTypeVisibility,
97+
];
9598

9699
impl Edition {
97100
pub const LEGACY: Self = Self {

move-compiler/src/parser/syntax.rs

Lines changed: 45 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2021,16 +2021,9 @@ fn parse_struct_decl(
20212021
entry,
20222022
native,
20232023
} = modifiers;
2024-
if let Some(vis) = visibility {
2025-
let msg = format!(
2026-
"Invalid struct declaration. Structs cannot have visibility modifiers as they are \
2027-
always '{}'",
2028-
Visibility::PUBLIC
2029-
);
2030-
context
2031-
.env
2032-
.add_diag(diag!(Syntax::InvalidModifier, (vis.loc().unwrap(), msg)));
2033-
}
2024+
2025+
check_struct_visibility(visibility, context);
2026+
20342027
if let Some(loc) = entry {
20352028
let msg = format!(
20362029
"Invalid constant declaration. '{}' is used only on functions",
@@ -2183,6 +2176,48 @@ fn parse_postfix_ability_declarations(
21832176
Ok(())
21842177
}
21852178

2179+
fn check_struct_visibility(visibility: Option<Visibility>, context: &mut Context) {
2180+
let current_package = context.package_name;
2181+
if let Some(Visibility::Public(loc)) = &visibility {
2182+
context
2183+
.env
2184+
.check_feature(&FeatureGate::StructTypeVisibility, current_package, *loc);
2185+
}
2186+
2187+
let supports_public = context
2188+
.env
2189+
.supports_feature(current_package, &FeatureGate::StructTypeVisibility);
2190+
2191+
if supports_public {
2192+
if !matches!(visibility, Some(Visibility::Public(_))) {
2193+
let (loc, vis_str) = match visibility {
2194+
Some(vis) => (vis.loc().unwrap(), format!("'{vis}'")),
2195+
None => {
2196+
let loc = current_token_loc(context.tokens);
2197+
(loc, "Internal".to_owned())
2198+
}
2199+
};
2200+
let msg = format!(
2201+
"Invalid struct declaration. {vis_str} struct declarations are not yet supported"
2202+
);
2203+
let note = "Visibility annotations are required on struct declarations from the Move 2024 edition onwards.";
2204+
let mut err = diag!(Syntax::InvalidModifier, (loc, msg));
2205+
err.add_note(note);
2206+
context.env.add_diag(err);
2207+
}
2208+
} else if let Some(vis) = visibility {
2209+
let msg = format!(
2210+
"Invalid struct declaration. Structs cannot have visibility modifiers as they are \
2211+
always '{}'",
2212+
Visibility::PUBLIC
2213+
);
2214+
let note = "Starting in the Move 2024 edition visibility must be annotated on struct declarations.";
2215+
let mut err = diag!(Syntax::InvalidModifier, (vis.loc().unwrap(), msg));
2216+
err.add_note(note);
2217+
context.env.add_diag(err);
2218+
}
2219+
}
2220+
21862221
//**************************************************************************************************
21872222
// Constants
21882223
//**************************************************************************************************

move-compiler/src/shared/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -534,6 +534,10 @@ impl CompilationEnv {
534534
edition_check_feature(self, self.package_config(package).edition, feature, loc)
535535
}
536536

537+
pub fn supports_feature(&self, package: Option<Symbol>, feature: &FeatureGate) -> bool {
538+
self.package_config(package).edition.supports(feature)
539+
}
540+
537541
pub fn package_config(&self, package: Option<Symbol>) -> &PackageConfig {
538542
package
539543
.and_then(|p| self.package_configs.get(&p))
Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
error[E01003]: invalid modifier
2-
┌─ tests/move_2024/parser/ability_modifier_infix_and_postfix.move:4:34
2+
┌─ tests/move_2024/parser/ability_modifier_infix_and_postfix.move:4:41
33
4-
4 │ struct Foo has copy, drop {} has store;
5-
│ --- ^^^ Duplicate ability declaration. Abilities can be declared before or after the field declarations, but not both.
6-
│ │
7-
│ Ability declaration previously given here
4+
4 │ public struct Foo has copy, drop {} has store;
5+
--- ^^^ Duplicate ability declaration. Abilities can be declared before or after the field declarations, but not both.
6+
7+
Ability declaration previously given here
88

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
address 0x42 {
22
module M {
33
// has both prefix and postfix ability declarations
4-
struct Foo has copy, drop {} has store;
4+
public struct Foo has copy, drop {} has store;
55
}
66
}
Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
error[E01002]: unexpected token
2-
┌─ tests/move_2024/parser/ability_modifier_infix_and_postfix_native_struct.move:5:39
2+
┌─ tests/move_2024/parser/ability_modifier_infix_and_postfix_native_struct.move:5:46
33
4-
5 │ native struct Foo has copy, drop; has store;
5-
│ ^^^
6-
│ │
7-
│ Unexpected 'has'
8-
│ Expected a module member: 'spec', 'use', 'friend', 'const', 'fun', or 'struct'
4+
5 │ public native struct Foo has copy, drop; has store;
5+
^^^
6+
7+
Unexpected 'has'
8+
Expected a module member: 'spec', 'use', 'friend', 'const', 'fun', or 'struct'
99

move-compiler/tests/move_2024/parser/ability_modifier_infix_and_postfix_native_struct.move

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@ address 0x42 {
22
module M {
33
// has both invalid declaration since postfix ability declarations
44
// are not allowed for native structs
5-
native struct Foo has copy, drop; has store;
5+
public native struct Foo has copy, drop; has store;
66
}
77
}
Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
error[E01002]: unexpected token
2-
┌─ tests/move_2024/parser/ability_modifier_infix_postfix_no_fields.move:4:38
2+
┌─ tests/move_2024/parser/ability_modifier_infix_postfix_no_fields.move:4:45
33
4-
4 │ native struct Foo has copy, drop has store;
5-
│ ^^^
6-
│ │
7-
│ Unexpected 'has'
8-
│ Expected one of: ',', '{', or ';'
4+
4 │ public native struct Foo has copy, drop has store;
5+
^^^
6+
7+
Unexpected 'has'
8+
Expected one of: ',', '{', or ';'
99

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
address 0x42 {
22
module M {
33
// has both prefix and invalid postfix ability declarations
4-
native struct Foo has copy, drop has store;
4+
public native struct Foo has copy, drop has store;
55
}
66
}
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
error[E01002]: unexpected token
2-
┌─ tests/move_2024/parser/ability_modifier_infix_postfix_no_fields_with_comma_sep.move:4:39
2+
┌─ tests/move_2024/parser/ability_modifier_infix_postfix_no_fields_with_comma_sep.move:4:46
33
4-
4 │ native struct Foo has copy, drop, has store;
5-
│ ^^^ Unexpected 'has'. Expected a type ability, one of: 'copy', 'drop', 'store', or 'key'
4+
4 │ public native struct Foo has copy, drop, has store;
5+
^^^ Unexpected 'has'. Expected a type ability, one of: 'copy', 'drop', 'store', or 'key'
66

0 commit comments

Comments
 (0)