Fix parsing of parenthesized type args and RTN

This commit is contained in:
Lukas Wirth 2024-12-03 18:29:00 +01:00
parent edb432639b
commit 65c0b29720
44 changed files with 1022 additions and 700 deletions

View file

@ -525,7 +525,7 @@ fn method_call_expr<const FLOAT_RECOVERY: bool>(
p.bump(T![.]);
}
name_ref(p);
generic_args::opt_generic_arg_list(p, true);
generic_args::opt_generic_arg_list_expr(p);
if p.at(T!['(']) {
arg_list(p);
} else {

View file

@ -1,14 +1,13 @@
use super::*;
// test_err generic_arg_list_recover
// type T = T<0, ,T>;
pub(super) fn opt_generic_arg_list(p: &mut Parser<'_>, colon_colon_required: bool) {
// test_err generic_arg_list_recover_expr
// const _: () = T::<0, ,T>;
// const _: () = T::<0, ,T>();
pub(super) fn opt_generic_arg_list_expr(p: &mut Parser<'_>) {
let m;
if p.at(T![::]) && p.nth(2) == T![<] {
m = p.start();
p.bump(T![::]);
} else if !colon_colon_required && p.at(T![<]) && p.nth(1) != T![=] {
m = p.start();
} else {
return;
}
@ -25,7 +24,7 @@ pub(super) fn opt_generic_arg_list(p: &mut Parser<'_>, colon_colon_required: boo
m.complete(p, GENERIC_ARG_LIST);
}
const GENERIC_ARG_FIRST: TokenSet = TokenSet::new(&[
pub(crate) const GENERIC_ARG_FIRST: TokenSet = TokenSet::new(&[
LIFETIME_IDENT,
IDENT,
T!['{'],
@ -47,20 +46,23 @@ const GENERIC_ARG_RECOVERY_SET: TokenSet = TokenSet::new(&[T![>], T![,]]);
// test generic_arg
// type T = S<i32>;
fn generic_arg(p: &mut Parser<'_>) -> bool {
pub(crate) fn generic_arg(p: &mut Parser<'_>) -> bool {
match p.current() {
LIFETIME_IDENT if !p.nth_at(1, T![+]) => lifetime_arg(p),
T!['{'] | T![true] | T![false] | T![-] => const_arg(p),
k if k.is_literal() => const_arg(p),
// test associated_type_bounds
// fn print_all<T: Iterator<Item, Item::Item, Item::<true>, Item: Display, Item<'a> = Item>>(printables: T) {}
// test generic_arg_bounds
// type Plain = Foo<Item, Item::Item, Item: Bound, Item = Item>;
// type GenericArgs = Foo<Item<T>, Item::<T>, Item<T>: Bound, Item::<T>: Bound, Item<T> = Item, Item::<T> = Item>;
// type ParenthesizedArgs = Foo<Item(T), Item::(T), Item(T): Bound, Item::(T): Bound, Item(T) = Item, Item::(T) = Item>;
// type RTN = Foo<Item(..), Item(..), Item(..): Bound, Item(..): Bound, Item(..) = Item, Item(..) = Item>;
// test macro_inside_generic_arg
// type A = Foo<syn::Token![_]>;
IDENT if [T![<], T![=], T![:]].contains(&p.nth(1)) && !p.nth_at(1, T![::]) => {
IDENT => {
let m = p.start();
name_ref(p);
opt_generic_arg_list(p, false);
paths::opt_path_type_args(p);
match p.current() {
T![=] => {
p.bump_any();
@ -88,45 +90,26 @@ fn generic_arg(p: &mut Parser<'_>) -> bool {
}
// test assoc_type_bound
// type T = StreamingIterator<Item<'a>: Clone>;
// type T = StreamingIterator<Item(T): Clone>;
T![:] if !p.at(T![::]) => {
generic_params::bounds(p);
m.complete(p, ASSOC_TYPE_ARG);
}
// Turned out to be just a normal path type (mirror `path_or_macro_type`)
_ => {
let m = m.complete(p, PATH_SEGMENT).precede(p).complete(p, PATH);
let m = paths::type_path_for_qualifier(p, m);
m.precede(p).complete(p, PATH_TYPE).precede(p).complete(p, TYPE_ARG);
let m = if p.at(T![!]) && !p.at(T![!=]) {
let m = m.precede(p);
items::macro_call_after_excl(p);
m.complete(p, MACRO_CALL).precede(p).complete(p, MACRO_TYPE)
} else {
m.precede(p).complete(p, PATH_TYPE)
};
types::opt_type_bounds_as_dyn_trait_type(p, m).precede(p).complete(p, TYPE_ARG);
}
}
}
IDENT if p.nth_at(1, T!['(']) => {
let m = p.start();
name_ref(p);
if p.nth_at(1, T![..]) {
let rtn = p.start();
p.bump(T!['(']);
p.bump(T![..]);
p.expect(T![')']);
rtn.complete(p, RETURN_TYPE_SYNTAX);
// test return_type_syntax_assoc_type_bound
// fn foo<T: Trait<method(..): Send>>() {}
generic_params::bounds(p);
m.complete(p, ASSOC_TYPE_ARG);
} else {
params::param_list_fn_trait(p);
// test bare_dyn_types_with_paren_as_generic_args
// type A = S<Fn(i32)>;
// type A = S<Fn(i32) + Send>;
// type B = S<Fn(i32) -> i32>;
// type C = S<Fn(i32) -> i32 + Send>;
opt_ret_type(p);
let m = m.complete(p, PATH_SEGMENT).precede(p).complete(p, PATH);
let m = paths::type_path_for_qualifier(p, m);
let m = m.precede(p).complete(p, PATH_TYPE);
let m = types::opt_type_bounds_as_dyn_trait_type(p, m);
m.precede(p).complete(p, TYPE_ARG);
}
}
_ if p.at_ts(types::TYPE_FIRST) => type_arg(p),
_ => return false,
}
@ -190,7 +173,7 @@ pub(super) fn const_arg(p: &mut Parser<'_>) {
m.complete(p, CONST_ARG);
}
fn type_arg(p: &mut Parser<'_>) {
pub(crate) fn type_arg(p: &mut Parser<'_>) {
let m = p.start();
types::type_(p);
m.complete(p, TYPE_ARG);

View file

@ -14,12 +14,6 @@ pub(super) fn param_list_fn_def(p: &mut Parser<'_>) {
list_(p, Flavor::FnDef);
}
// test param_list_opt_patterns
// fn foo<F: FnMut(&mut Foo<'a>)>(){}
pub(super) fn param_list_fn_trait(p: &mut Parser<'_>) {
list_(p, Flavor::FnTrait);
}
pub(super) fn param_list_fn_ptr(p: &mut Parser<'_>) {
list_(p, Flavor::FnPointer);
}
@ -28,10 +22,9 @@ pub(super) fn param_list_closure(p: &mut Parser<'_>) {
list_(p, Flavor::Closure);
}
#[derive(Debug, Clone, Copy)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum Flavor {
FnDef, // Includes trait fn params; omitted param idents are not supported
FnTrait, // Params for `Fn(...)`/`FnMut(...)`/`FnOnce(...)` annotations
FnDef, // Includes trait fn params; omitted param idents are not supported
FnPointer,
Closure,
}
@ -41,7 +34,7 @@ fn list_(p: &mut Parser<'_>, flavor: Flavor) {
let (bra, ket) = match flavor {
Closure => (T![|], T![|]),
FnDef | FnTrait | FnPointer => (T!['('], T![')']),
FnDef | FnPointer => (T!['('], T![')']),
};
let list_marker = p.start();
@ -119,11 +112,6 @@ fn param(p: &mut Parser<'_>, m: Marker, flavor: Flavor) {
}
}
}
// test value_parameters_no_patterns
// type F = Box<Fn(i32, &i32, &i32, ())>;
Flavor::FnTrait => {
types::type_(p);
}
// test fn_pointer_param_ident_path
// type Foo = fn(Bar::Baz);
// type Qux = fn(baz: Bar::Baz);

View file

@ -110,7 +110,7 @@ fn path_segment(p: &mut Parser<'_>, mode: Mode, first: bool) -> Option<Completed
match p.current() {
IDENT => {
name_ref(p);
opt_path_type_args(p, mode);
opt_path_args(p, mode);
}
// test crate_path
// use crate::foo;
@ -142,38 +142,74 @@ fn path_segment(p: &mut Parser<'_>, mode: Mode, first: bool) -> Option<Completed
Some(m.complete(p, PATH_SEGMENT))
}
fn opt_path_type_args(p: &mut Parser<'_>, mode: Mode) {
match mode {
Mode::Use | Mode::Attr | Mode::Vis => {}
Mode::Type => {
// test typepathfn_with_coloncolon
// type F = Start::(Middle) -> (Middle)::End;
// type GenericArg = S<Start(Middle)::End>;
if p.at(T![::]) && p.nth_at(2, T!['(']) {
p.bump(T![::]);
}
if p.at(T!['(']) {
if p.nth_at(1, T![..]) {
// test return_type_syntax_in_path
// fn foo<T>()
// where
// T::method(..): Send,
// {}
let rtn = p.start();
p.bump(T!['(']);
p.bump(T![..]);
p.expect(T![')']);
rtn.complete(p, RETURN_TYPE_SYNTAX);
} else {
// test path_fn_trait_args
// type F = Box<Fn(i32) -> ()>;
params::param_list_fn_trait(p);
opt_ret_type(p);
}
} else {
generic_args::opt_generic_arg_list(p, false);
}
}
Mode::Expr => generic_args::opt_generic_arg_list(p, true),
pub(crate) fn opt_path_type_args(p: &mut Parser<'_>) {
// test typepathfn_with_coloncolon
// type F = Start::(Middle) -> (Middle)::End;
// type GenericArg = S<Start(Middle)::End>;
let m;
if p.at(T![::]) && matches!(p.nth(2), T![<] | T!['(']) {
m = p.start();
p.bump(T![::]);
} else if (p.current() == T![<] && p.nth(1) != T![=]) || p.current() == T!['('] {
m = p.start();
} else {
return;
}
let current = p.current();
if current == T![<] {
// test_err generic_arg_list_recover
// type T = T<0, ,T>;
// type T = T::<0, ,T>;
delimited(
p,
T![<],
T![>],
T![,],
|| "expected generic argument".into(),
generic_args::GENERIC_ARG_FIRST,
generic_args::generic_arg,
);
m.complete(p, GENERIC_ARG_LIST);
} else if p.nth_at(1, T![..]) {
// test return_type_syntax_in_path
// fn foo<T>()
// where
// T::method(..): Send,
// method(..): Send,
// method::(..): Send,
// {}
p.bump(T!['(']);
p.bump(T![..]);
p.expect(T![')']);
m.complete(p, RETURN_TYPE_SYNTAX);
} else {
// test path_fn_trait_args
// type F = Box<Fn(i32) -> ()>;
// type F = Box<::Fn(i32) -> ()>;
// type F = Box<Fn::(i32) -> ()>;
// type F = Box<::Fn::(i32) -> ()>;
delimited(
p,
T!['('],
T![')'],
T![,],
|| "expected type".into(),
types::TYPE_FIRST,
|p| {
let progress = types::TYPE_FIRST.contains(p.current());
generic_args::type_arg(p);
progress
},
);
m.complete(p, PARENTHESIZED_ARG_LIST);
opt_ret_type(p);
}
}
fn opt_path_args(p: &mut Parser<'_>, mode: Mode) {
match mode {
Mode::Use | Mode::Attr | Mode::Vis => {}
Mode::Type => opt_path_type_args(p),
Mode::Expr => generic_args::opt_generic_arg_list_expr(p),
}
}

View file

@ -50,7 +50,7 @@ fn type_with_bounds_cond(p: &mut Parser<'_>, allow_bounds: bool) {
// Some path types are not allowed to have bounds (no plus)
T![<] => path_type_bounds(p, allow_bounds),
T![ident] if !p.edition().at_least_2018() && is_dyn_weak(p) => dyn_trait_type_weak(p),
_ if paths::is_path_start(p) => path_or_macro_type_(p, allow_bounds),
_ if paths::is_path_start(p) => path_or_macro_type(p, allow_bounds),
LIFETIME_IDENT if p.nth_at(1, T![+]) => bare_dyn_trait_type(p),
_ => {
p.err_recover("expected type", TYPE_RECOVERY_SET);
@ -337,7 +337,7 @@ pub(super) fn path_type(p: &mut Parser<'_>) {
// test macro_call_type
// type A = foo!();
// type B = crate::foo!();
fn path_or_macro_type_(p: &mut Parser<'_>, allow_bounds: bool) {
fn path_or_macro_type(p: &mut Parser<'_>, allow_bounds: bool) {
assert!(paths::is_path_start(p));
let r = p.start();
let m = p.start();

View file

@ -256,6 +256,7 @@ pub enum SyntaxKind {
OR_PAT,
PARAM,
PARAM_LIST,
PARENTHESIZED_ARG_LIST,
PAREN_EXPR,
PAREN_PAT,
PAREN_TYPE,

View file

@ -39,10 +39,6 @@ mod ok {
#[test]
fn assoc_type_eq() { run_and_expect_no_errors("test_data/parser/inline/ok/assoc_type_eq.rs"); }
#[test]
fn associated_type_bounds() {
run_and_expect_no_errors("test_data/parser/inline/ok/associated_type_bounds.rs");
}
#[test]
fn async_trait_bound() {
run_and_expect_no_errors("test_data/parser/inline/ok/async_trait_bound.rs");
}
@ -59,12 +55,6 @@ mod ok {
);
}
#[test]
fn bare_dyn_types_with_paren_as_generic_args() {
run_and_expect_no_errors(
"test_data/parser/inline/ok/bare_dyn_types_with_paren_as_generic_args.rs",
);
}
#[test]
fn become_expr() { run_and_expect_no_errors("test_data/parser/inline/ok/become_expr.rs"); }
#[test]
fn bind_pat() { run_and_expect_no_errors("test_data/parser/inline/ok/bind_pat.rs"); }
@ -281,6 +271,10 @@ mod ok {
#[test]
fn generic_arg() { run_and_expect_no_errors("test_data/parser/inline/ok/generic_arg.rs"); }
#[test]
fn generic_arg_bounds() {
run_and_expect_no_errors("test_data/parser/inline/ok/generic_arg_bounds.rs");
}
#[test]
fn generic_param_attribute() {
run_and_expect_no_errors("test_data/parser/inline/ok/generic_param_attribute.rs");
}
@ -423,10 +417,6 @@ mod ok {
#[test]
fn param_list() { run_and_expect_no_errors("test_data/parser/inline/ok/param_list.rs"); }
#[test]
fn param_list_opt_patterns() {
run_and_expect_no_errors("test_data/parser/inline/ok/param_list_opt_patterns.rs");
}
#[test]
fn param_list_vararg() {
run_and_expect_no_errors("test_data/parser/inline/ok/param_list_vararg.rs");
}
@ -521,12 +511,6 @@ mod ok {
#[test]
fn return_expr() { run_and_expect_no_errors("test_data/parser/inline/ok/return_expr.rs"); }
#[test]
fn return_type_syntax_assoc_type_bound() {
run_and_expect_no_errors(
"test_data/parser/inline/ok/return_type_syntax_assoc_type_bound.rs",
);
}
#[test]
fn return_type_syntax_in_path() {
run_and_expect_no_errors("test_data/parser/inline/ok/return_type_syntax_in_path.rs");
}
@ -685,10 +669,6 @@ mod ok {
#[test]
fn use_tree_star() { run_and_expect_no_errors("test_data/parser/inline/ok/use_tree_star.rs"); }
#[test]
fn value_parameters_no_patterns() {
run_and_expect_no_errors("test_data/parser/inline/ok/value_parameters_no_patterns.rs");
}
#[test]
fn variant_discriminant() {
run_and_expect_no_errors("test_data/parser/inline/ok/variant_discriminant.rs");
}
@ -754,6 +734,10 @@ mod err {
run_and_expect_errors("test_data/parser/inline/err/generic_arg_list_recover.rs");
}
#[test]
fn generic_arg_list_recover_expr() {
run_and_expect_errors("test_data/parser/inline/err/generic_arg_list_recover_expr.rs");
}
#[test]
fn generic_param_list_recover() {
run_and_expect_errors("test_data/parser/inline/err/generic_param_list_recover.rs");
}

View file

@ -30,4 +30,37 @@ SOURCE_FILE
R_ANGLE ">"
SEMICOLON ";"
WHITESPACE "\n"
TYPE_ALIAS
TYPE_KW "type"
WHITESPACE " "
NAME
IDENT "T"
WHITESPACE " "
EQ "="
WHITESPACE " "
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "T"
GENERIC_ARG_LIST
COLON2 "::"
L_ANGLE "<"
CONST_ARG
LITERAL
INT_NUMBER "0"
COMMA ","
WHITESPACE " "
ERROR
COMMA ","
TYPE_ARG
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "T"
R_ANGLE ">"
SEMICOLON ";"
WHITESPACE "\n"
error 14: expected generic argument
error 35: expected generic argument

View file

@ -1 +1,2 @@
type T = T<0, ,T>;
type T = T::<0, ,T>;

View file

@ -0,0 +1,79 @@
SOURCE_FILE
CONST
CONST_KW "const"
WHITESPACE " "
UNDERSCORE "_"
COLON ":"
WHITESPACE " "
TUPLE_TYPE
L_PAREN "("
R_PAREN ")"
WHITESPACE " "
EQ "="
WHITESPACE " "
PATH_EXPR
PATH
PATH_SEGMENT
NAME_REF
IDENT "T"
GENERIC_ARG_LIST
COLON2 "::"
L_ANGLE "<"
CONST_ARG
LITERAL
INT_NUMBER "0"
COMMA ","
WHITESPACE " "
ERROR
COMMA ","
TYPE_ARG
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "T"
R_ANGLE ">"
SEMICOLON ";"
WHITESPACE "\n"
CONST
CONST_KW "const"
WHITESPACE " "
UNDERSCORE "_"
COLON ":"
WHITESPACE " "
TUPLE_TYPE
L_PAREN "("
R_PAREN ")"
WHITESPACE " "
EQ "="
WHITESPACE " "
CALL_EXPR
PATH_EXPR
PATH
PATH_SEGMENT
NAME_REF
IDENT "T"
GENERIC_ARG_LIST
COLON2 "::"
L_ANGLE "<"
CONST_ARG
LITERAL
INT_NUMBER "0"
COMMA ","
WHITESPACE " "
ERROR
COMMA ","
TYPE_ARG
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "T"
R_ANGLE ">"
ARG_LIST
L_PAREN "("
R_PAREN ")"
SEMICOLON ";"
WHITESPACE "\n"
error 21: expected generic argument
error 47: expected generic argument

View file

@ -0,0 +1,2 @@
const _: () = T::<0, ,T>;
const _: () = T::<0, ,T>();

View file

@ -35,3 +35,42 @@ SOURCE_FILE
R_ANGLE ">"
SEMICOLON ";"
WHITESPACE "\n"
TYPE_ALIAS
TYPE_KW "type"
WHITESPACE " "
NAME
IDENT "T"
WHITESPACE " "
EQ "="
WHITESPACE " "
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "StreamingIterator"
GENERIC_ARG_LIST
L_ANGLE "<"
ASSOC_TYPE_ARG
NAME_REF
IDENT "Item"
PARENTHESIZED_ARG_LIST
L_PAREN "("
TYPE_ARG
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "T"
R_PAREN ")"
COLON ":"
WHITESPACE " "
TYPE_BOUND_LIST
TYPE_BOUND
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "Clone"
R_ANGLE ">"
SEMICOLON ";"
WHITESPACE "\n"

View file

@ -1 +1,2 @@
type T = StreamingIterator<Item<'a>: Clone>;
type T = StreamingIterator<Item(T): Clone>;

View file

@ -1,111 +0,0 @@
SOURCE_FILE
FN
FN_KW "fn"
WHITESPACE " "
NAME
IDENT "print_all"
GENERIC_PARAM_LIST
L_ANGLE "<"
TYPE_PARAM
NAME
IDENT "T"
COLON ":"
WHITESPACE " "
TYPE_BOUND_LIST
TYPE_BOUND
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "Iterator"
GENERIC_ARG_LIST
L_ANGLE "<"
TYPE_ARG
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "Item"
COMMA ","
WHITESPACE " "
TYPE_ARG
PATH_TYPE
PATH
PATH
PATH_SEGMENT
NAME_REF
IDENT "Item"
COLON2 "::"
PATH_SEGMENT
NAME_REF
IDENT "Item"
COMMA ","
WHITESPACE " "
TYPE_ARG
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "Item"
GENERIC_ARG_LIST
COLON2 "::"
L_ANGLE "<"
CONST_ARG
LITERAL
TRUE_KW "true"
R_ANGLE ">"
COMMA ","
WHITESPACE " "
ASSOC_TYPE_ARG
NAME_REF
IDENT "Item"
COLON ":"
WHITESPACE " "
TYPE_BOUND_LIST
TYPE_BOUND
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "Display"
COMMA ","
WHITESPACE " "
ASSOC_TYPE_ARG
NAME_REF
IDENT "Item"
GENERIC_ARG_LIST
L_ANGLE "<"
LIFETIME_ARG
LIFETIME
LIFETIME_IDENT "'a"
R_ANGLE ">"
WHITESPACE " "
EQ "="
WHITESPACE " "
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "Item"
R_ANGLE ">"
R_ANGLE ">"
PARAM_LIST
L_PAREN "("
PARAM
IDENT_PAT
NAME
IDENT "printables"
COLON ":"
WHITESPACE " "
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "T"
R_PAREN ")"
WHITESPACE " "
BLOCK_EXPR
STMT_LIST
L_CURLY "{"
R_CURLY "}"
WHITESPACE "\n"

View file

@ -1 +0,0 @@
fn print_all<T: Iterator<Item, Item::Item, Item::<true>, Item: Display, Item<'a> = Item>>(printables: T) {}

View file

@ -23,9 +23,9 @@ SOURCE_FILE
PATH_SEGMENT
NAME_REF
IDENT "Fn"
PARAM_LIST
PARENTHESIZED_ARG_LIST
L_PAREN "("
PARAM
TYPE_ARG
REF_TYPE
AMP "&"
PATH_TYPE

View file

@ -1,175 +0,0 @@
SOURCE_FILE
TYPE_ALIAS
TYPE_KW "type"
WHITESPACE " "
NAME
IDENT "A"
WHITESPACE " "
EQ "="
WHITESPACE " "
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "S"
GENERIC_ARG_LIST
L_ANGLE "<"
TYPE_ARG
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "Fn"
PARAM_LIST
L_PAREN "("
PARAM
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "i32"
R_PAREN ")"
R_ANGLE ">"
SEMICOLON ";"
WHITESPACE "\n"
TYPE_ALIAS
TYPE_KW "type"
WHITESPACE " "
NAME
IDENT "A"
WHITESPACE " "
EQ "="
WHITESPACE " "
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "S"
GENERIC_ARG_LIST
L_ANGLE "<"
TYPE_ARG
DYN_TRAIT_TYPE
TYPE_BOUND_LIST
TYPE_BOUND
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "Fn"
PARAM_LIST
L_PAREN "("
PARAM
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "i32"
R_PAREN ")"
WHITESPACE " "
PLUS "+"
WHITESPACE " "
TYPE_BOUND
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "Send"
R_ANGLE ">"
SEMICOLON ";"
WHITESPACE "\n"
TYPE_ALIAS
TYPE_KW "type"
WHITESPACE " "
NAME
IDENT "B"
WHITESPACE " "
EQ "="
WHITESPACE " "
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "S"
GENERIC_ARG_LIST
L_ANGLE "<"
TYPE_ARG
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "Fn"
PARAM_LIST
L_PAREN "("
PARAM
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "i32"
R_PAREN ")"
WHITESPACE " "
RET_TYPE
THIN_ARROW "->"
WHITESPACE " "
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "i32"
R_ANGLE ">"
SEMICOLON ";"
WHITESPACE "\n"
TYPE_ALIAS
TYPE_KW "type"
WHITESPACE " "
NAME
IDENT "C"
WHITESPACE " "
EQ "="
WHITESPACE " "
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "S"
GENERIC_ARG_LIST
L_ANGLE "<"
TYPE_ARG
DYN_TRAIT_TYPE
TYPE_BOUND_LIST
TYPE_BOUND
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "Fn"
PARAM_LIST
L_PAREN "("
PARAM
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "i32"
R_PAREN ")"
WHITESPACE " "
RET_TYPE
THIN_ARROW "->"
WHITESPACE " "
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "i32"
WHITESPACE " "
PLUS "+"
WHITESPACE " "
TYPE_BOUND
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "Send"
R_ANGLE ">"
SEMICOLON ";"
WHITESPACE "\n"

View file

@ -1,4 +0,0 @@
type A = S<Fn(i32)>;
type A = S<Fn(i32) + Send>;
type B = S<Fn(i32) -> i32>;
type C = S<Fn(i32) -> i32 + Send>;

View file

@ -0,0 +1,461 @@
SOURCE_FILE
TYPE_ALIAS
TYPE_KW "type"
WHITESPACE " "
NAME
IDENT "Plain"
WHITESPACE " "
EQ "="
WHITESPACE " "
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "Foo"
GENERIC_ARG_LIST
L_ANGLE "<"
TYPE_ARG
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "Item"
COMMA ","
WHITESPACE " "
TYPE_ARG
PATH_TYPE
PATH
PATH
PATH_SEGMENT
NAME_REF
IDENT "Item"
COLON2 "::"
PATH_SEGMENT
NAME_REF
IDENT "Item"
COMMA ","
WHITESPACE " "
ASSOC_TYPE_ARG
NAME_REF
IDENT "Item"
COLON ":"
WHITESPACE " "
TYPE_BOUND_LIST
TYPE_BOUND
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "Bound"
COMMA ","
WHITESPACE " "
ASSOC_TYPE_ARG
NAME_REF
IDENT "Item"
WHITESPACE " "
EQ "="
WHITESPACE " "
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "Item"
R_ANGLE ">"
SEMICOLON ";"
WHITESPACE "\n"
TYPE_ALIAS
TYPE_KW "type"
WHITESPACE " "
NAME
IDENT "GenericArgs"
WHITESPACE " "
EQ "="
WHITESPACE " "
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "Foo"
GENERIC_ARG_LIST
L_ANGLE "<"
TYPE_ARG
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "Item"
GENERIC_ARG_LIST
L_ANGLE "<"
TYPE_ARG
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "T"
R_ANGLE ">"
COMMA ","
WHITESPACE " "
TYPE_ARG
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "Item"
GENERIC_ARG_LIST
COLON2 "::"
L_ANGLE "<"
TYPE_ARG
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "T"
R_ANGLE ">"
COMMA ","
WHITESPACE " "
ASSOC_TYPE_ARG
NAME_REF
IDENT "Item"
GENERIC_ARG_LIST
L_ANGLE "<"
TYPE_ARG
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "T"
R_ANGLE ">"
COLON ":"
WHITESPACE " "
TYPE_BOUND_LIST
TYPE_BOUND
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "Bound"
COMMA ","
WHITESPACE " "
ASSOC_TYPE_ARG
NAME_REF
IDENT "Item"
GENERIC_ARG_LIST
COLON2 "::"
L_ANGLE "<"
TYPE_ARG
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "T"
R_ANGLE ">"
COLON ":"
WHITESPACE " "
TYPE_BOUND_LIST
TYPE_BOUND
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "Bound"
COMMA ","
WHITESPACE " "
ASSOC_TYPE_ARG
NAME_REF
IDENT "Item"
GENERIC_ARG_LIST
L_ANGLE "<"
TYPE_ARG
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "T"
R_ANGLE ">"
WHITESPACE " "
EQ "="
WHITESPACE " "
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "Item"
COMMA ","
WHITESPACE " "
ASSOC_TYPE_ARG
NAME_REF
IDENT "Item"
GENERIC_ARG_LIST
COLON2 "::"
L_ANGLE "<"
TYPE_ARG
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "T"
R_ANGLE ">"
WHITESPACE " "
EQ "="
WHITESPACE " "
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "Item"
R_ANGLE ">"
SEMICOLON ";"
WHITESPACE "\n"
TYPE_ALIAS
TYPE_KW "type"
WHITESPACE " "
NAME
IDENT "ParenthesizedArgs"
WHITESPACE " "
EQ "="
WHITESPACE " "
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "Foo"
GENERIC_ARG_LIST
L_ANGLE "<"
TYPE_ARG
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "Item"
PARENTHESIZED_ARG_LIST
L_PAREN "("
TYPE_ARG
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "T"
R_PAREN ")"
COMMA ","
WHITESPACE " "
TYPE_ARG
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "Item"
PARENTHESIZED_ARG_LIST
COLON2 "::"
L_PAREN "("
TYPE_ARG
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "T"
R_PAREN ")"
COMMA ","
WHITESPACE " "
ASSOC_TYPE_ARG
NAME_REF
IDENT "Item"
PARENTHESIZED_ARG_LIST
L_PAREN "("
TYPE_ARG
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "T"
R_PAREN ")"
COLON ":"
WHITESPACE " "
TYPE_BOUND_LIST
TYPE_BOUND
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "Bound"
COMMA ","
WHITESPACE " "
ASSOC_TYPE_ARG
NAME_REF
IDENT "Item"
PARENTHESIZED_ARG_LIST
COLON2 "::"
L_PAREN "("
TYPE_ARG
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "T"
R_PAREN ")"
COLON ":"
WHITESPACE " "
TYPE_BOUND_LIST
TYPE_BOUND
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "Bound"
COMMA ","
WHITESPACE " "
ASSOC_TYPE_ARG
NAME_REF
IDENT "Item"
PARENTHESIZED_ARG_LIST
L_PAREN "("
TYPE_ARG
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "T"
R_PAREN ")"
WHITESPACE " "
EQ "="
WHITESPACE " "
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "Item"
COMMA ","
WHITESPACE " "
ASSOC_TYPE_ARG
NAME_REF
IDENT "Item"
PARENTHESIZED_ARG_LIST
COLON2 "::"
L_PAREN "("
TYPE_ARG
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "T"
R_PAREN ")"
WHITESPACE " "
EQ "="
WHITESPACE " "
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "Item"
R_ANGLE ">"
SEMICOLON ";"
WHITESPACE "\n"
TYPE_ALIAS
TYPE_KW "type"
WHITESPACE " "
NAME
IDENT "RTN"
WHITESPACE " "
EQ "="
WHITESPACE " "
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "Foo"
GENERIC_ARG_LIST
L_ANGLE "<"
TYPE_ARG
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "Item"
RETURN_TYPE_SYNTAX
L_PAREN "("
DOT2 ".."
R_PAREN ")"
COMMA ","
WHITESPACE " "
TYPE_ARG
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "Item"
RETURN_TYPE_SYNTAX
L_PAREN "("
DOT2 ".."
R_PAREN ")"
COMMA ","
WHITESPACE " "
ASSOC_TYPE_ARG
NAME_REF
IDENT "Item"
RETURN_TYPE_SYNTAX
L_PAREN "("
DOT2 ".."
R_PAREN ")"
COLON ":"
WHITESPACE " "
TYPE_BOUND_LIST
TYPE_BOUND
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "Bound"
COMMA ","
WHITESPACE " "
ASSOC_TYPE_ARG
NAME_REF
IDENT "Item"
RETURN_TYPE_SYNTAX
L_PAREN "("
DOT2 ".."
R_PAREN ")"
COLON ":"
WHITESPACE " "
TYPE_BOUND_LIST
TYPE_BOUND
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "Bound"
COMMA ","
WHITESPACE " "
ASSOC_TYPE_ARG
NAME_REF
IDENT "Item"
RETURN_TYPE_SYNTAX
L_PAREN "("
DOT2 ".."
R_PAREN ")"
WHITESPACE " "
EQ "="
WHITESPACE " "
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "Item"
COMMA ","
WHITESPACE " "
ASSOC_TYPE_ARG
NAME_REF
IDENT "Item"
RETURN_TYPE_SYNTAX
L_PAREN "("
DOT2 ".."
R_PAREN ")"
WHITESPACE " "
EQ "="
WHITESPACE " "
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "Item"
R_ANGLE ">"
SEMICOLON ";"
WHITESPACE "\n"

View file

@ -0,0 +1,4 @@
type Plain = Foo<Item, Item::Item, Item: Bound, Item = Item>;
type GenericArgs = Foo<Item<T>, Item::<T>, Item<T>: Bound, Item::<T>: Bound, Item<T> = Item, Item::<T> = Item>;
type ParenthesizedArgs = Foo<Item(T), Item::(T), Item(T): Bound, Item::(T): Bound, Item(T) = Item, Item::(T) = Item>;
type RTN = Foo<Item(..), Item(..), Item(..): Bound, Item(..): Bound, Item(..) = Item, Item(..) = Item>;

View file

@ -1,48 +0,0 @@
SOURCE_FILE
FN
FN_KW "fn"
WHITESPACE " "
NAME
IDENT "foo"
GENERIC_PARAM_LIST
L_ANGLE "<"
TYPE_PARAM
NAME
IDENT "F"
COLON ":"
WHITESPACE " "
TYPE_BOUND_LIST
TYPE_BOUND
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "FnMut"
PARAM_LIST
L_PAREN "("
PARAM
REF_TYPE
AMP "&"
MUT_KW "mut"
WHITESPACE " "
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "Foo"
GENERIC_ARG_LIST
L_ANGLE "<"
LIFETIME_ARG
LIFETIME
LIFETIME_IDENT "'a"
R_ANGLE ">"
R_PAREN ")"
R_ANGLE ">"
PARAM_LIST
L_PAREN "("
R_PAREN ")"
BLOCK_EXPR
STMT_LIST
L_CURLY "{"
R_CURLY "}"
WHITESPACE "\n"

View file

@ -1 +0,0 @@
fn foo<F: FnMut(&mut Foo<'a>)>(){}

View file

@ -20,9 +20,133 @@ SOURCE_FILE
PATH_SEGMENT
NAME_REF
IDENT "Fn"
PARAM_LIST
PARENTHESIZED_ARG_LIST
L_PAREN "("
PARAM
TYPE_ARG
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "i32"
R_PAREN ")"
WHITESPACE " "
RET_TYPE
THIN_ARROW "->"
WHITESPACE " "
TUPLE_TYPE
L_PAREN "("
R_PAREN ")"
R_ANGLE ">"
SEMICOLON ";"
WHITESPACE "\n"
TYPE_ALIAS
TYPE_KW "type"
WHITESPACE " "
NAME
IDENT "F"
WHITESPACE " "
EQ "="
WHITESPACE " "
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "Box"
GENERIC_ARG_LIST
L_ANGLE "<"
TYPE_ARG
PATH_TYPE
PATH
PATH_SEGMENT
COLON2 "::"
NAME_REF
IDENT "Fn"
PARENTHESIZED_ARG_LIST
L_PAREN "("
TYPE_ARG
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "i32"
R_PAREN ")"
WHITESPACE " "
RET_TYPE
THIN_ARROW "->"
WHITESPACE " "
TUPLE_TYPE
L_PAREN "("
R_PAREN ")"
R_ANGLE ">"
SEMICOLON ";"
WHITESPACE "\n"
TYPE_ALIAS
TYPE_KW "type"
WHITESPACE " "
NAME
IDENT "F"
WHITESPACE " "
EQ "="
WHITESPACE " "
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "Box"
GENERIC_ARG_LIST
L_ANGLE "<"
TYPE_ARG
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "Fn"
PARENTHESIZED_ARG_LIST
COLON2 "::"
L_PAREN "("
TYPE_ARG
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "i32"
R_PAREN ")"
WHITESPACE " "
RET_TYPE
THIN_ARROW "->"
WHITESPACE " "
TUPLE_TYPE
L_PAREN "("
R_PAREN ")"
R_ANGLE ">"
SEMICOLON ";"
WHITESPACE "\n"
TYPE_ALIAS
TYPE_KW "type"
WHITESPACE " "
NAME
IDENT "F"
WHITESPACE " "
EQ "="
WHITESPACE " "
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "Box"
GENERIC_ARG_LIST
L_ANGLE "<"
TYPE_ARG
PATH_TYPE
PATH
PATH_SEGMENT
COLON2 "::"
NAME_REF
IDENT "Fn"
PARENTHESIZED_ARG_LIST
COLON2 "::"
L_PAREN "("
TYPE_ARG
PATH_TYPE
PATH
PATH_SEGMENT

View file

@ -1 +1,4 @@
type F = Box<Fn(i32) -> ()>;
type F = Box<::Fn(i32) -> ()>;
type F = Box<Fn::(i32) -> ()>;
type F = Box<::Fn::(i32) -> ()>;

View file

@ -1,49 +0,0 @@
SOURCE_FILE
FN
FN_KW "fn"
WHITESPACE " "
NAME
IDENT "foo"
GENERIC_PARAM_LIST
L_ANGLE "<"
TYPE_PARAM
NAME
IDENT "T"
COLON ":"
WHITESPACE " "
TYPE_BOUND_LIST
TYPE_BOUND
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "Trait"
GENERIC_ARG_LIST
L_ANGLE "<"
ASSOC_TYPE_ARG
NAME_REF
IDENT "method"
RETURN_TYPE_SYNTAX
L_PAREN "("
DOT2 ".."
R_PAREN ")"
COLON ":"
WHITESPACE " "
TYPE_BOUND_LIST
TYPE_BOUND
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "Send"
R_ANGLE ">"
R_ANGLE ">"
PARAM_LIST
L_PAREN "("
R_PAREN ")"
WHITESPACE " "
BLOCK_EXPR
STMT_LIST
L_CURLY "{"
R_CURLY "}"
WHITESPACE "\n"

View file

@ -1 +0,0 @@
fn foo<T: Trait<method(..): Send>>() {}

View file

@ -42,6 +42,49 @@ SOURCE_FILE
NAME_REF
IDENT "Send"
COMMA ","
WHITESPACE "\n "
WHERE_PRED
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "method"
RETURN_TYPE_SYNTAX
L_PAREN "("
DOT2 ".."
R_PAREN ")"
COLON ":"
WHITESPACE " "
TYPE_BOUND_LIST
TYPE_BOUND
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "Send"
COMMA ","
WHITESPACE "\n "
WHERE_PRED
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "method"
RETURN_TYPE_SYNTAX
COLON2 "::"
L_PAREN "("
DOT2 ".."
R_PAREN ")"
COLON ":"
WHITESPACE " "
TYPE_BOUND_LIST
TYPE_BOUND
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "Send"
COMMA ","
WHITESPACE "\n"
BLOCK_EXPR
STMT_LIST

View file

@ -1,4 +1,6 @@
fn foo<T>()
where
T::method(..): Send,
method(..): Send,
method::(..): Send,
{}

View file

@ -13,10 +13,10 @@ SOURCE_FILE
PATH_SEGMENT
NAME_REF
IDENT "Start"
COLON2 "::"
PARAM_LIST
PARENTHESIZED_ARG_LIST
COLON2 "::"
L_PAREN "("
PARAM
TYPE_ARG
PATH_TYPE
PATH
PATH_SEGMENT
@ -63,9 +63,9 @@ SOURCE_FILE
PATH_SEGMENT
NAME_REF
IDENT "Start"
PARAM_LIST
PARENTHESIZED_ARG_LIST
L_PAREN "("
PARAM
TYPE_ARG
PATH_TYPE
PATH
PATH_SEGMENT

View file

@ -1,60 +0,0 @@
SOURCE_FILE
TYPE_ALIAS
TYPE_KW "type"
WHITESPACE " "
NAME
IDENT "F"
WHITESPACE " "
EQ "="
WHITESPACE " "
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "Box"
GENERIC_ARG_LIST
L_ANGLE "<"
TYPE_ARG
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "Fn"
PARAM_LIST
L_PAREN "("
PARAM
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "i32"
COMMA ","
WHITESPACE " "
PARAM
REF_TYPE
AMP "&"
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "i32"
COMMA ","
WHITESPACE " "
PARAM
REF_TYPE
AMP "&"
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "i32"
COMMA ","
WHITESPACE " "
PARAM
TUPLE_TYPE
L_PAREN "("
R_PAREN ")"
R_PAREN ")"
R_ANGLE ">"
SEMICOLON ";"
WHITESPACE "\n"

View file

@ -1 +0,0 @@
type F = Box<Fn(i32, &i32, &i32, ())>;

View file

@ -40,9 +40,9 @@ SOURCE_FILE
PATH_SEGMENT
NAME_REF
IDENT "Fn"
PARAM_LIST
PARENTHESIZED_ARG_LIST
L_PAREN "("
PARAM
TYPE_ARG
REF_TYPE
AMP "&"
LIFETIME

View file

@ -180,7 +180,7 @@ SOURCE_FILE
PATH_SEGMENT
NAME_REF
IDENT "Fn"
PARAM_LIST
PARENTHESIZED_ARG_LIST
L_PAREN "("
R_PAREN ")"
WHITESPACE " "

View file

@ -138,63 +138,6 @@ SOURCE_FILE
WHITESPACE " "
R_CURLY "}"
WHITESPACE "\n\n"
FN
FN_KW "fn"
WHITESPACE " "
NAME
IDENT "foo"
GENERIC_PARAM_LIST
L_ANGLE "<"
TYPE_PARAM
NAME
IDENT "F"
COLON ":"
WHITESPACE " "
TYPE_BOUND_LIST
TYPE_BOUND
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "FnMut"
PARAM_LIST
L_PAREN "("
PARAM
ATTR
POUND "#"
L_BRACK "["
META
PATH
PATH_SEGMENT
NAME_REF
IDENT "attr"
R_BRACK "]"
WHITESPACE " "
REF_TYPE
AMP "&"
MUT_KW "mut"
WHITESPACE " "
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "Foo"
GENERIC_ARG_LIST
L_ANGLE "<"
LIFETIME_ARG
LIFETIME
LIFETIME_IDENT "'a"
R_ANGLE ">"
R_PAREN ")"
R_ANGLE ">"
PARAM_LIST
L_PAREN "("
R_PAREN ")"
BLOCK_EXPR
STMT_LIST
L_CURLY "{"
R_CURLY "}"
WHITESPACE "\n\n"
TRAIT
TRAIT_KW "trait"
WHITESPACE " "

View file

@ -3,8 +3,6 @@ fn g2(#[attr1] x: u8) {}
extern "C" { fn printf(format: *const i8, #[attr] ...) -> i32; }
fn foo<F: FnMut(#[attr] &mut Foo<'a>)>(){}
trait Foo {
fn bar(#[attr] _: u64, # [attr] mut x: i32);
}

View file

@ -58,9 +58,9 @@ SOURCE_FILE
PATH_SEGMENT
NAME_REF
IDENT "FnMut"
PARAM_LIST
PARENTHESIZED_ARG_LIST
L_PAREN "("
PARAM
TYPE_ARG
PATH_TYPE
PATH
PATH
@ -101,9 +101,9 @@ SOURCE_FILE
PATH_SEGMENT
NAME_REF
IDENT "FnMut"
PARAM_LIST
PARENTHESIZED_ARG_LIST
L_PAREN "("
PARAM
TYPE_ARG
REF_TYPE
AMP "&"
PATH_TYPE

View file

@ -32,7 +32,7 @@ SOURCE_FILE
PATH_SEGMENT
NAME_REF
IDENT "Fn"
PARAM_LIST
PARENTHESIZED_ARG_LIST
L_PAREN "("
R_PAREN ")"
WHITESPACE " "

View file

@ -40,9 +40,9 @@ SOURCE_FILE
PATH_SEGMENT
NAME_REF
IDENT "Fn"
PARAM_LIST
PARENTHESIZED_ARG_LIST
L_PAREN "("
PARAM
TYPE_ARG
REF_TYPE
AMP "&"
LIFETIME
@ -165,9 +165,9 @@ SOURCE_FILE
PATH_SEGMENT
NAME_REF
IDENT "Fn"
PARAM_LIST
PARENTHESIZED_ARG_LIST
L_PAREN "("
PARAM
TYPE_ARG
REF_TYPE
AMP "&"
LIFETIME