From 7e66785859fc4a31fc3faf4848174699d3a2c020 Mon Sep 17 00:00:00 2001 From: Toby Dimmick Date: Thu, 6 Feb 2020 11:44:00 +0000 Subject: Rework value parameter parsing - `Fn__(...)` parameters with idents/patterns no longer parse - Trait function parameters with arbitrary patterns parse - Trait function parameters without idents/patterns no longer parse - `fn(...)` parameters no longer parse with patterns other than a single ident --- crates/ra_parser/src/grammar/expressions/atom.rs | 2 +- crates/ra_parser/src/grammar/items.rs | 9 +- crates/ra_parser/src/grammar/params.rs | 111 ++++++++++++++--------- crates/ra_parser/src/grammar/paths.rs | 4 +- crates/ra_parser/src/grammar/types.rs | 2 +- 5 files changed, 73 insertions(+), 55 deletions(-) (limited to 'crates/ra_parser/src') diff --git a/crates/ra_parser/src/grammar/expressions/atom.rs b/crates/ra_parser/src/grammar/expressions/atom.rs index 2cc321473..f154077a8 100644 --- a/crates/ra_parser/src/grammar/expressions/atom.rs +++ b/crates/ra_parser/src/grammar/expressions/atom.rs @@ -229,7 +229,7 @@ fn lambda_expr(p: &mut Parser) -> CompletedMarker { let m = p.start(); p.eat(T![async]); p.eat(T![move]); - params::param_list_opt_types(p); + params::param_list_closure(p); if opt_fn_ret_type(p) { if !p.at(T!['{']) { p.error("expected `{`"); diff --git a/crates/ra_parser/src/grammar/items.rs b/crates/ra_parser/src/grammar/items.rs index 6e23d9b72..b20d224e8 100644 --- a/crates/ra_parser/src/grammar/items.rs +++ b/crates/ra_parser/src/grammar/items.rs @@ -164,7 +164,7 @@ pub(super) fn maybe_item(p: &mut Parser, m: Marker, flavor: ItemFlavor) -> Resul // async unsafe fn foo() {} // unsafe const fn bar() {} T![fn] => { - fn_def(p, flavor); + fn_def(p); m.complete(p, FN_DEF); } @@ -301,7 +301,7 @@ pub(crate) fn extern_item_list(p: &mut Parser) { m.complete(p, EXTERN_ITEM_LIST); } -fn fn_def(p: &mut Parser, flavor: ItemFlavor) { +fn fn_def(p: &mut Parser) { assert!(p.at(T![fn])); p.bump(T![fn]); @@ -311,10 +311,7 @@ fn fn_def(p: &mut Parser, flavor: ItemFlavor) { type_params::opt_type_param_list(p); if p.at(T!['(']) { - match flavor { - ItemFlavor::Mod => params::param_list(p), - ItemFlavor::Trait => params::param_list_opt_patterns(p), - } + params::param_list_fn(p); } else { p.error("expected function arguments"); } diff --git a/crates/ra_parser/src/grammar/params.rs b/crates/ra_parser/src/grammar/params.rs index c10b53316..897092a67 100644 --- a/crates/ra_parser/src/grammar/params.rs +++ b/crates/ra_parser/src/grammar/params.rs @@ -7,54 +7,59 @@ use super::*; // fn b(x: i32) {} // fn c(x: i32, ) {} // fn d(x: i32, y: ()) {} -pub(super) fn param_list(p: &mut Parser) { - list_(p, Flavor::Normal) +pub(super) fn param_list_fn(p: &mut Parser) { + list_(p, Flavor::Function) } // test param_list_opt_patterns // fn foo)>(){} -pub(super) fn param_list_opt_patterns(p: &mut Parser) { - list_(p, Flavor::OptionalPattern) +pub(super) fn param_list_impl_fn(p: &mut Parser) { + list_(p, Flavor::ImplFn) } -pub(super) fn param_list_opt_types(p: &mut Parser) { - list_(p, Flavor::OptionalType) +pub(super) fn param_list_fn_ptr(p: &mut Parser) { + list_(p, Flavor::FnPointer) } -#[derive(Clone, Copy, Eq, PartialEq)] -enum Flavor { - OptionalType, - OptionalPattern, - Normal, +pub(super) fn param_list_closure(p: &mut Parser) { + list_(p, Flavor::Closure) } -impl Flavor { - fn type_required(self) -> bool { - match self { - Flavor::OptionalType => false, - _ => true, - } - } +#[derive(Debug, Clone, Copy)] +enum Flavor { + Function, // Includes trait fn params; omitted param idents are not supported + ImplFn, + FnPointer, + Closure } fn list_(p: &mut Parser, flavor: Flavor) { - let (bra, ket) = if flavor.type_required() { (T!['('], T![')']) } else { (T![|], T![|]) }; - assert!(p.at(bra)); + use Flavor::*; + + let (bra, ket) = match flavor { + Closure => (T![|], T![|]), + Function | ImplFn | FnPointer => (T!['('], T![')']) + }; + let m = p.start(); p.bump(bra); - if flavor.type_required() { + + if let Function = flavor { // test self_param_outer_attr // fn f(#[must_use] self) {} attributes::outer_attributes(p); opt_self_param(p); } + while !p.at(EOF) && !p.at(ket) { // test param_outer_arg // fn f(#[attr1] pat: Type) {} attributes::outer_attributes(p); - if flavor.type_required() && p.at(T![...]) { - break; + if let Function | FnPointer = flavor { + if p.at(T![...]) { + break; + } } if !p.at_ts(VALUE_PARAMETER_FIRST) { @@ -68,7 +73,7 @@ fn list_(p: &mut Parser, flavor: Flavor) { } // test param_list_vararg // extern "C" { fn printf(format: *const i8, ...) -> i32; } - if flavor.type_required() { + if let Function | FnPointer = flavor { p.eat(T![...]); } p.expect(ket); @@ -80,36 +85,52 @@ const VALUE_PARAMETER_FIRST: TokenSet = patterns::PATTERN_FIRST.union(types::TYP fn value_parameter(p: &mut Parser, flavor: Flavor) { let m = p.start(); match flavor { - Flavor::OptionalType | Flavor::Normal => { + // test trait_fn_placeholder_parameter + // trait Foo { + // fn bar(_: u64, mut x: i32); + // } + + // test trait_fn_patterns + // trait T { + // fn f1((a, b): (usize, usize)) {} + // fn f2(S { a, b }: S) {} + // fn f3(NewType(a): NewType) {} + // fn f4(&&a: &&usize) {} + // } + + // test fn_patterns + // impl U { + // fn f1((a, b): (usize, usize)) {} + // fn f2(S { a, b }: S) {} + // fn f3(NewType(a): NewType) {} + // fn f4(&&a: &&usize) {} + // } + Flavor::Function => { patterns::pattern(p); - if p.at(T![:]) && !p.at(T![::]) || flavor.type_required() { - types::ascription(p) - } + types::ascription(p); } // test value_parameters_no_patterns - // type F = Box; - Flavor::OptionalPattern => { - let la0 = p.current(); - let la1 = p.nth(1); - let la2 = p.nth(2); - let la3 = p.nth(3); - - // test trait_fn_placeholder_parameter - // trait Foo { - // fn bar(_: u64, mut x: i32); - // } - if (la0 == IDENT || la0 == T![_]) && la1 == T![:] && !p.nth_at(1, T![::]) - || la0 == T![mut] && la1 == IDENT && la2 == T![:] - || la0 == T![&] - && (la1 == IDENT && la2 == T![:] && !p.nth_at(2, T![::]) - || la1 == T![mut] && la2 == IDENT && la3 == T![:] && !p.nth_at(3, T![::])) - { + // type F = Box; + Flavor::ImplFn => { + types::type_(p); + } + // test fn_pointer_param_ident_path + // type Foo = fn(Bar::Baz); + // type Qux = fn(baz: Bar::Baz); + Flavor::FnPointer => { + if p.at(IDENT) && p.nth(1) == T![:] && !p.nth_at(1, T![::]) { patterns::pattern(p); types::ascription(p); } else { types::type_(p); } } + Flavor::Closure => { + patterns::pattern(p); + if p.at(T![:]) && !p.at(T![::]) { + types::ascription(p); + } + } } m.complete(p, PARAM); } diff --git a/crates/ra_parser/src/grammar/paths.rs b/crates/ra_parser/src/grammar/paths.rs index ca8e075a1..186064320 100644 --- a/crates/ra_parser/src/grammar/paths.rs +++ b/crates/ra_parser/src/grammar/paths.rs @@ -97,9 +97,9 @@ fn opt_path_type_args(p: &mut Parser, mode: Mode) { Mode::Use => return, Mode::Type => { // test path_fn_trait_args - // type F = Box ()>; + // type F = Box ()>; if p.at(T!['(']) { - params::param_list_opt_patterns(p); + params::param_list_impl_fn(p); opt_fn_ret_type(p); } else { type_args::opt_type_arg_list(p, false) diff --git a/crates/ra_parser/src/grammar/types.rs b/crates/ra_parser/src/grammar/types.rs index 9b2e440fb..2c00bce80 100644 --- a/crates/ra_parser/src/grammar/types.rs +++ b/crates/ra_parser/src/grammar/types.rs @@ -183,7 +183,7 @@ fn fn_pointer_type(p: &mut Parser) { return; } if p.at(T!['(']) { - params::param_list_opt_patterns(p); + params::param_list_fn_ptr(p); } else { p.error("expected parameters") } -- cgit v1.2.3 From e1921ea59c04a21725caea53777c739e0a954f78 Mon Sep 17 00:00:00 2001 From: Toby Dimmick Date: Thu, 6 Feb 2020 20:04:35 +0000 Subject: rustfmt --- crates/ra_parser/src/grammar/params.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'crates/ra_parser/src') diff --git a/crates/ra_parser/src/grammar/params.rs b/crates/ra_parser/src/grammar/params.rs index 897092a67..2445f71f7 100644 --- a/crates/ra_parser/src/grammar/params.rs +++ b/crates/ra_parser/src/grammar/params.rs @@ -30,7 +30,7 @@ enum Flavor { Function, // Includes trait fn params; omitted param idents are not supported ImplFn, FnPointer, - Closure + Closure, } fn list_(p: &mut Parser, flavor: Flavor) { @@ -38,7 +38,7 @@ fn list_(p: &mut Parser, flavor: Flavor) { let (bra, ket) = match flavor { Closure => (T![|], T![|]), - Function | ImplFn | FnPointer => (T!['('], T![')']) + Function | ImplFn | FnPointer => (T!['('], T![')']), }; let m = p.start(); -- cgit v1.2.3 From 0183952d2e1252a030aca3dafd8d7abe093be3a2 Mon Sep 17 00:00:00 2001 From: Toby Dimmick Date: Thu, 6 Feb 2020 20:39:27 +0000 Subject: Closure params test --- crates/ra_parser/src/grammar/params.rs | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'crates/ra_parser/src') diff --git a/crates/ra_parser/src/grammar/params.rs b/crates/ra_parser/src/grammar/params.rs index 2445f71f7..d9fbc7c94 100644 --- a/crates/ra_parser/src/grammar/params.rs +++ b/crates/ra_parser/src/grammar/params.rs @@ -125,6 +125,10 @@ fn value_parameter(p: &mut Parser, flavor: Flavor) { types::type_(p); } } + // test closure_params + // fn main() { + // let foo = |bar, baz: Baz, qux: Qux::Quux| (); + // } Flavor::Closure => { patterns::pattern(p); if p.at(T![:]) && !p.at(T![::]) { -- cgit v1.2.3 From 90ff2be4e820601a1d16ba5716916f7424dfa10d Mon Sep 17 00:00:00 2001 From: Toby Dimmick Date: Fri, 7 Feb 2020 12:36:33 +0000 Subject: PR tweaks --- crates/ra_parser/src/grammar/items.rs | 2 +- crates/ra_parser/src/grammar/params.rs | 35 ++++++++++++++++------------------ crates/ra_parser/src/grammar/paths.rs | 2 +- 3 files changed, 18 insertions(+), 21 deletions(-) (limited to 'crates/ra_parser/src') diff --git a/crates/ra_parser/src/grammar/items.rs b/crates/ra_parser/src/grammar/items.rs index b20d224e8..7263c4d69 100644 --- a/crates/ra_parser/src/grammar/items.rs +++ b/crates/ra_parser/src/grammar/items.rs @@ -311,7 +311,7 @@ fn fn_def(p: &mut Parser) { type_params::opt_type_param_list(p); if p.at(T!['(']) { - params::param_list_fn(p); + params::param_list_fn_def(p); } else { p.error("expected function arguments"); } diff --git a/crates/ra_parser/src/grammar/params.rs b/crates/ra_parser/src/grammar/params.rs index d9fbc7c94..94edc7f35 100644 --- a/crates/ra_parser/src/grammar/params.rs +++ b/crates/ra_parser/src/grammar/params.rs @@ -7,14 +7,14 @@ use super::*; // fn b(x: i32) {} // fn c(x: i32, ) {} // fn d(x: i32, y: ()) {} -pub(super) fn param_list_fn(p: &mut Parser) { - list_(p, Flavor::Function) +pub(super) fn param_list_fn_def(p: &mut Parser) { + list_(p, Flavor::FnDef) } // test param_list_opt_patterns // fn foo)>(){} -pub(super) fn param_list_impl_fn(p: &mut Parser) { - list_(p, Flavor::ImplFn) +pub(super) fn param_list_fn_trait(p: &mut Parser) { + list_(p, Flavor::FnTrait) } pub(super) fn param_list_fn_ptr(p: &mut Parser) { @@ -27,8 +27,8 @@ pub(super) fn param_list_closure(p: &mut Parser) { #[derive(Debug, Clone, Copy)] enum Flavor { - Function, // Includes trait fn params; omitted param idents are not supported - ImplFn, + FnDef, // Includes trait fn params; omitted param idents are not supported + FnTrait, // Params for `Fn(...)`/`FnMut(...)`/`FnOnce(...)` annotations FnPointer, Closure, } @@ -38,13 +38,13 @@ fn list_(p: &mut Parser, flavor: Flavor) { let (bra, ket) = match flavor { Closure => (T![|], T![|]), - Function | ImplFn | FnPointer => (T!['('], T![')']), + FnDef | FnTrait | FnPointer => (T!['('], T![')']), }; let m = p.start(); p.bump(bra); - if let Function = flavor { + if let FnDef = flavor { // test self_param_outer_attr // fn f(#[must_use] self) {} attributes::outer_attributes(p); @@ -56,10 +56,11 @@ fn list_(p: &mut Parser, flavor: Flavor) { // fn f(#[attr1] pat: Type) {} attributes::outer_attributes(p); - if let Function | FnPointer = flavor { - if p.at(T![...]) { - break; - } + // test param_list_vararg + // extern "C" { fn printf(format: *const i8, ...) -> i32; } + match flavor { + FnDef | FnPointer if p.eat(T![...]) => break, + _ => (), } if !p.at_ts(VALUE_PARAMETER_FIRST) { @@ -71,11 +72,7 @@ fn list_(p: &mut Parser, flavor: Flavor) { p.expect(T![,]); } } - // test param_list_vararg - // extern "C" { fn printf(format: *const i8, ...) -> i32; } - if let Function | FnPointer = flavor { - p.eat(T![...]); - } + p.expect(ket); m.complete(p, PARAM_LIST); } @@ -105,13 +102,13 @@ fn value_parameter(p: &mut Parser, flavor: Flavor) { // fn f3(NewType(a): NewType) {} // fn f4(&&a: &&usize) {} // } - Flavor::Function => { + Flavor::FnDef => { patterns::pattern(p); types::ascription(p); } // test value_parameters_no_patterns // type F = Box; - Flavor::ImplFn => { + Flavor::FnTrait => { types::type_(p); } // test fn_pointer_param_ident_path diff --git a/crates/ra_parser/src/grammar/paths.rs b/crates/ra_parser/src/grammar/paths.rs index 186064320..f5bf3d7ce 100644 --- a/crates/ra_parser/src/grammar/paths.rs +++ b/crates/ra_parser/src/grammar/paths.rs @@ -99,7 +99,7 @@ fn opt_path_type_args(p: &mut Parser, mode: Mode) { // test path_fn_trait_args // type F = Box ()>; if p.at(T!['(']) { - params::param_list_impl_fn(p); + params::param_list_fn_trait(p); opt_fn_ret_type(p); } else { type_args::opt_type_arg_list(p, false) -- cgit v1.2.3 From 73ec2ab184f6d8828ebcdca418a7ae83bb60b0bc Mon Sep 17 00:00:00 2001 From: Emil Lauridsen Date: Fri, 7 Feb 2020 13:51:51 +0100 Subject: Update async unsafe fn ordering. As of rust-lang/rust#61319 the correct order for functions that are both unsafe and async is: `async unsafe fn` and not `unsafe async fn`. This commit updates the parser tests to reflect this, and corrects parsing behavior to accept the correct ordering. Fixes #3025 --- crates/ra_parser/src/grammar/items.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'crates/ra_parser/src') diff --git a/crates/ra_parser/src/grammar/items.rs b/crates/ra_parser/src/grammar/items.rs index 6e23d9b72..a88206fa8 100644 --- a/crates/ra_parser/src/grammar/items.rs +++ b/crates/ra_parser/src/grammar/items.rs @@ -91,13 +91,6 @@ pub(super) fn maybe_item(p: &mut Parser, m: Marker, flavor: ItemFlavor) -> Resul // modifiers has_mods |= p.eat(T![const]); - // test_err unsafe_block_in_mod - // fn foo(){} unsafe { } fn bar(){} - if p.at(T![unsafe]) && p.nth(1) != T!['{'] { - p.eat(T![unsafe]); - has_mods = true; - } - // test_err async_without_semicolon // fn foo() { let _ = async {} } if p.at(T![async]) && p.nth(1) != T!['{'] && p.nth(1) != T![move] && p.nth(1) != T![|] { @@ -105,6 +98,13 @@ pub(super) fn maybe_item(p: &mut Parser, m: Marker, flavor: ItemFlavor) -> Resul has_mods = true; } + // test_err unsafe_block_in_mod + // fn foo(){} unsafe { } fn bar(){} + if p.at(T![unsafe]) && p.nth(1) != T!['{'] { + p.eat(T![unsafe]); + has_mods = true; + } + if p.at(T![extern]) { has_mods = true; abi(p); @@ -157,11 +157,11 @@ pub(super) fn maybe_item(p: &mut Parser, m: Marker, flavor: ItemFlavor) -> Resul // unsafe fn foo() {} // test combined_fns - // unsafe async fn foo() {} + // async unsafe fn foo() {} // const unsafe fn bar() {} // test_err wrong_order_fns - // async unsafe fn foo() {} + // unsafe async fn foo() {} // unsafe const fn bar() {} T![fn] => { fn_def(p, flavor); -- cgit v1.2.3 From 740a26b7d26a68cc46becda3cca39091e8da67fc Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Fri, 7 Feb 2020 23:35:34 +0200 Subject: Rename add import assist --- crates/ra_parser/src/syntax_kind/generated.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'crates/ra_parser/src') diff --git a/crates/ra_parser/src/syntax_kind/generated.rs b/crates/ra_parser/src/syntax_kind/generated.rs index 4b301d67a..e27b27ffa 100644 --- a/crates/ra_parser/src/syntax_kind/generated.rs +++ b/crates/ra_parser/src/syntax_kind/generated.rs @@ -1,4 +1,4 @@ -//! Generated file, do not edit by hand, see `crate/ra_tools/src/codegen` +//! Generated file, do not edit by hand, see `xtask/src/codegen` #![allow(bad_style, missing_docs, unreachable_pub)] #[doc = r" The kind of syntax node, e.g. `IDENT`, `USE_KW`, or `STRUCT_DEF`."] -- cgit v1.2.3