mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-27 05:23:24 +00:00
Merge #6967
6967: Correctly parse legacy trait objects with leading ForType r=matklad a=Veykril Fixes #1422 Co-authored-by: Lukas Wirth <lukastw97@gmail.com>
This commit is contained in:
commit
fa75e11eb6
4 changed files with 63 additions and 9 deletions
|
@ -113,7 +113,7 @@ fn type_bound(p: &mut Parser) -> bool {
|
||||||
p.eat(T![?]);
|
p.eat(T![?]);
|
||||||
match p.current() {
|
match p.current() {
|
||||||
LIFETIME_IDENT => lifetime(p),
|
LIFETIME_IDENT => lifetime(p),
|
||||||
T![for] => types::for_type(p),
|
T![for] => types::for_type(p, false),
|
||||||
_ if paths::is_use_path_start(p) => types::path_type_(p, false),
|
_ if paths::is_use_path_start(p) => types::path_type_(p, false),
|
||||||
_ => {
|
_ => {
|
||||||
m.abandon(p);
|
m.abandon(p);
|
||||||
|
|
|
@ -44,7 +44,7 @@ fn type_with_bounds_cond(p: &mut Parser, allow_bounds: bool) {
|
||||||
T![&] => ref_type(p),
|
T![&] => ref_type(p),
|
||||||
T![_] => infer_type(p),
|
T![_] => infer_type(p),
|
||||||
T![fn] | T![unsafe] | T![extern] => fn_ptr_type(p),
|
T![fn] | T![unsafe] | T![extern] => fn_ptr_type(p),
|
||||||
T![for] => for_type(p),
|
T![for] => for_type(p, allow_bounds),
|
||||||
T![impl] => impl_trait_type(p),
|
T![impl] => impl_trait_type(p),
|
||||||
T![dyn] => dyn_trait_type(p),
|
T![dyn] => dyn_trait_type(p),
|
||||||
// Some path types are not allowed to have bounds (no plus)
|
// Some path types are not allowed to have bounds (no plus)
|
||||||
|
@ -227,7 +227,7 @@ pub(super) fn for_binder(p: &mut Parser) {
|
||||||
// type A = for<'a> fn() -> ();
|
// type A = for<'a> fn() -> ();
|
||||||
// type B = for<'a> unsafe extern "C" fn(&'a ()) -> ();
|
// type B = for<'a> unsafe extern "C" fn(&'a ()) -> ();
|
||||||
// type Obj = for<'a> PartialEq<&'a i32>;
|
// type Obj = for<'a> PartialEq<&'a i32>;
|
||||||
pub(super) fn for_type(p: &mut Parser) {
|
pub(super) fn for_type(p: &mut Parser, allow_bounds: bool) {
|
||||||
assert!(p.at(T![for]));
|
assert!(p.at(T![for]));
|
||||||
let m = p.start();
|
let m = p.start();
|
||||||
for_binder(p);
|
for_binder(p);
|
||||||
|
@ -240,7 +240,13 @@ pub(super) fn for_type(p: &mut Parser) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
type_no_bounds(p);
|
type_no_bounds(p);
|
||||||
m.complete(p, FOR_TYPE);
|
let completed = m.complete(p, FOR_TYPE);
|
||||||
|
|
||||||
|
// test no_dyn_trait_leading_for
|
||||||
|
// type A = for<'a> Test<'a> + Send;
|
||||||
|
if allow_bounds {
|
||||||
|
opt_type_bounds_as_dyn_trait_type(p, completed);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// test impl_trait_type
|
// test impl_trait_type
|
||||||
|
@ -290,7 +296,7 @@ fn path_or_macro_type_(p: &mut Parser, allow_bounds: bool) {
|
||||||
let path = m.complete(p, kind);
|
let path = m.complete(p, kind);
|
||||||
|
|
||||||
if allow_bounds {
|
if allow_bounds {
|
||||||
opt_path_type_bounds_as_dyn_trait_type(p, path);
|
opt_type_bounds_as_dyn_trait_type(p, path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -304,19 +310,23 @@ pub(super) fn path_type_(p: &mut Parser, allow_bounds: bool) {
|
||||||
// fn foo() -> Box<dyn T + 'f> {}
|
// fn foo() -> Box<dyn T + 'f> {}
|
||||||
let path = m.complete(p, PATH_TYPE);
|
let path = m.complete(p, PATH_TYPE);
|
||||||
if allow_bounds {
|
if allow_bounds {
|
||||||
opt_path_type_bounds_as_dyn_trait_type(p, path);
|
opt_type_bounds_as_dyn_trait_type(p, path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This turns a parsed PATH_TYPE optionally into a DYN_TRAIT_TYPE
|
/// This turns a parsed PATH_TYPE or FOR_TYPE optionally into a DYN_TRAIT_TYPE
|
||||||
/// with a TYPE_BOUND_LIST
|
/// with a TYPE_BOUND_LIST
|
||||||
fn opt_path_type_bounds_as_dyn_trait_type(p: &mut Parser, path_type_marker: CompletedMarker) {
|
fn opt_type_bounds_as_dyn_trait_type(p: &mut Parser, type_marker: CompletedMarker) {
|
||||||
|
assert!(matches!(
|
||||||
|
type_marker.kind(),
|
||||||
|
SyntaxKind::PATH_TYPE | SyntaxKind::FOR_TYPE | SyntaxKind::MACRO_CALL
|
||||||
|
));
|
||||||
if !p.at(T![+]) {
|
if !p.at(T![+]) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// First create a TYPE_BOUND from the completed PATH_TYPE
|
// First create a TYPE_BOUND from the completed PATH_TYPE
|
||||||
let m = path_type_marker.precede(p).complete(p, TYPE_BOUND);
|
let m = type_marker.precede(p).complete(p, TYPE_BOUND);
|
||||||
|
|
||||||
// Next setup a marker for the TYPE_BOUND_LIST
|
// Next setup a marker for the TYPE_BOUND_LIST
|
||||||
let m = m.precede(p);
|
let m = m.precede(p);
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
SOURCE_FILE@0..34
|
||||||
|
TYPE_ALIAS@0..33
|
||||||
|
TYPE_KW@0..4 "type"
|
||||||
|
WHITESPACE@4..5 " "
|
||||||
|
NAME@5..6
|
||||||
|
IDENT@5..6 "A"
|
||||||
|
WHITESPACE@6..7 " "
|
||||||
|
EQ@7..8 "="
|
||||||
|
WHITESPACE@8..9 " "
|
||||||
|
DYN_TRAIT_TYPE@9..32
|
||||||
|
TYPE_BOUND_LIST@9..32
|
||||||
|
TYPE_BOUND@9..25
|
||||||
|
FOR_TYPE@9..25
|
||||||
|
FOR_KW@9..12 "for"
|
||||||
|
GENERIC_PARAM_LIST@12..16
|
||||||
|
L_ANGLE@12..13 "<"
|
||||||
|
LIFETIME_PARAM@13..15
|
||||||
|
LIFETIME@13..15
|
||||||
|
LIFETIME_IDENT@13..15 "\'a"
|
||||||
|
R_ANGLE@15..16 ">"
|
||||||
|
WHITESPACE@16..17 " "
|
||||||
|
PATH_TYPE@17..25
|
||||||
|
PATH@17..25
|
||||||
|
PATH_SEGMENT@17..25
|
||||||
|
NAME_REF@17..21
|
||||||
|
IDENT@17..21 "Test"
|
||||||
|
GENERIC_ARG_LIST@21..25
|
||||||
|
L_ANGLE@21..22 "<"
|
||||||
|
LIFETIME_ARG@22..24
|
||||||
|
LIFETIME@22..24
|
||||||
|
LIFETIME_IDENT@22..24 "\'a"
|
||||||
|
R_ANGLE@24..25 ">"
|
||||||
|
WHITESPACE@25..26 " "
|
||||||
|
PLUS@26..27 "+"
|
||||||
|
WHITESPACE@27..28 " "
|
||||||
|
TYPE_BOUND@28..32
|
||||||
|
PATH_TYPE@28..32
|
||||||
|
PATH@28..32
|
||||||
|
PATH_SEGMENT@28..32
|
||||||
|
NAME_REF@28..32
|
||||||
|
IDENT@28..32 "Send"
|
||||||
|
SEMICOLON@32..33 ";"
|
||||||
|
WHITESPACE@33..34 "\n"
|
|
@ -0,0 +1 @@
|
||||||
|
type A = for<'a> Test<'a> + Send;
|
Loading…
Reference in a new issue