diff --git a/crates/ra_parser/src/grammar/expressions.rs b/crates/ra_parser/src/grammar/expressions.rs index 742076c1a48..0495f34aeb0 100644 --- a/crates/ra_parser/src/grammar/expressions.rs +++ b/crates/ra_parser/src/grammar/expressions.rs @@ -554,7 +554,7 @@ fn arg_list(p: &mut Parser) { // let _ = format!(); // } fn path_expr(p: &mut Parser, r: Restrictions) -> (CompletedMarker, BlockLike) { - assert!(paths::is_path_start(p) || p.at(T![<])); + assert!(paths::is_path_start(p)); let m = p.start(); paths::expr_path(p); match p.current() { diff --git a/crates/ra_parser/src/grammar/expressions/atom.rs b/crates/ra_parser/src/grammar/expressions/atom.rs index d98953a7efa..401c738a3f5 100644 --- a/crates/ra_parser/src/grammar/expressions/atom.rs +++ b/crates/ra_parser/src/grammar/expressions/atom.rs @@ -62,7 +62,7 @@ pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option<(CompletedMar if let Some(m) = literal(p) { return Some((m, BlockLike::NotBlock)); } - if paths::is_path_start(p) || p.at(T![<]) { + if paths::is_path_start(p) { return Some(path_expr(p, r)); } let la = p.nth(1); diff --git a/crates/ra_parser/src/grammar/items.rs b/crates/ra_parser/src/grammar/items.rs index 543af7c4bb1..b7da44758d9 100644 --- a/crates/ra_parser/src/grammar/items.rs +++ b/crates/ra_parser/src/grammar/items.rs @@ -49,7 +49,7 @@ pub(super) fn item_or_macro(p: &mut Parser, stop_on_r_curly: bool, flavor: ItemF } Err(m) => m, }; - if paths::is_path_start(p) { + if paths::is_use_path_start(p) { match macro_call(p) { BlockLike::Block => (), BlockLike::NotBlock => { @@ -378,7 +378,7 @@ pub(crate) fn mod_item_list(p: &mut Parser) { } fn macro_call(p: &mut Parser) -> BlockLike { - assert!(paths::is_path_start(p)); + assert!(paths::is_use_path_start(p)); paths::use_path(p); macro_call_after_excl(p) } diff --git a/crates/ra_parser/src/grammar/items/use_item.rs b/crates/ra_parser/src/grammar/items/use_item.rs index c3a0b4410db..c0c7d0ec6fa 100644 --- a/crates/ra_parser/src/grammar/items/use_item.rs +++ b/crates/ra_parser/src/grammar/items/use_item.rs @@ -65,7 +65,7 @@ fn use_tree(p: &mut Parser) { // use crate::Item; // use self::some::Struct; // use crate_name::some_item; - _ if paths::is_path_start(p) => { + _ if paths::is_use_path_start(p) => { paths::use_path(p); match p.current() { T![as] => { diff --git a/crates/ra_parser/src/grammar/paths.rs b/crates/ra_parser/src/grammar/paths.rs index 3537b0da117..07eb53b0c70 100644 --- a/crates/ra_parser/src/grammar/paths.rs +++ b/crates/ra_parser/src/grammar/paths.rs @@ -4,6 +4,10 @@ pub(super) const PATH_FIRST: TokenSet = token_set![IDENT, SELF_KW, SUPER_KW, CRATE_KW, COLONCOLON, L_ANGLE]; pub(super) fn is_path_start(p: &Parser) -> bool { + is_use_path_start(p) || p.at(T![<]) +} + +pub(super) fn is_use_path_start(p: &Parser) -> bool { match p.current() { IDENT | T![self] | T![super] | T![crate] | T![::] => true, _ => false, @@ -58,7 +62,7 @@ fn path_segment(p: &mut Parser, mode: Mode, first: bool) { if first && p.eat(T![<]) { types::type_(p); if p.eat(T![as]) { - if is_path_start(p) { + if is_use_path_start(p) { types::path_type(p); } else { p.error("expected a trait"); diff --git a/crates/ra_parser/src/grammar/patterns.rs b/crates/ra_parser/src/grammar/patterns.rs index 46034942a93..df60007070c 100644 --- a/crates/ra_parser/src/grammar/patterns.rs +++ b/crates/ra_parser/src/grammar/patterns.rs @@ -65,7 +65,7 @@ fn atom_pat(p: &mut Parser, recovery_set: TokenSet) -> Option { { return Some(bind_pat(p, true)); } - if paths::is_path_start(p) { + if paths::is_use_path_start(p) { return Some(path_pat(p)); } @@ -118,7 +118,7 @@ fn literal_pat(p: &mut Parser) -> CompletedMarker { // let Bar(..) = (); // } fn path_pat(p: &mut Parser) -> CompletedMarker { - assert!(paths::is_path_start(p)); + assert!(paths::is_use_path_start(p)); let m = p.start(); paths::expr_path(p); let kind = match p.current() { diff --git a/crates/ra_parser/src/grammar/type_params.rs b/crates/ra_parser/src/grammar/type_params.rs index ef59b59d3ee..d739df72773 100644 --- a/crates/ra_parser/src/grammar/type_params.rs +++ b/crates/ra_parser/src/grammar/type_params.rs @@ -101,7 +101,7 @@ fn type_bound(p: &mut Parser) -> bool { match p.current() { LIFETIME => p.bump(), T![for] => types::for_type(p), - _ if paths::is_path_start(p) => types::path_type_(p, false), + _ if paths::is_use_path_start(p) => types::path_type_(p, false), _ => { m.abandon(p); return false; diff --git a/crates/ra_parser/src/grammar/types.rs b/crates/ra_parser/src/grammar/types.rs index c0b72256967..29d173305cf 100644 --- a/crates/ra_parser/src/grammar/types.rs +++ b/crates/ra_parser/src/grammar/types.rs @@ -29,7 +29,7 @@ fn type_with_bounds_cond(p: &mut Parser, allow_bounds: bool) { T![dyn ] => dyn_trait_type(p), // Some path types are not allowed to have bounds (no plus) T![<] => path_type_(p, allow_bounds), - _ if paths::is_path_start(p) => path_or_macro_type_(p, allow_bounds), + _ if paths::is_use_path_start(p) => path_or_macro_type_(p, allow_bounds), _ => { p.err_recover("expected type", TYPE_RECOVERY_SET); } @@ -205,6 +205,7 @@ pub(super) fn for_binder(p: &mut Parser) { // type A = for<'a> fn() -> (); // fn foo(_t: &T) where for<'a> &'a T: Iterator {} // fn bar(_t: &T) where for<'a> &'a mut T: Iterator {} +// fn baz(_t: &T) where for<'a> <&'a T as Baz>::Foo: Iterator {} pub(super) fn for_type(p: &mut Parser) { assert!(p.at(T![for])); let m = p.start(); @@ -251,7 +252,7 @@ pub(super) fn path_type(p: &mut Parser) { // type A = foo!(); // type B = crate::foo!(); fn path_or_macro_type_(p: &mut Parser, allow_bounds: bool) { - assert!(paths::is_path_start(p) || p.at(T![<])); + assert!(paths::is_path_start(p)); let m = p.start(); paths::type_path(p); @@ -270,7 +271,7 @@ fn path_or_macro_type_(p: &mut Parser, allow_bounds: bool) { } pub(super) fn path_type_(p: &mut Parser, allow_bounds: bool) { - assert!(paths::is_path_start(p) || p.at(T![<])); + assert!(paths::is_path_start(p)); let m = p.start(); paths::type_path(p); diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0081_for_type.rs b/crates/ra_syntax/test_data/parser/inline/ok/0081_for_type.rs index 7cde5c53297..d6774d438bc 100644 --- a/crates/ra_syntax/test_data/parser/inline/ok/0081_for_type.rs +++ b/crates/ra_syntax/test_data/parser/inline/ok/0081_for_type.rs @@ -1,3 +1,4 @@ type A = for<'a> fn() -> (); fn foo(_t: &T) where for<'a> &'a T: Iterator {} fn bar(_t: &T) where for<'a> &'a mut T: Iterator {} +fn baz(_t: &T) where for<'a> <&'a T as Baz>::Foo: Iterator {} diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0081_for_type.txt b/crates/ra_syntax/test_data/parser/inline/ok/0081_for_type.txt index 599cf9452b7..c12ce4ddb8b 100644 --- a/crates/ra_syntax/test_data/parser/inline/ok/0081_for_type.txt +++ b/crates/ra_syntax/test_data/parser/inline/ok/0081_for_type.txt @@ -1,4 +1,4 @@ -SOURCE_FILE@[0; 135) +SOURCE_FILE@[0; 200) TYPE_ALIAS_DEF@[0; 28) TYPE_KW@[0; 4) "type" WHITESPACE@[4; 5) " " @@ -157,3 +157,84 @@ SOURCE_FILE@[0; 135) L_CURLY@[132; 133) "{" R_CURLY@[133; 134) "}" WHITESPACE@[134; 135) "\n" + FN_DEF@[135; 199) + FN_KW@[135; 137) "fn" + WHITESPACE@[137; 138) " " + NAME@[138; 141) + IDENT@[138; 141) "baz" + TYPE_PARAM_LIST@[141; 144) + L_ANGLE@[141; 142) "<" + TYPE_PARAM@[142; 143) + NAME@[142; 143) + IDENT@[142; 143) "T" + R_ANGLE@[143; 144) ">" + PARAM_LIST@[144; 152) + L_PAREN@[144; 145) "(" + PARAM@[145; 151) + BIND_PAT@[145; 147) + NAME@[145; 147) + IDENT@[145; 147) "_t" + COLON@[147; 148) ":" + WHITESPACE@[148; 149) " " + REFERENCE_TYPE@[149; 151) + AMP@[149; 150) "&" + PATH_TYPE@[150; 151) + PATH@[150; 151) + PATH_SEGMENT@[150; 151) + NAME_REF@[150; 151) + IDENT@[150; 151) "T" + R_PAREN@[151; 152) ")" + WHITESPACE@[152; 153) " " + WHERE_CLAUSE@[153; 196) + WHERE_KW@[153; 158) "where" + WHITESPACE@[158; 159) " " + WHERE_PRED@[159; 196) + FOR_TYPE@[159; 186) + FOR_KW@[159; 162) "for" + TYPE_PARAM_LIST@[162; 166) + L_ANGLE@[162; 163) "<" + LIFETIME_PARAM@[163; 165) + LIFETIME@[163; 165) "\'a" + R_ANGLE@[165; 166) ">" + WHITESPACE@[166; 167) " " + PATH_TYPE@[167; 186) + PATH@[167; 186) + PATH@[167; 181) + PATH_SEGMENT@[167; 181) + L_ANGLE@[167; 168) "<" + REFERENCE_TYPE@[168; 173) + AMP@[168; 169) "&" + LIFETIME@[169; 171) "\'a" + WHITESPACE@[171; 172) " " + PATH_TYPE@[172; 173) + PATH@[172; 173) + PATH_SEGMENT@[172; 173) + NAME_REF@[172; 173) + IDENT@[172; 173) "T" + WHITESPACE@[173; 174) " " + AS_KW@[174; 176) "as" + WHITESPACE@[176; 177) " " + PATH_TYPE@[177; 180) + PATH@[177; 180) + PATH_SEGMENT@[177; 180) + NAME_REF@[177; 180) + IDENT@[177; 180) "Baz" + R_ANGLE@[180; 181) ">" + COLONCOLON@[181; 183) "::" + PATH_SEGMENT@[183; 186) + NAME_REF@[183; 186) + IDENT@[183; 186) "Foo" + COLON@[186; 187) ":" + WHITESPACE@[187; 188) " " + TYPE_BOUND_LIST@[188; 196) + TYPE_BOUND@[188; 196) + PATH_TYPE@[188; 196) + PATH@[188; 196) + PATH_SEGMENT@[188; 196) + NAME_REF@[188; 196) + IDENT@[188; 196) "Iterator" + WHITESPACE@[196; 197) " " + BLOCK@[197; 199) + L_CURLY@[197; 198) "{" + R_CURLY@[198; 199) "}" + WHITESPACE@[199; 200) "\n"