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:
bors[bot] 2020-12-21 08:46:42 +00:00 committed by GitHub
commit fa75e11eb6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 63 additions and 9 deletions

View file

@ -113,7 +113,7 @@ fn type_bound(p: &mut Parser) -> bool {
p.eat(T![?]);
match p.current() {
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),
_ => {
m.abandon(p);

View file

@ -44,7 +44,7 @@ fn type_with_bounds_cond(p: &mut Parser, allow_bounds: bool) {
T![&] => ref_type(p),
T![_] => infer_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![dyn] => dyn_trait_type(p),
// 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 B = for<'a> unsafe extern "C" fn(&'a ()) -> ();
// 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]));
let m = p.start();
for_binder(p);
@ -240,7 +240,13 @@ pub(super) fn for_type(p: &mut Parser) {
}
}
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
@ -290,7 +296,7 @@ fn path_or_macro_type_(p: &mut Parser, allow_bounds: bool) {
let path = m.complete(p, kind);
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> {}
let path = m.complete(p, PATH_TYPE);
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
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![+]) {
return;
}
// 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
let m = m.precede(p);

View file

@ -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"

View file

@ -0,0 +1 @@
type A = for<'a> Test<'a> + Send;