Skip to content

Commit

Permalink
[move 2024][alpha] Method syntax (MystenLabs#13933)
Browse files Browse the repository at this point in the history
## Description 

See 'Release Notes' for feature description.

This PR:
- Resurrects original method style syntax
- Adds a `defines_primitive` annotation so that method style syntax can
be used with primitive/builtin types
- Adds use fun declarations 

Some notes about implementation details
- A normal use alias, `use a::m::f as g` introduces an implicit `use fun
a::m::f as a::m::S.g` in situations where the first argument of
`a::m::f` is `a::m::S`. This ensures that there isn't any weird
precedence/shadowing between `use` and `use fun` in a given scope.
- There are some nuances here, but the rules are ensuring that once you
have a module that calls `x.foo()`, it always resolves to the same
function `a::m::bar`, even if new `public use fun`s are added elsewhere.
- I had to move `ProgramInfo` into the `naming::ast::program` and
`typing::ast::program` to properly resolve `use funs` (particularly with
this implicit setup described above)

Follow up 
- `let mut` and `mut` variable modifiers
- I think I will rewrite alias maps in expansion to reduce clones (as I
did with use fun declarations

## Test Plan 

- New 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

Method style syntax has been added to Move 2024.alpha. This means
functions can now be invoked with the syntax, `e.foo(arg1, arg2)`.
Assuming `e: a::m::S` (or `&a::m::S` or `&mut a::m::S`), `e.foo(arg1,
arg2)` will resolve to `a::m::foo(e, arg1, arg2)`. Additionally, the
compiler will borrow `e` when necessary.
For instances where the desired target function is not declared in the
same module as the type (or is not declared with the desired name), a
`use fun` alias can be used instead. For example, `use b::n::bar as
S.baz` will allow `e.baz()` to resolve as `b::n::bar(e)`. A `public use
fun` can be declared in the types defining module, allowing the alias to
be used outside of the module.
  • Loading branch information
tnowacki authored Sep 29, 2023
1 parent 3764c46 commit abd1234
Show file tree
Hide file tree
Showing 132 changed files with 4,307 additions and 447 deletions.
6 changes: 3 additions & 3 deletions crates/sui-move-build/src/linters/coin_field.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ use move_compiler::{
diagnostics::codes::{custom, DiagnosticInfo, Severity},
expansion::ast as E,
naming::ast as N,
shared::{CompilationEnv, Identifier},
typing::{ast as T, core::TypingProgramInfo, visitor::TypingVisitor},
shared::{program_info::TypingProgramInfo, CompilationEnv, Identifier},
typing::{ast as T, visitor::TypingVisitor},
};
use move_core_types::account_address::AccountAddress;
use move_ir_types::location::Loc;
Expand All @@ -37,7 +37,7 @@ impl TypingVisitor for CoinFieldVisitor {
&mut self,
env: &mut CompilationEnv,
_program_info: &TypingProgramInfo,
program: &mut T::Program,
program: &mut T::Program_,
) {
for (_, _, mdef) in program.modules.iter() {
env.add_warning_filter_scope(mdef.warning_filter.clone());
Expand Down
5 changes: 2 additions & 3 deletions crates/sui-move-build/src/linters/collection_equality.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,9 @@ use move_compiler::{
diagnostics::codes::{custom, DiagnosticInfo, Severity},
naming::ast as N,
parser::ast as P,
shared::{CompilationEnv, Identifier},
shared::{program_info::TypingProgramInfo, CompilationEnv, Identifier},
typing::{
ast as T,
core::TypingProgramInfo,
visitor::{TypingVisitorConstructor, TypingVisitorContext},
},
};
Expand Down Expand Up @@ -64,7 +63,7 @@ impl TypingVisitorConstructor for CollectionEqualityVisitor {
fn context<'a>(
env: &'a mut CompilationEnv,
_program_info: &'a TypingProgramInfo,
_program: &T::Program,
_program: &T::Program_,
) -> Self::Context<'a> {
Context { env }
}
Expand Down
5 changes: 2 additions & 3 deletions crates/sui-move-build/src/linters/freeze_wrapped.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,9 @@ use move_compiler::{
expansion::ast as E,
naming::ast as N,
parser::ast::{self as P, Ability_},
shared::{CompilationEnv, Identifier},
shared::{program_info::TypingProgramInfo, CompilationEnv, Identifier},
typing::{
ast as T,
core::TypingProgramInfo,
visitor::{TypingVisitorConstructor, TypingVisitorContext},
},
};
Expand Down Expand Up @@ -83,7 +82,7 @@ impl TypingVisitorConstructor for FreezeWrappedVisitor {
fn context<'a>(
env: &'a mut CompilationEnv,
program_info: &'a TypingProgramInfo,
_program: &T::Program,
_program: &T::Program_,
) -> Self::Context<'a> {
Context {
env,
Expand Down
2 changes: 1 addition & 1 deletion external-crates/move/move-analyzer/src/symbols.rs
Original file line number Diff line number Diff line change
Expand Up @@ -702,7 +702,7 @@ impl Symbolicator {
}
}

let modules = &typed_ast.unwrap().modules;
let modules = &typed_ast.unwrap().inner.modules;

let mut mod_outer_defs = BTreeMap::new();
let mut mod_use_defs = BTreeMap::new();
Expand Down
4 changes: 2 additions & 2 deletions external-crates/move/move-compiler/src/cfgir/cfg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ impl<T: Deref<Target = BasicBlocks>> CFG for ForwardCFG<T> {
}

fn debug(&self) {
crate::shared::ast_debug::print(self);
self.print();
}
}

Expand Down Expand Up @@ -733,7 +733,7 @@ impl<'forward, Blocks: Deref<Target = BasicBlocks>> CFG for ReverseCFG<'forward,
}

fn debug(&self) {
crate::shared::ast_debug::print(self);
self.print();
}
}

Expand Down
2 changes: 2 additions & 0 deletions external-crates/move/move-compiler/src/diagnostics/codes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@ codes!(
InvalidAttribute: { msg: "invalid attribute", severity: NonblockingError },
InvalidVisibilityModifier:
{ msg: "invalid visibility modifier", severity: NonblockingError },
InvalidUseFun: { msg: "invalid 'use fun' declaration", severity: NonblockingError },
],
// errors name resolution, mostly expansion/translate and naming/translate
NameResolution: [
Expand Down Expand Up @@ -250,6 +251,7 @@ codes!(
(NOTE: this may become an error in the future)",
severity: Warning
},
InvalidMethodCall: { msg: "invalid method call", severity: BlockingError },
],
// errors for ability rules. mostly typing/translate
AbilitySafety: [
Expand Down
32 changes: 20 additions & 12 deletions external-crates/move/move-compiler/src/editions/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ pub enum FeatureGate {
PublicPackage,
PostFixAbilities,
StructTypeVisibility,
DotCall,
}

#[derive(PartialEq, Eq, Clone, Copy, Debug, PartialOrd, Ord, Default)]
Expand All @@ -46,7 +47,7 @@ pub enum Flavor {
pub fn check_feature(
env: &mut CompilationEnv,
edition: Edition,
feature: &FeatureGate,
feature: FeatureGate,
loc: Loc,
) -> bool {
let supports_feature = edition.supports(feature);
Expand All @@ -61,8 +62,9 @@ pub fn check_feature(
(
loc,
format!(
"{feature} not supported by current edition '{edition}', \
only '{valid_editions}' support this feature"
"{} not supported by current edition '{edition}', \
only '{valid_editions}' support this feature",
feature.error_prefix(),
)
)
);
Expand All @@ -75,7 +77,7 @@ pub fn check_feature(
supports_feature
}

pub fn valid_editions_for_feature(feature: &FeatureGate) -> Vec<Edition> {
pub fn valid_editions_for_feature(feature: FeatureGate) -> Vec<Edition> {
Edition::ALL
.iter()
.filter(|e| e.supports(feature))
Expand All @@ -94,6 +96,7 @@ const E2024_ALPHA_FEATURES: &[FeatureGate] = &[
FeatureGate::PublicPackage,
FeatureGate::PostFixAbilities,
FeatureGate::StructTypeVisibility,
FeatureGate::DotCall,
];

impl Edition {
Expand All @@ -110,8 +113,8 @@ impl Edition {

pub const ALL: &[Self] = &[Self::LEGACY, Self::E2024_ALPHA];

pub fn supports(&self, feature: &FeatureGate) -> bool {
SUPPORTED_FEATURES.get(self).unwrap().contains(feature)
pub fn supports(&self, feature: FeatureGate) -> bool {
SUPPORTED_FEATURES.get(self).unwrap().contains(&feature)
}

// Intended only for implementing the lazy static (supported feature map) above
Expand Down Expand Up @@ -159,6 +162,17 @@ impl Flavor {
pub const ALL: &[Self] = &[Self::GlobalStorage, Self::Sui];
}

impl FeatureGate {
fn error_prefix(&self) -> &'static str {
match self {
FeatureGate::PublicPackage => "'public(package)' is",
FeatureGate::PostFixAbilities => "Postfix abilities are",
FeatureGate::StructTypeVisibility => "Struct visibility modifiers are",
FeatureGate::DotCall => "Method syntax is",
}
}
}

//**************************************************************************************************
// Parsing/Deserialize
//**************************************************************************************************
Expand Down Expand Up @@ -263,12 +277,6 @@ impl Serialize for Flavor {
}
}

impl Display for FeatureGate {
fn fmt(&self, _: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
Ok(())
}
}

//**************************************************************************************************
// traits
//**************************************************************************************************
Expand Down
27 changes: 25 additions & 2 deletions external-crates/move/move-compiler/src/expansion/aliases.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
// SPDX-License-Identifier: Apache-2.0

use crate::{
expansion::ast::{ModuleIdent, ModuleIdent_},
parser::ast::ModuleName,
expansion::ast::{self as E, ModuleIdent, ModuleIdent_},
parser::ast::{self as P, ModuleName},
shared::{unique_map::UniqueMap, unique_set::UniqueSet, *},
};
use move_ir_types::location::*;
Expand Down Expand Up @@ -33,6 +33,20 @@ pub struct AliasMap {

pub struct OldAliasMap(Option<AliasMap>);

pub struct ParserExplicitUseFun {
pub loc: Loc,
pub attributes: E::Attributes,
pub is_public: Option<Loc>,
pub function: Box<P::NameAccessChain>,
pub ty: Box<P::NameAccessChain>,
pub method: Name,
}

pub struct UseFunsBuilder {
pub explicit: Vec<ParserExplicitUseFun>,
pub implicit: UniqueMap<Name, E::ImplicitUseFunCandidate>,
}

impl AliasSet {
pub fn new() -> Self {
Self {
Expand Down Expand Up @@ -276,3 +290,12 @@ impl OldAliasMap {
}
}
}

impl UseFunsBuilder {
pub fn new() -> Self {
Self {
explicit: vec![],
implicit: UniqueMap::new(),
}
}
}
Loading

0 comments on commit abd1234

Please sign in to comment.