Merge pull request #20281 from ChayimFriedman2/parse-hrtb-const

fix: Parse `for<'a> [const]`
This commit is contained in:
Shoyu Vanilla (Flint) 2025-07-23 01:50:16 +00:00 committed by GitHub
commit fa64d3b720
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
28 changed files with 465 additions and 354 deletions

View File

@ -960,37 +960,28 @@ impl ExprCollector<'_> {
impl_trait_lower_fn: ImplTraitLowerFn<'_>, impl_trait_lower_fn: ImplTraitLowerFn<'_>,
) -> TypeBound { ) -> TypeBound {
match node.kind() { match node.kind() {
ast::TypeBoundKind::PathType(path_type) => { ast::TypeBoundKind::PathType(binder, path_type) => {
let m = match node.question_mark_token() { let binder = match binder.and_then(|it| it.generic_param_list()) {
Some(_) => TraitBoundModifier::Maybe,
None => TraitBoundModifier::None,
};
self.lower_path_type(&path_type, impl_trait_lower_fn)
.map(|p| {
TypeBound::Path(self.alloc_path(p, AstPtr::new(&path_type).upcast()), m)
})
.unwrap_or(TypeBound::Error)
}
ast::TypeBoundKind::ForType(for_type) => {
let lt_refs = match for_type.generic_param_list() {
Some(gpl) => gpl Some(gpl) => gpl
.lifetime_params() .lifetime_params()
.flat_map(|lp| lp.lifetime().map(|lt| Name::new_lifetime(&lt.text()))) .flat_map(|lp| lp.lifetime().map(|lt| Name::new_lifetime(&lt.text())))
.collect(), .collect(),
None => ThinVec::default(), None => ThinVec::default(),
}; };
let path = for_type.ty().and_then(|ty| match &ty { let m = match node.question_mark_token() {
ast::Type::PathType(path_type) => { Some(_) => TraitBoundModifier::Maybe,
self.lower_path_type(path_type, impl_trait_lower_fn).map(|p| (p, ty)) None => TraitBoundModifier::None,
} };
_ => None, self.lower_path_type(&path_type, impl_trait_lower_fn)
}); .map(|p| {
match path { let path = self.alloc_path(p, AstPtr::new(&path_type).upcast());
Some((p, ty)) => { if binder.is_empty() {
TypeBound::ForLifetime(lt_refs, self.alloc_path(p, AstPtr::new(&ty))) TypeBound::Path(path, m)
} } else {
None => TypeBound::Error, TypeBound::ForLifetime(binder, path)
} }
})
.unwrap_or(TypeBound::Error)
} }
ast::TypeBoundKind::Use(gal) => TypeBound::Use( ast::TypeBoundKind::Use(gal) => TypeBound::Use(
gal.use_bound_generic_args() gal.use_bound_generic_args()

View File

@ -180,17 +180,18 @@ impl GenericParamsCollector {
continue; continue;
}; };
let lifetimes: Option<Box<_>> = pred.generic_param_list().map(|param_list| { let lifetimes: Option<Box<_>> =
// Higher-Ranked Trait Bounds pred.for_binder().and_then(|it| it.generic_param_list()).map(|param_list| {
param_list // Higher-Ranked Trait Bounds
.lifetime_params() param_list
.map(|lifetime_param| { .lifetime_params()
lifetime_param .map(|lifetime_param| {
.lifetime() lifetime_param
.map_or_else(Name::missing, |lt| Name::new_lifetime(&lt.text())) .lifetime()
}) .map_or_else(Name::missing, |lt| Name::new_lifetime(&lt.text()))
.collect() })
}); .collect()
});
for bound in pred.type_bound_list().iter().flat_map(|l| l.bounds()) { for bound in pred.type_bound_list().iter().flat_map(|l| l.bounds()) {
self.lower_type_bound_as_predicate(ec, bound, lifetimes.as_deref(), target); self.lower_type_bound_as_predicate(ec, bound, lifetimes.as_deref(), target);
} }

View File

@ -77,17 +77,18 @@ pub(super) fn fn_ptr_hints(
return None; return None;
} }
let parent_for_type = func let parent_for_binder = func
.syntax() .syntax()
.ancestors() .ancestors()
.skip(1) .skip(1)
.take_while(|it| matches!(it.kind(), SyntaxKind::PAREN_TYPE | SyntaxKind::FOR_TYPE)) .take_while(|it| matches!(it.kind(), SyntaxKind::PAREN_TYPE | SyntaxKind::FOR_TYPE))
.find_map(ast::ForType::cast); .find_map(ast::ForType::cast)
.and_then(|it| it.for_binder());
let param_list = func.param_list()?; let param_list = func.param_list()?;
let generic_param_list = parent_for_type.as_ref().and_then(|it| it.generic_param_list()); let generic_param_list = parent_for_binder.as_ref().and_then(|it| it.generic_param_list());
let ret_type = func.ret_type(); let ret_type = func.ret_type();
let for_kw = parent_for_type.as_ref().and_then(|it| it.for_token()); let for_kw = parent_for_binder.as_ref().and_then(|it| it.for_token());
hints_( hints_(
acc, acc,
ctx, ctx,
@ -143,15 +144,16 @@ pub(super) fn fn_path_hints(
// FIXME: Support general path types // FIXME: Support general path types
let (param_list, ret_type) = func.path().as_ref().and_then(path_as_fn)?; let (param_list, ret_type) = func.path().as_ref().and_then(path_as_fn)?;
let parent_for_type = func let parent_for_binder = func
.syntax() .syntax()
.ancestors() .ancestors()
.skip(1) .skip(1)
.take_while(|it| matches!(it.kind(), SyntaxKind::PAREN_TYPE | SyntaxKind::FOR_TYPE)) .take_while(|it| matches!(it.kind(), SyntaxKind::PAREN_TYPE | SyntaxKind::FOR_TYPE))
.find_map(ast::ForType::cast); .find_map(ast::ForType::cast)
.and_then(|it| it.for_binder());
let generic_param_list = parent_for_type.as_ref().and_then(|it| it.generic_param_list()); let generic_param_list = parent_for_binder.as_ref().and_then(|it| it.generic_param_list());
let for_kw = parent_for_type.as_ref().and_then(|it| it.for_token()); let for_kw = parent_for_binder.as_ref().and_then(|it| it.for_token());
hints_( hints_(
acc, acc,
ctx, ctx,

View File

@ -572,9 +572,7 @@ fn closure_expr(p: &mut Parser<'_>) -> CompletedMarker {
// test closure_binder // test closure_binder
// fn main() { for<'a> || (); } // fn main() { for<'a> || (); }
if p.at(T![for]) { if p.at(T![for]) {
let b = p.start();
types::for_binder(p); types::for_binder(p);
b.complete(p, CLOSURE_BINDER);
} }
// test const_closure // test const_closure
// fn main() { let cl = const || _ = 0; } // fn main() { let cl = const || _ = 0; }

View File

@ -13,7 +13,7 @@ pub(super) fn opt_generic_param_list(p: &mut Parser<'_>) {
// test_err generic_param_list_recover // test_err generic_param_list_recover
// fn f<T: Clone,, U:, V>() {} // fn f<T: Clone,, U:, V>() {}
fn generic_param_list(p: &mut Parser<'_>) { pub(super) fn generic_param_list(p: &mut Parser<'_>) {
assert!(p.at(T![<])); assert!(p.at(T![<]));
let m = p.start(); let m = p.start();
delimited( delimited(
@ -147,7 +147,15 @@ fn type_bound(p: &mut Parser<'_>) -> bool {
let has_paren = p.eat(T!['(']); let has_paren = p.eat(T!['(']);
match p.current() { match p.current() {
LIFETIME_IDENT => lifetime(p), LIFETIME_IDENT => lifetime(p),
T![for] => types::for_type(p, false), // test for_binder_bound
// fn foo<T: for<'a> [const] async Trait>() {}
T![for] => {
types::for_binder(p);
if path_type_bound(p).is_err() {
m.abandon(p);
return false;
}
}
// test precise_capturing // test precise_capturing
// fn captures<'a: 'a, 'b: 'b, T>() -> impl Sized + use<'b, T, Self> {} // fn captures<'a: 'a, 'b: 'b, T>() -> impl Sized + use<'b, T, Self> {}
@ -180,44 +188,8 @@ fn type_bound(p: &mut Parser<'_>) -> bool {
p.bump_any(); p.bump_any();
types::for_type(p, false) types::for_type(p, false)
} }
current => { _ => {
match current { if path_type_bound(p).is_err() {
T![?] => p.bump_any(),
T![~] => {
p.bump_any();
p.expect(T![const]);
}
T!['['] => {
p.bump_any();
p.expect(T![const]);
p.expect(T![']']);
}
// test const_trait_bound
// const fn foo(_: impl const Trait) {}
T![const] => {
p.bump_any();
}
// test async_trait_bound
// fn async_foo(_: impl async Fn(&i32)) {}
T![async] => {
p.bump_any();
}
_ => (),
}
if paths::is_use_path_start(p) {
types::path_type_bounds(p, false);
// test_err type_bounds_macro_call_recovery
// fn foo<T: T![], T: T!, T: T!{}>() -> Box<T! + T!{}> {}
if p.at(T![!]) {
let m = p.start();
p.bump(T![!]);
p.error("unexpected `!` in type path, macro calls are not allowed here");
if p.at_ts(TokenSet::new(&[T!['{'], T!['['], T!['(']])) {
items::token_tree(p);
}
m.complete(p, ERROR);
}
} else {
m.abandon(p); m.abandon(p);
return false; return false;
} }
@ -231,6 +203,43 @@ fn type_bound(p: &mut Parser<'_>) -> bool {
true true
} }
fn path_type_bound(p: &mut Parser<'_>) -> Result<(), ()> {
if p.eat(T![~]) {
p.expect(T![const]);
} else if p.eat(T!['[']) {
// test maybe_const_trait_bound
// const fn foo(_: impl [const] Trait) {}
p.expect(T![const]);
p.expect(T![']']);
} else {
// test const_trait_bound
// const fn foo(_: impl const Trait) {}
p.eat(T![const]);
}
// test async_trait_bound
// fn async_foo(_: impl async Fn(&i32)) {}
p.eat(T![async]);
p.eat(T![?]);
if paths::is_use_path_start(p) {
types::path_type_bounds(p, false);
// test_err type_bounds_macro_call_recovery
// fn foo<T: T![], T: T!, T: T!{}>() -> Box<T! + T!{}> {}
if p.at(T![!]) {
let m = p.start();
p.bump(T![!]);
p.error("unexpected `!` in type path, macro calls are not allowed here");
if p.at_ts(TokenSet::new(&[T!['{'], T!['['], T!['(']])) {
items::token_tree(p);
}
m.complete(p, ERROR);
}
Ok(())
} else {
Err(())
}
}
// test where_clause // test where_clause
// fn foo() // fn foo()
// where // where

View File

@ -249,13 +249,14 @@ fn fn_ptr_type(p: &mut Parser<'_>) {
} }
pub(super) fn for_binder(p: &mut Parser<'_>) { pub(super) fn for_binder(p: &mut Parser<'_>) {
assert!(p.at(T![for])); let m = p.start();
p.bump(T![for]); p.bump(T![for]);
if p.at(T![<]) { if p.at(T![<]) {
generic_params::opt_generic_param_list(p); generic_params::generic_param_list(p);
} else { } else {
p.error("expected `<`"); p.error("expected `<`");
} }
m.complete(p, FOR_BINDER);
} }
// test for_type // test for_type

View File

@ -185,7 +185,6 @@ pub enum SyntaxKind {
BREAK_EXPR, BREAK_EXPR,
CALL_EXPR, CALL_EXPR,
CAST_EXPR, CAST_EXPR,
CLOSURE_BINDER,
CLOSURE_EXPR, CLOSURE_EXPR,
CONST, CONST,
CONST_ARG, CONST_ARG,
@ -203,6 +202,7 @@ pub enum SyntaxKind {
FN_PTR_TYPE, FN_PTR_TYPE,
FORMAT_ARGS_ARG, FORMAT_ARGS_ARG,
FORMAT_ARGS_EXPR, FORMAT_ARGS_EXPR,
FOR_BINDER,
FOR_EXPR, FOR_EXPR,
FOR_TYPE, FOR_TYPE,
GENERIC_ARG_LIST, GENERIC_ARG_LIST,
@ -358,7 +358,6 @@ impl SyntaxKind {
| BREAK_EXPR | BREAK_EXPR
| CALL_EXPR | CALL_EXPR
| CAST_EXPR | CAST_EXPR
| CLOSURE_BINDER
| CLOSURE_EXPR | CLOSURE_EXPR
| CONST | CONST
| CONST_ARG | CONST_ARG
@ -376,6 +375,7 @@ impl SyntaxKind {
| FN_PTR_TYPE | FN_PTR_TYPE
| FORMAT_ARGS_ARG | FORMAT_ARGS_ARG
| FORMAT_ARGS_EXPR | FORMAT_ARGS_EXPR
| FOR_BINDER
| FOR_EXPR | FOR_EXPR
| FOR_TYPE | FOR_TYPE
| GENERIC_ARG_LIST | GENERIC_ARG_LIST

View File

@ -253,6 +253,10 @@ mod ok {
run_and_expect_no_errors("test_data/parser/inline/ok/fn_pointer_unnamed_arg.rs"); run_and_expect_no_errors("test_data/parser/inline/ok/fn_pointer_unnamed_arg.rs");
} }
#[test] #[test]
fn for_binder_bound() {
run_and_expect_no_errors("test_data/parser/inline/ok/for_binder_bound.rs");
}
#[test]
fn for_expr() { run_and_expect_no_errors("test_data/parser/inline/ok/for_expr.rs"); } fn for_expr() { run_and_expect_no_errors("test_data/parser/inline/ok/for_expr.rs"); }
#[test] #[test]
fn for_range_from() { fn for_range_from() {
@ -402,6 +406,10 @@ mod ok {
#[test] #[test]
fn match_guard() { run_and_expect_no_errors("test_data/parser/inline/ok/match_guard.rs"); } fn match_guard() { run_and_expect_no_errors("test_data/parser/inline/ok/match_guard.rs"); }
#[test] #[test]
fn maybe_const_trait_bound() {
run_and_expect_no_errors("test_data/parser/inline/ok/maybe_const_trait_bound.rs");
}
#[test]
fn metas() { run_and_expect_no_errors("test_data/parser/inline/ok/metas.rs"); } fn metas() { run_and_expect_no_errors("test_data/parser/inline/ok/metas.rs"); }
#[test] #[test]
fn method_call_expr() { fn method_call_expr() {

View File

@ -37,7 +37,7 @@ SOURCE_FILE
WHITESPACE " " WHITESPACE " "
TYPE_BOUND TYPE_BOUND
L_PAREN "(" L_PAREN "("
FOR_TYPE FOR_BINDER
FOR_KW "for" FOR_KW "for"
GENERIC_PARAM_LIST GENERIC_PARAM_LIST
L_ANGLE "<" L_ANGLE "<"
@ -45,18 +45,18 @@ SOURCE_FILE
LIFETIME LIFETIME
LIFETIME_IDENT "'a" LIFETIME_IDENT "'a"
R_ANGLE ">" R_ANGLE ">"
WHITESPACE " " WHITESPACE " "
PATH_TYPE PATH_TYPE
PATH PATH
PATH_SEGMENT PATH_SEGMENT
NAME_REF NAME_REF
IDENT "Trait" IDENT "Trait"
GENERIC_ARG_LIST GENERIC_ARG_LIST
L_ANGLE "<" L_ANGLE "<"
LIFETIME_ARG LIFETIME_ARG
LIFETIME LIFETIME
LIFETIME_IDENT "'a" LIFETIME_IDENT "'a"
R_ANGLE ">" R_ANGLE ">"
R_PAREN ")" R_PAREN ")"
R_ANGLE ">" R_ANGLE ">"
PARAM_LIST PARAM_LIST
@ -124,7 +124,7 @@ SOURCE_FILE
WHITESPACE " " WHITESPACE " "
TYPE_BOUND TYPE_BOUND
L_PAREN "(" L_PAREN "("
FOR_TYPE FOR_BINDER
FOR_KW "for" FOR_KW "for"
GENERIC_PARAM_LIST GENERIC_PARAM_LIST
L_ANGLE "<" L_ANGLE "<"
@ -132,18 +132,18 @@ SOURCE_FILE
LIFETIME LIFETIME
LIFETIME_IDENT "'a" LIFETIME_IDENT "'a"
R_ANGLE ">" R_ANGLE ">"
WHITESPACE " " WHITESPACE " "
PATH_TYPE PATH_TYPE
PATH PATH
PATH_SEGMENT PATH_SEGMENT
NAME_REF NAME_REF
IDENT "Trait" IDENT "Trait"
GENERIC_ARG_LIST GENERIC_ARG_LIST
L_ANGLE "<" L_ANGLE "<"
LIFETIME_ARG LIFETIME_ARG
LIFETIME LIFETIME
LIFETIME_IDENT "'a" LIFETIME_IDENT "'a"
R_ANGLE ">" R_ANGLE ">"
R_PAREN ")" R_PAREN ")"
ERROR ERROR
R_ANGLE ">" R_ANGLE ">"
@ -186,7 +186,7 @@ SOURCE_FILE
TUPLE_EXPR TUPLE_EXPR
L_PAREN "(" L_PAREN "("
CLOSURE_EXPR CLOSURE_EXPR
CLOSURE_BINDER FOR_BINDER
FOR_KW "for" FOR_KW "for"
GENERIC_PARAM_LIST GENERIC_PARAM_LIST
L_ANGLE "<" L_ANGLE "<"
@ -243,13 +243,14 @@ SOURCE_FILE
PAREN_TYPE PAREN_TYPE
L_PAREN "(" L_PAREN "("
FOR_TYPE FOR_TYPE
FOR_KW "for" FOR_BINDER
GENERIC_PARAM_LIST FOR_KW "for"
L_ANGLE "<" GENERIC_PARAM_LIST
LIFETIME_PARAM L_ANGLE "<"
LIFETIME LIFETIME_PARAM
LIFETIME_IDENT "'a" LIFETIME
R_ANGLE ">" LIFETIME_IDENT "'a"
R_ANGLE ">"
WHITESPACE " " WHITESPACE " "
PATH_TYPE PATH_TYPE
PATH PATH

View File

@ -12,13 +12,14 @@ SOURCE_FILE
WHERE_KW "where" WHERE_KW "where"
WHITESPACE " " WHITESPACE " "
WHERE_PRED WHERE_PRED
FOR_KW "for" FOR_BINDER
GENERIC_PARAM_LIST FOR_KW "for"
L_ANGLE "<" GENERIC_PARAM_LIST
LIFETIME_PARAM L_ANGLE "<"
LIFETIME LIFETIME_PARAM
LIFETIME_IDENT "'a" LIFETIME
R_ANGLE ">" LIFETIME_IDENT "'a"
R_ANGLE ">"
WHITESPACE "\n" WHITESPACE "\n"
BLOCK_EXPR BLOCK_EXPR
STMT_LIST STMT_LIST

View File

@ -8,13 +8,14 @@ SOURCE_FILE
EQ "=" EQ "="
WHITESPACE " " WHITESPACE " "
FOR_TYPE FOR_TYPE
FOR_KW "for" FOR_BINDER
GENERIC_PARAM_LIST FOR_KW "for"
L_ANGLE "<" GENERIC_PARAM_LIST
LIFETIME_PARAM L_ANGLE "<"
LIFETIME LIFETIME_PARAM
LIFETIME_IDENT "'a" LIFETIME
R_ANGLE ">" LIFETIME_IDENT "'a"
R_ANGLE ">"
WHITESPACE " " WHITESPACE " "
REF_TYPE REF_TYPE
AMP "&" AMP "&"
@ -37,13 +38,14 @@ SOURCE_FILE
EQ "=" EQ "="
WHITESPACE " " WHITESPACE " "
FOR_TYPE FOR_TYPE
FOR_KW "for" FOR_BINDER
GENERIC_PARAM_LIST FOR_KW "for"
L_ANGLE "<" GENERIC_PARAM_LIST
LIFETIME_PARAM L_ANGLE "<"
LIFETIME LIFETIME_PARAM
LIFETIME_IDENT "'a" LIFETIME
R_ANGLE ">" LIFETIME_IDENT "'a"
R_ANGLE ">"
WHITESPACE " " WHITESPACE " "
TUPLE_TYPE TUPLE_TYPE
L_PAREN "(" L_PAREN "("
@ -70,13 +72,14 @@ SOURCE_FILE
EQ "=" EQ "="
WHITESPACE " " WHITESPACE " "
FOR_TYPE FOR_TYPE
FOR_KW "for" FOR_BINDER
GENERIC_PARAM_LIST FOR_KW "for"
L_ANGLE "<" GENERIC_PARAM_LIST
LIFETIME_PARAM L_ANGLE "<"
LIFETIME LIFETIME_PARAM
LIFETIME_IDENT "'a" LIFETIME
R_ANGLE ">" LIFETIME_IDENT "'a"
R_ANGLE ">"
WHITESPACE " " WHITESPACE " "
SLICE_TYPE SLICE_TYPE
L_BRACK "[" L_BRACK "["
@ -97,22 +100,24 @@ SOURCE_FILE
EQ "=" EQ "="
WHITESPACE " " WHITESPACE " "
FOR_TYPE FOR_TYPE
FOR_KW "for" FOR_BINDER
GENERIC_PARAM_LIST
L_ANGLE "<"
LIFETIME_PARAM
LIFETIME
LIFETIME_IDENT "'a"
R_ANGLE ">"
WHITESPACE " "
FOR_TYPE
FOR_KW "for" FOR_KW "for"
GENERIC_PARAM_LIST GENERIC_PARAM_LIST
L_ANGLE "<" L_ANGLE "<"
LIFETIME_PARAM LIFETIME_PARAM
LIFETIME LIFETIME
LIFETIME_IDENT "'b" LIFETIME_IDENT "'a"
R_ANGLE ">" R_ANGLE ">"
WHITESPACE " "
FOR_TYPE
FOR_BINDER
FOR_KW "for"
GENERIC_PARAM_LIST
L_ANGLE "<"
LIFETIME_PARAM
LIFETIME
LIFETIME_IDENT "'b"
R_ANGLE ">"
WHITESPACE " " WHITESPACE " "
FN_PTR_TYPE FN_PTR_TYPE
FN_KW "fn" FN_KW "fn"
@ -164,31 +169,34 @@ SOURCE_FILE
WHERE_KW "where" WHERE_KW "where"
WHITESPACE "\n " WHITESPACE "\n "
WHERE_PRED WHERE_PRED
FOR_KW "for" FOR_BINDER
GENERIC_PARAM_LIST
L_ANGLE "<"
LIFETIME_PARAM
LIFETIME
LIFETIME_IDENT "'a"
R_ANGLE ">"
WHITESPACE " "
FOR_TYPE
FOR_KW "for" FOR_KW "for"
GENERIC_PARAM_LIST GENERIC_PARAM_LIST
L_ANGLE "<" L_ANGLE "<"
LIFETIME_PARAM LIFETIME_PARAM
LIFETIME LIFETIME
LIFETIME_IDENT "'b" LIFETIME_IDENT "'a"
R_ANGLE ">" R_ANGLE ">"
WHITESPACE " " WHITESPACE " "
FOR_TYPE FOR_TYPE
FOR_BINDER
FOR_KW "for" FOR_KW "for"
GENERIC_PARAM_LIST GENERIC_PARAM_LIST
L_ANGLE "<" L_ANGLE "<"
LIFETIME_PARAM LIFETIME_PARAM
LIFETIME LIFETIME
LIFETIME_IDENT "'c" LIFETIME_IDENT "'b"
R_ANGLE ">" R_ANGLE ">"
WHITESPACE " "
FOR_TYPE
FOR_BINDER
FOR_KW "for"
GENERIC_PARAM_LIST
L_ANGLE "<"
LIFETIME_PARAM
LIFETIME
LIFETIME_IDENT "'c"
R_ANGLE ">"
WHITESPACE " " WHITESPACE " "
FN_PTR_TYPE FN_PTR_TYPE
FN_KW "fn" FN_KW "fn"

View File

@ -14,7 +14,7 @@ SOURCE_FILE
WHITESPACE " " WHITESPACE " "
EXPR_STMT EXPR_STMT
CLOSURE_EXPR CLOSURE_EXPR
CLOSURE_BINDER FOR_BINDER
FOR_KW "for" FOR_KW "for"
GENERIC_PARAM_LIST GENERIC_PARAM_LIST
L_ANGLE "<" L_ANGLE "<"

View File

@ -103,7 +103,7 @@ SOURCE_FILE
WHITESPACE " " WHITESPACE " "
TYPE_BOUND_LIST TYPE_BOUND_LIST
TYPE_BOUND TYPE_BOUND
FOR_TYPE FOR_BINDER
FOR_KW "for" FOR_KW "for"
GENERIC_PARAM_LIST GENERIC_PARAM_LIST
L_ANGLE "<" L_ANGLE "<"
@ -111,12 +111,12 @@ SOURCE_FILE
LIFETIME LIFETIME
LIFETIME_IDENT "'a" LIFETIME_IDENT "'a"
R_ANGLE ">" R_ANGLE ">"
WHITESPACE " " WHITESPACE " "
PATH_TYPE PATH_TYPE
PATH PATH
PATH_SEGMENT PATH_SEGMENT
NAME_REF NAME_REF
IDENT "Path" IDENT "Path"
SEMICOLON ";" SEMICOLON ";"
WHITESPACE "\n" WHITESPACE "\n"
TYPE_ALIAS TYPE_ALIAS

View File

@ -0,0 +1,45 @@
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
FOR_BINDER
FOR_KW "for"
GENERIC_PARAM_LIST
L_ANGLE "<"
LIFETIME_PARAM
LIFETIME
LIFETIME_IDENT "'a"
R_ANGLE ">"
WHITESPACE " "
L_BRACK "["
CONST_KW "const"
R_BRACK "]"
WHITESPACE " "
ASYNC_KW "async"
WHITESPACE " "
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "Trait"
R_ANGLE ">"
PARAM_LIST
L_PAREN "("
R_PAREN ")"
WHITESPACE " "
BLOCK_EXPR
STMT_LIST
L_CURLY "{"
R_CURLY "}"
WHITESPACE "\n"

View File

@ -0,0 +1 @@
fn foo<T: for<'a> [const] async Trait>() {}

View File

@ -8,13 +8,14 @@ SOURCE_FILE
EQ "=" EQ "="
WHITESPACE " " WHITESPACE " "
FOR_TYPE FOR_TYPE
FOR_KW "for" FOR_BINDER
GENERIC_PARAM_LIST FOR_KW "for"
L_ANGLE "<" GENERIC_PARAM_LIST
LIFETIME_PARAM L_ANGLE "<"
LIFETIME LIFETIME_PARAM
LIFETIME_IDENT "'a" LIFETIME
R_ANGLE ">" LIFETIME_IDENT "'a"
R_ANGLE ">"
WHITESPACE " " WHITESPACE " "
FN_PTR_TYPE FN_PTR_TYPE
FN_KW "fn" FN_KW "fn"
@ -39,13 +40,14 @@ SOURCE_FILE
EQ "=" EQ "="
WHITESPACE " " WHITESPACE " "
FOR_TYPE FOR_TYPE
FOR_KW "for" FOR_BINDER
GENERIC_PARAM_LIST FOR_KW "for"
L_ANGLE "<" GENERIC_PARAM_LIST
LIFETIME_PARAM L_ANGLE "<"
LIFETIME LIFETIME_PARAM
LIFETIME_IDENT "'a" LIFETIME
R_ANGLE ">" LIFETIME_IDENT "'a"
R_ANGLE ">"
WHITESPACE " " WHITESPACE " "
FN_PTR_TYPE FN_PTR_TYPE
UNSAFE_KW "unsafe" UNSAFE_KW "unsafe"
@ -86,13 +88,14 @@ SOURCE_FILE
EQ "=" EQ "="
WHITESPACE " " WHITESPACE " "
FOR_TYPE FOR_TYPE
FOR_KW "for" FOR_BINDER
GENERIC_PARAM_LIST FOR_KW "for"
L_ANGLE "<" GENERIC_PARAM_LIST
LIFETIME_PARAM L_ANGLE "<"
LIFETIME LIFETIME_PARAM
LIFETIME_IDENT "'a" LIFETIME
R_ANGLE ">" LIFETIME_IDENT "'a"
R_ANGLE ">"
WHITESPACE " " WHITESPACE " "
PATH_TYPE PATH_TYPE
PATH PATH

View File

@ -202,7 +202,7 @@ SOURCE_FILE
WHITESPACE "\n " WHITESPACE "\n "
EXPR_STMT EXPR_STMT
CLOSURE_EXPR CLOSURE_EXPR
CLOSURE_BINDER FOR_BINDER
FOR_KW "for" FOR_KW "for"
GENERIC_PARAM_LIST GENERIC_PARAM_LIST
L_ANGLE "<" L_ANGLE "<"
@ -223,7 +223,7 @@ SOURCE_FILE
WHITESPACE "\n " WHITESPACE "\n "
EXPR_STMT EXPR_STMT
CLOSURE_EXPR CLOSURE_EXPR
CLOSURE_BINDER FOR_BINDER
FOR_KW "for" FOR_KW "for"
GENERIC_PARAM_LIST GENERIC_PARAM_LIST
L_ANGLE "<" L_ANGLE "<"

View File

@ -0,0 +1,36 @@
SOURCE_FILE
FN
CONST_KW "const"
WHITESPACE " "
FN_KW "fn"
WHITESPACE " "
NAME
IDENT "foo"
PARAM_LIST
L_PAREN "("
PARAM
WILDCARD_PAT
UNDERSCORE "_"
COLON ":"
WHITESPACE " "
IMPL_TRAIT_TYPE
IMPL_KW "impl"
WHITESPACE " "
TYPE_BOUND_LIST
TYPE_BOUND
L_BRACK "["
CONST_KW "const"
R_BRACK "]"
WHITESPACE " "
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "Trait"
R_PAREN ")"
WHITESPACE " "
BLOCK_EXPR
STMT_LIST
L_CURLY "{"
R_CURLY "}"
WHITESPACE "\n"

View File

@ -0,0 +1 @@
const fn foo(_: impl [const] Trait) {}

View File

@ -11,13 +11,14 @@ SOURCE_FILE
TYPE_BOUND_LIST TYPE_BOUND_LIST
TYPE_BOUND TYPE_BOUND
FOR_TYPE FOR_TYPE
FOR_KW "for" FOR_BINDER
GENERIC_PARAM_LIST FOR_KW "for"
L_ANGLE "<" GENERIC_PARAM_LIST
LIFETIME_PARAM L_ANGLE "<"
LIFETIME LIFETIME_PARAM
LIFETIME_IDENT "'a" LIFETIME
R_ANGLE ">" LIFETIME_IDENT "'a"
R_ANGLE ">"
WHITESPACE " " WHITESPACE " "
PATH_TYPE PATH_TYPE
PATH PATH

View File

@ -29,10 +29,11 @@ SOURCE_FILE
TYPE_BOUND TYPE_BOUND
QUESTION "?" QUESTION "?"
FOR_TYPE FOR_TYPE
FOR_KW "for" FOR_BINDER
GENERIC_PARAM_LIST FOR_KW "for"
L_ANGLE "<" GENERIC_PARAM_LIST
R_ANGLE ">" L_ANGLE "<"
R_ANGLE ">"
WHITESPACE " " WHITESPACE " "
PATH_TYPE PATH_TYPE
PATH PATH

View File

@ -18,13 +18,14 @@ SOURCE_FILE
WHERE_KW "where" WHERE_KW "where"
WHITESPACE "\n " WHITESPACE "\n "
WHERE_PRED WHERE_PRED
FOR_KW "for" FOR_BINDER
GENERIC_PARAM_LIST FOR_KW "for"
L_ANGLE "<" GENERIC_PARAM_LIST
LIFETIME_PARAM L_ANGLE "<"
LIFETIME LIFETIME_PARAM
LIFETIME_IDENT "'a" LIFETIME
R_ANGLE ">" LIFETIME_IDENT "'a"
R_ANGLE ">"
WHITESPACE " " WHITESPACE " "
PATH_TYPE PATH_TYPE
PATH PATH

View File

@ -36,7 +36,7 @@ SOURCE_FILE
PLUS "+" PLUS "+"
WHITESPACE " " WHITESPACE " "
TYPE_BOUND TYPE_BOUND
FOR_TYPE FOR_BINDER
FOR_KW "for" FOR_KW "for"
GENERIC_PARAM_LIST GENERIC_PARAM_LIST
L_ANGLE "<" L_ANGLE "<"
@ -44,18 +44,18 @@ SOURCE_FILE
LIFETIME LIFETIME
LIFETIME_IDENT "'de" LIFETIME_IDENT "'de"
R_ANGLE ">" R_ANGLE ">"
WHITESPACE " " WHITESPACE " "
PATH_TYPE PATH_TYPE
PATH PATH
PATH_SEGMENT PATH_SEGMENT
NAME_REF NAME_REF
IDENT "Deserialize" IDENT "Deserialize"
GENERIC_ARG_LIST GENERIC_ARG_LIST
L_ANGLE "<" L_ANGLE "<"
LIFETIME_ARG LIFETIME_ARG
LIFETIME LIFETIME
LIFETIME_IDENT "'de" LIFETIME_IDENT "'de"
R_ANGLE ">" R_ANGLE ">"
WHITESPACE " " WHITESPACE " "
PLUS "+" PLUS "+"
WHITESPACE " " WHITESPACE " "

View File

@ -18,13 +18,14 @@ SOURCE_FILE
WHERE_KW "where" WHERE_KW "where"
WHITESPACE "\n " WHITESPACE "\n "
WHERE_PRED WHERE_PRED
FOR_KW "for" FOR_BINDER
GENERIC_PARAM_LIST FOR_KW "for"
L_ANGLE "<" GENERIC_PARAM_LIST
LIFETIME_PARAM L_ANGLE "<"
LIFETIME LIFETIME_PARAM
LIFETIME_IDENT "'a" LIFETIME
R_ANGLE ">" LIFETIME_IDENT "'a"
R_ANGLE ">"
WHITESPACE " " WHITESPACE " "
PATH_TYPE PATH_TYPE
PATH PATH
@ -81,13 +82,14 @@ SOURCE_FILE
WHERE_KW "where" WHERE_KW "where"
WHITESPACE "\n " WHITESPACE "\n "
WHERE_PRED WHERE_PRED
FOR_KW "for" FOR_BINDER
GENERIC_PARAM_LIST FOR_KW "for"
L_ANGLE "<" GENERIC_PARAM_LIST
LIFETIME_PARAM L_ANGLE "<"
LIFETIME LIFETIME_PARAM
LIFETIME_IDENT "'a" LIFETIME
R_ANGLE ">" LIFETIME_IDENT "'a"
R_ANGLE ">"
WHITESPACE " " WHITESPACE " "
REF_TYPE REF_TYPE
AMP "&" AMP "&"
@ -135,13 +137,14 @@ SOURCE_FILE
WHERE_KW "where" WHERE_KW "where"
WHITESPACE "\n " WHITESPACE "\n "
WHERE_PRED WHERE_PRED
FOR_KW "for" FOR_BINDER
GENERIC_PARAM_LIST FOR_KW "for"
L_ANGLE "<" GENERIC_PARAM_LIST
LIFETIME_PARAM L_ANGLE "<"
LIFETIME LIFETIME_PARAM
LIFETIME_IDENT "'a" LIFETIME
R_ANGLE ">" LIFETIME_IDENT "'a"
R_ANGLE ">"
WHITESPACE " " WHITESPACE " "
PAREN_TYPE PAREN_TYPE
L_PAREN "(" L_PAREN "("
@ -206,13 +209,14 @@ SOURCE_FILE
WHERE_KW "where" WHERE_KW "where"
WHITESPACE "\n " WHITESPACE "\n "
WHERE_PRED WHERE_PRED
FOR_KW "for" FOR_BINDER
GENERIC_PARAM_LIST FOR_KW "for"
L_ANGLE "<" GENERIC_PARAM_LIST
LIFETIME_PARAM L_ANGLE "<"
LIFETIME LIFETIME_PARAM
LIFETIME_IDENT "'a" LIFETIME
R_ANGLE ">" LIFETIME_IDENT "'a"
R_ANGLE ">"
WHITESPACE " " WHITESPACE " "
SLICE_TYPE SLICE_TYPE
L_BRACK "[" L_BRACK "["
@ -276,13 +280,14 @@ SOURCE_FILE
WHERE_KW "where" WHERE_KW "where"
WHITESPACE "\n " WHITESPACE "\n "
WHERE_PRED WHERE_PRED
FOR_KW "for" FOR_BINDER
GENERIC_PARAM_LIST FOR_KW "for"
L_ANGLE "<" GENERIC_PARAM_LIST
LIFETIME_PARAM L_ANGLE "<"
LIFETIME LIFETIME_PARAM
LIFETIME_IDENT "'a" LIFETIME
R_ANGLE ">" LIFETIME_IDENT "'a"
R_ANGLE ">"
WHITESPACE " " WHITESPACE " "
PATH_TYPE PATH_TYPE
PATH PATH
@ -349,22 +354,24 @@ SOURCE_FILE
WHERE_KW "where" WHERE_KW "where"
WHITESPACE "\n " WHITESPACE "\n "
WHERE_PRED WHERE_PRED
FOR_KW "for" FOR_BINDER
GENERIC_PARAM_LIST
L_ANGLE "<"
LIFETIME_PARAM
LIFETIME
LIFETIME_IDENT "'a"
R_ANGLE ">"
WHITESPACE " "
FOR_TYPE
FOR_KW "for" FOR_KW "for"
GENERIC_PARAM_LIST GENERIC_PARAM_LIST
L_ANGLE "<" L_ANGLE "<"
LIFETIME_PARAM LIFETIME_PARAM
LIFETIME LIFETIME
LIFETIME_IDENT "'b" LIFETIME_IDENT "'a"
R_ANGLE ">" R_ANGLE ">"
WHITESPACE " "
FOR_TYPE
FOR_BINDER
FOR_KW "for"
GENERIC_PARAM_LIST
L_ANGLE "<"
LIFETIME_PARAM
LIFETIME
LIFETIME_IDENT "'b"
R_ANGLE ">"
WHITESPACE " " WHITESPACE " "
FN_PTR_TYPE FN_PTR_TYPE
FN_KW "fn" FN_KW "fn"

View File

@ -101,7 +101,7 @@ WhereClause =
'where' predicates:(WherePred (',' WherePred)* ','?) 'where' predicates:(WherePred (',' WherePred)* ','?)
WherePred = WherePred =
('for' GenericParamList)? (Lifetime | Type) ':' TypeBoundList? ForBinder? (Lifetime | Type) ':' TypeBoundList?
//*************************// //*************************//
@ -534,10 +534,10 @@ FieldExpr =
Attr* Expr '.' NameRef Attr* Expr '.' NameRef
ClosureExpr = ClosureExpr =
Attr* ClosureBinder? 'const'? 'static'? 'async'? 'gen'? 'move'? ParamList RetType? Attr* ForBinder? 'const'? 'static'? 'async'? 'gen'? 'move'? ParamList RetType?
body:Expr body:Expr
ClosureBinder = ForBinder =
'for' GenericParamList 'for' GenericParamList
IfExpr = IfExpr =
@ -658,7 +658,7 @@ FnPtrType =
'const'? 'async'? 'unsafe'? Abi? 'fn' ParamList RetType? 'const'? 'async'? 'unsafe'? Abi? 'fn' ParamList RetType?
ForType = ForType =
'for' GenericParamList Type ForBinder Type
ImplTraitType = ImplTraitType =
'impl' TypeBoundList 'impl' TypeBoundList
@ -671,7 +671,7 @@ TypeBoundList =
TypeBound = TypeBound =
Lifetime Lifetime
| ('~' 'const' | '[' 'const' ']' | 'const')? 'async'? '?'? Type | ForBinder? ('~' 'const' | '[' 'const' ']' | 'const')? 'async'? '?'? Type
| 'use' UseBoundGenericArgs | 'use' UseBoundGenericArgs
UseBoundGenericArgs = UseBoundGenericArgs =

View File

@ -393,8 +393,7 @@ where
let pred = predicates.next().unwrap(); let pred = predicates.next().unwrap();
let mut bounds = pred.type_bound_list().unwrap().bounds(); let mut bounds = pred.type_bound_list().unwrap().bounds();
assert!(pred.for_token().is_none()); assert!(pred.for_binder().is_none());
assert!(pred.generic_param_list().is_none());
assert_eq!("T", pred.ty().unwrap().syntax().text().to_string()); assert_eq!("T", pred.ty().unwrap().syntax().text().to_string());
assert_bound("Clone", bounds.next()); assert_bound("Clone", bounds.next());
assert_bound("Copy", bounds.next()); assert_bound("Copy", bounds.next());
@ -432,8 +431,10 @@ where
let pred = predicates.next().unwrap(); let pred = predicates.next().unwrap();
let mut bounds = pred.type_bound_list().unwrap().bounds(); let mut bounds = pred.type_bound_list().unwrap().bounds();
assert!(pred.for_token().is_some()); assert_eq!(
assert_eq!("<'a>", pred.generic_param_list().unwrap().syntax().text().to_string()); "<'a>",
pred.for_binder().unwrap().generic_param_list().unwrap().syntax().text().to_string()
);
assert_eq!("F", pred.ty().unwrap().syntax().text().to_string()); assert_eq!("F", pred.ty().unwrap().syntax().text().to_string());
assert_bound("Fn(&'a str)", bounds.next()); assert_bound("Fn(&'a str)", bounds.next());
} }

View File

@ -377,22 +377,13 @@ impl CastExpr {
#[inline] #[inline]
pub fn as_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![as]) } pub fn as_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![as]) }
} }
pub struct ClosureBinder {
pub(crate) syntax: SyntaxNode,
}
impl ClosureBinder {
#[inline]
pub fn generic_param_list(&self) -> Option<GenericParamList> { support::child(&self.syntax) }
#[inline]
pub fn for_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![for]) }
}
pub struct ClosureExpr { pub struct ClosureExpr {
pub(crate) syntax: SyntaxNode, pub(crate) syntax: SyntaxNode,
} }
impl ast::HasAttrs for ClosureExpr {} impl ast::HasAttrs for ClosureExpr {}
impl ClosureExpr { impl ClosureExpr {
#[inline] #[inline]
pub fn closure_binder(&self) -> Option<ClosureBinder> { support::child(&self.syntax) } pub fn for_binder(&self) -> Option<ForBinder> { support::child(&self.syntax) }
#[inline] #[inline]
pub fn param_list(&self) -> Option<ParamList> { support::child(&self.syntax) } pub fn param_list(&self) -> Option<ParamList> { support::child(&self.syntax) }
#[inline] #[inline]
@ -615,6 +606,15 @@ impl FnPtrType {
#[inline] #[inline]
pub fn unsafe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![unsafe]) } pub fn unsafe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![unsafe]) }
} }
pub struct ForBinder {
pub(crate) syntax: SyntaxNode,
}
impl ForBinder {
#[inline]
pub fn generic_param_list(&self) -> Option<GenericParamList> { support::child(&self.syntax) }
#[inline]
pub fn for_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![for]) }
}
pub struct ForExpr { pub struct ForExpr {
pub(crate) syntax: SyntaxNode, pub(crate) syntax: SyntaxNode,
} }
@ -632,11 +632,9 @@ pub struct ForType {
} }
impl ForType { impl ForType {
#[inline] #[inline]
pub fn generic_param_list(&self) -> Option<GenericParamList> { support::child(&self.syntax) } pub fn for_binder(&self) -> Option<ForBinder> { support::child(&self.syntax) }
#[inline] #[inline]
pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) } pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
#[inline]
pub fn for_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![for]) }
} }
pub struct FormatArgsArg { pub struct FormatArgsArg {
pub(crate) syntax: SyntaxNode, pub(crate) syntax: SyntaxNode,
@ -1765,6 +1763,8 @@ pub struct TypeBound {
pub(crate) syntax: SyntaxNode, pub(crate) syntax: SyntaxNode,
} }
impl TypeBound { impl TypeBound {
#[inline]
pub fn for_binder(&self) -> Option<ForBinder> { support::child(&self.syntax) }
#[inline] #[inline]
pub fn lifetime(&self) -> Option<Lifetime> { support::child(&self.syntax) } pub fn lifetime(&self) -> Option<Lifetime> { support::child(&self.syntax) }
#[inline] #[inline]
@ -1938,13 +1938,11 @@ pub struct WherePred {
impl ast::HasTypeBounds for WherePred {} impl ast::HasTypeBounds for WherePred {}
impl WherePred { impl WherePred {
#[inline] #[inline]
pub fn generic_param_list(&self) -> Option<GenericParamList> { support::child(&self.syntax) } pub fn for_binder(&self) -> Option<ForBinder> { support::child(&self.syntax) }
#[inline] #[inline]
pub fn lifetime(&self) -> Option<Lifetime> { support::child(&self.syntax) } pub fn lifetime(&self) -> Option<Lifetime> { support::child(&self.syntax) }
#[inline] #[inline]
pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) } pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
#[inline]
pub fn for_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![for]) }
} }
pub struct WhileExpr { pub struct WhileExpr {
pub(crate) syntax: SyntaxNode, pub(crate) syntax: SyntaxNode,
@ -3239,42 +3237,6 @@ impl fmt::Debug for CastExpr {
f.debug_struct("CastExpr").field("syntax", &self.syntax).finish() f.debug_struct("CastExpr").field("syntax", &self.syntax).finish()
} }
} }
impl AstNode for ClosureBinder {
#[inline]
fn kind() -> SyntaxKind
where
Self: Sized,
{
CLOSURE_BINDER
}
#[inline]
fn can_cast(kind: SyntaxKind) -> bool { kind == CLOSURE_BINDER }
#[inline]
fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
} else {
None
}
}
#[inline]
fn syntax(&self) -> &SyntaxNode { &self.syntax }
}
impl hash::Hash for ClosureBinder {
fn hash<H: hash::Hasher>(&self, state: &mut H) { self.syntax.hash(state); }
}
impl Eq for ClosureBinder {}
impl PartialEq for ClosureBinder {
fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax }
}
impl Clone for ClosureBinder {
fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } }
}
impl fmt::Debug for ClosureBinder {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("ClosureBinder").field("syntax", &self.syntax).finish()
}
}
impl AstNode for ClosureExpr { impl AstNode for ClosureExpr {
#[inline] #[inline]
fn kind() -> SyntaxKind fn kind() -> SyntaxKind
@ -3815,6 +3777,42 @@ impl fmt::Debug for FnPtrType {
f.debug_struct("FnPtrType").field("syntax", &self.syntax).finish() f.debug_struct("FnPtrType").field("syntax", &self.syntax).finish()
} }
} }
impl AstNode for ForBinder {
#[inline]
fn kind() -> SyntaxKind
where
Self: Sized,
{
FOR_BINDER
}
#[inline]
fn can_cast(kind: SyntaxKind) -> bool { kind == FOR_BINDER }
#[inline]
fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
} else {
None
}
}
#[inline]
fn syntax(&self) -> &SyntaxNode { &self.syntax }
}
impl hash::Hash for ForBinder {
fn hash<H: hash::Hasher>(&self, state: &mut H) { self.syntax.hash(state); }
}
impl Eq for ForBinder {}
impl PartialEq for ForBinder {
fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax }
}
impl Clone for ForBinder {
fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } }
}
impl fmt::Debug for ForBinder {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("ForBinder").field("syntax", &self.syntax).finish()
}
}
impl AstNode for ForExpr { impl AstNode for ForExpr {
#[inline] #[inline]
fn kind() -> SyntaxKind fn kind() -> SyntaxKind
@ -10146,11 +10144,6 @@ impl std::fmt::Display for CastExpr {
std::fmt::Display::fmt(self.syntax(), f) std::fmt::Display::fmt(self.syntax(), f)
} }
} }
impl std::fmt::Display for ClosureBinder {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self.syntax(), f)
}
}
impl std::fmt::Display for ClosureExpr { impl std::fmt::Display for ClosureExpr {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self.syntax(), f) std::fmt::Display::fmt(self.syntax(), f)
@ -10226,6 +10219,11 @@ impl std::fmt::Display for FnPtrType {
std::fmt::Display::fmt(self.syntax(), f) std::fmt::Display::fmt(self.syntax(), f)
} }
} }
impl std::fmt::Display for ForBinder {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self.syntax(), f)
}
}
impl std::fmt::Display for ForExpr { impl std::fmt::Display for ForExpr {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self.syntax(), f) std::fmt::Display::fmt(self.syntax(), f)

View File

@ -805,9 +805,7 @@ impl ast::SelfParam {
#[derive(Clone, Debug, PartialEq, Eq, Hash)] #[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub enum TypeBoundKind { pub enum TypeBoundKind {
/// Trait /// Trait
PathType(ast::PathType), PathType(Option<ast::ForBinder>, ast::PathType),
/// for<'a> ...
ForType(ast::ForType),
/// use /// use
Use(ast::UseBoundGenericArgs), Use(ast::UseBoundGenericArgs),
/// 'a /// 'a
@ -817,9 +815,7 @@ pub enum TypeBoundKind {
impl ast::TypeBound { impl ast::TypeBound {
pub fn kind(&self) -> TypeBoundKind { pub fn kind(&self) -> TypeBoundKind {
if let Some(path_type) = support::children(self.syntax()).next() { if let Some(path_type) = support::children(self.syntax()).next() {
TypeBoundKind::PathType(path_type) TypeBoundKind::PathType(self.for_binder(), path_type)
} else if let Some(for_type) = support::children(self.syntax()).next() {
TypeBoundKind::ForType(for_type)
} else if let Some(args) = self.use_bound_generic_args() { } else if let Some(args) = self.use_bound_generic_args() {
TypeBoundKind::Use(args) TypeBoundKind::Use(args)
} else if let Some(lifetime) = self.lifetime() { } else if let Some(lifetime) = self.lifetime() {