Skip to content

Commit

Permalink
[move][move-2024] Add raw address support for patterns (MystenLabs#18482
Browse files Browse the repository at this point in the history
)

## Description 

This allows raw addresses to be used as pattern prefixes

## Test plan 

New tests

---

## 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 Jul 1, 2024
1 parent 1bc3c69 commit a7bc319
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 55 deletions.
115 changes: 60 additions & 55 deletions external-crates/move/crates/move-compiler/src/parser/syntax.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2093,66 +2093,71 @@ fn parse_match_pattern(context: &mut Context) -> Result<MatchPattern, Box<Diagno
consume_token(context.tokens, Tok::RParen)?;
pat
}
Tok::Mut | Tok::Identifier => ok_with_loc!(context, {
let mut_ = parse_mut_opt(context)?;
let name_access_chain = parse_name_access_chain(
context,
/* macros */ false,
/* tyargs */ true,
|| "a pattern entry",
)?;

fn report_invalid_mut(context: &mut Context, mut_: Option<Loc>) {
if let Some(loc) = mut_ {
let diag = diag!(
Syntax::UnexpectedToken,
(loc, "Invalid 'mut' keyword on non-variable pattern")
);
context.env.add_diag(diag);
t @ (Tok::Mut | Tok::Identifier | Tok::NumValue)
if !matches!(t, Tok::NumValue)
|| matches!(context.tokens.lookahead(), Ok(Tok::ColonColon)) =>
{
ok_with_loc!(context, {
let mut_ = parse_mut_opt(context)?;
let name_access_chain = parse_name_access_chain(
context,
/* macros */ false,
/* tyargs */ true,
|| "a pattern entry",
)?;

fn report_invalid_mut(context: &mut Context, mut_: Option<Loc>) {
if let Some(loc) = mut_ {
let diag = diag!(
Syntax::UnexpectedToken,
(loc, "Invalid 'mut' keyword on non-variable pattern")
);
context.env.add_diag(diag);
}
}
}

match context.tokens.peek() {
Tok::LParen => {
let mut pattern_start_set = VALUE_START_SET.clone();
pattern_start_set.add_all(&[
Tok::PeriodPeriod,
Tok::LParen,
Tok::Mut,
Tok::Identifier,
]);
let (loc, patterns) = with_loc!(
context,
parse_comma_list(
context,
match context.tokens.peek() {
Tok::LParen => {
let mut pattern_start_set = VALUE_START_SET.clone();
pattern_start_set.add_all(&[
Tok::PeriodPeriod,
Tok::LParen,
Tok::RParen,
&pattern_start_set,
parse_positional_field_pattern,
"a pattern",
)
);
report_invalid_mut(context, mut_);
MP::PositionalConstructor(name_access_chain, sp(loc, patterns))
}
Tok::LBrace => {
let (loc, patterns) = with_loc!(
context,
parse_comma_list(
Tok::Mut,
Tok::Identifier,
]);
let (loc, patterns) = with_loc!(
context,
Tok::LBrace,
Tok::RBrace,
&TokenSet::from([Tok::PeriodPeriod, Tok::Mut, Tok::Identifier]),
parse_field_pattern,
"a field pattern",
)
);
report_invalid_mut(context, mut_);
MP::FieldConstructor(name_access_chain, sp(loc, patterns))
parse_comma_list(
context,
Tok::LParen,
Tok::RParen,
&pattern_start_set,
parse_positional_field_pattern,
"a pattern",
)
);
report_invalid_mut(context, mut_);
MP::PositionalConstructor(name_access_chain, sp(loc, patterns))
}
Tok::LBrace => {
let (loc, patterns) = with_loc!(
context,
parse_comma_list(
context,
Tok::LBrace,
Tok::RBrace,
&TokenSet::from([Tok::PeriodPeriod, Tok::Mut, Tok::Identifier]),
parse_field_pattern,
"a field pattern",
)
);
report_invalid_mut(context, mut_);
MP::FieldConstructor(name_access_chain, sp(loc, patterns))
}
_ => MP::Name(mut_, name_access_chain),
}
_ => MP::Name(mut_, name_access_chain),
}
}),
})
}
_ => {
if let Some(value) = maybe_parse_value(context)? {
Ok(sp(value.loc, MP::Literal(value)))
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module 0x42::m;

public enum E {
V0(u64, u64)
}

public fun match_e(e: &E): (&u64, &u64) {
match (e) {
0x42::m::E::V0(x, y) => (x, y),
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
error[E04007]: incompatible types
┌─ tests/move_2024/matching/raw_address_invalid.move:10:9
7 │ public fun match_e(e: &E, rx: &u64, ry: &u64): (&u64, &u64) {
│ - Expected: '0x42::m::E'
·
10 │ 0x42 => (rx, ry),
│ ^^^^
│ │
│ Invalid pattern
│ Given: integer

error[E03006]: unexpected name in this position
┌─ tests/move_2024/matching/raw_address_invalid.move:11:9
11 │ 0x42::m => (rx, ry),
│ ^^^^^^^ Unexpected module identifier. A module identifier is not a valid pattern constructor

Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
module 0x42::m;

public enum E {
V0(u64, u64)
}

public fun match_e(e: &E, rx: &u64, ry: &u64): (&u64, &u64) {
match (e) {
0x42::m::E::V0(x, y) => (x, y),
0x42 => (rx, ry),
0x42::m => (rx, ry),
}
}

0 comments on commit a7bc319

Please sign in to comment.