Parse `for<'a> [const]`
And also refactor parsing of HRTB.
diff --git a/crates/hir-def/src/expr_store/lower.rs b/crates/hir-def/src/expr_store/lower.rs
index 4e87774..7990a64 100644
--- a/crates/hir-def/src/expr_store/lower.rs
+++ b/crates/hir-def/src/expr_store/lower.rs
@@ -960,37 +960,28 @@
impl_trait_lower_fn: ImplTraitLowerFn<'_>,
) -> TypeBound {
match node.kind() {
- ast::TypeBoundKind::PathType(path_type) => {
- let m = match node.question_mark_token() {
- 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() {
+ ast::TypeBoundKind::PathType(binder, path_type) => {
+ let binder = match binder.and_then(|it| it.generic_param_list()) {
Some(gpl) => gpl
.lifetime_params()
.flat_map(|lp| lp.lifetime().map(|lt| Name::new_lifetime(<.text())))
.collect(),
None => ThinVec::default(),
};
- let path = for_type.ty().and_then(|ty| match &ty {
- ast::Type::PathType(path_type) => {
- self.lower_path_type(path_type, impl_trait_lower_fn).map(|p| (p, ty))
- }
- _ => None,
- });
- match path {
- Some((p, ty)) => {
- TypeBound::ForLifetime(lt_refs, self.alloc_path(p, AstPtr::new(&ty)))
- }
- None => TypeBound::Error,
- }
+ let m = match node.question_mark_token() {
+ Some(_) => TraitBoundModifier::Maybe,
+ None => TraitBoundModifier::None,
+ };
+ self.lower_path_type(&path_type, impl_trait_lower_fn)
+ .map(|p| {
+ let path = self.alloc_path(p, AstPtr::new(&path_type).upcast());
+ if binder.is_empty() {
+ TypeBound::Path(path, m)
+ } else {
+ TypeBound::ForLifetime(binder, path)
+ }
+ })
+ .unwrap_or(TypeBound::Error)
}
ast::TypeBoundKind::Use(gal) => TypeBound::Use(
gal.use_bound_generic_args()
diff --git a/crates/hir-def/src/expr_store/lower/generics.rs b/crates/hir-def/src/expr_store/lower/generics.rs
index 02a1d27..c570df4 100644
--- a/crates/hir-def/src/expr_store/lower/generics.rs
+++ b/crates/hir-def/src/expr_store/lower/generics.rs
@@ -180,17 +180,18 @@
continue;
};
- let lifetimes: Option<Box<_>> = pred.generic_param_list().map(|param_list| {
- // Higher-Ranked Trait Bounds
- param_list
- .lifetime_params()
- .map(|lifetime_param| {
- lifetime_param
- .lifetime()
- .map_or_else(Name::missing, |lt| Name::new_lifetime(<.text()))
- })
- .collect()
- });
+ let lifetimes: Option<Box<_>> =
+ pred.for_binder().and_then(|it| it.generic_param_list()).map(|param_list| {
+ // Higher-Ranked Trait Bounds
+ param_list
+ .lifetime_params()
+ .map(|lifetime_param| {
+ lifetime_param
+ .lifetime()
+ .map_or_else(Name::missing, |lt| Name::new_lifetime(<.text()))
+ })
+ .collect()
+ });
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);
}
diff --git a/crates/ide/src/inlay_hints/lifetime.rs b/crates/ide/src/inlay_hints/lifetime.rs
index 0069452..49fec0a 100644
--- a/crates/ide/src/inlay_hints/lifetime.rs
+++ b/crates/ide/src/inlay_hints/lifetime.rs
@@ -77,17 +77,18 @@
return None;
}
- let parent_for_type = func
+ let parent_for_binder = func
.syntax()
.ancestors()
.skip(1)
.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 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 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_(
acc,
ctx,
@@ -143,15 +144,16 @@
// FIXME: Support general path types
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()
.ancestors()
.skip(1)
.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 for_kw = parent_for_type.as_ref().and_then(|it| it.for_token());
+ let generic_param_list = parent_for_binder.as_ref().and_then(|it| it.generic_param_list());
+ let for_kw = parent_for_binder.as_ref().and_then(|it| it.for_token());
hints_(
acc,
ctx,
diff --git a/crates/parser/src/grammar/expressions/atom.rs b/crates/parser/src/grammar/expressions/atom.rs
index 7665656..ed8a91c 100644
--- a/crates/parser/src/grammar/expressions/atom.rs
+++ b/crates/parser/src/grammar/expressions/atom.rs
@@ -572,9 +572,7 @@
// test closure_binder
// fn main() { for<'a> || (); }
if p.at(T![for]) {
- let b = p.start();
types::for_binder(p);
- b.complete(p, CLOSURE_BINDER);
}
// test const_closure
// fn main() { let cl = const || _ = 0; }
diff --git a/crates/parser/src/grammar/generic_params.rs b/crates/parser/src/grammar/generic_params.rs
index 55c5dc4..cb1b59f 100644
--- a/crates/parser/src/grammar/generic_params.rs
+++ b/crates/parser/src/grammar/generic_params.rs
@@ -13,7 +13,7 @@
// test_err generic_param_list_recover
// 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![<]));
let m = p.start();
delimited(
@@ -147,7 +147,15 @@
let has_paren = p.eat(T!['(']);
match p.current() {
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
// fn captures<'a: 'a, 'b: 'b, T>() -> impl Sized + use<'b, T, Self> {}
@@ -180,44 +188,8 @@
p.bump_any();
types::for_type(p, false)
}
- current => {
- match current {
- 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 {
+ _ => {
+ if path_type_bound(p).is_err() {
m.abandon(p);
return false;
}
@@ -231,6 +203,43 @@
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
// fn foo()
// where
diff --git a/crates/parser/src/grammar/types.rs b/crates/parser/src/grammar/types.rs
index 908440b..a7e97c5 100644
--- a/crates/parser/src/grammar/types.rs
+++ b/crates/parser/src/grammar/types.rs
@@ -249,13 +249,14 @@
}
pub(super) fn for_binder(p: &mut Parser<'_>) {
- assert!(p.at(T![for]));
+ let m = p.start();
p.bump(T![for]);
if p.at(T![<]) {
- generic_params::opt_generic_param_list(p);
+ generic_params::generic_param_list(p);
} else {
p.error("expected `<`");
}
+ m.complete(p, FOR_BINDER);
}
// test for_type
diff --git a/crates/parser/src/syntax_kind/generated.rs b/crates/parser/src/syntax_kind/generated.rs
index 12a13ca..3a8041d 100644
--- a/crates/parser/src/syntax_kind/generated.rs
+++ b/crates/parser/src/syntax_kind/generated.rs
@@ -185,7 +185,6 @@
BREAK_EXPR,
CALL_EXPR,
CAST_EXPR,
- CLOSURE_BINDER,
CLOSURE_EXPR,
CONST,
CONST_ARG,
@@ -203,6 +202,7 @@
FN_PTR_TYPE,
FORMAT_ARGS_ARG,
FORMAT_ARGS_EXPR,
+ FOR_BINDER,
FOR_EXPR,
FOR_TYPE,
GENERIC_ARG_LIST,
@@ -358,7 +358,6 @@
| BREAK_EXPR
| CALL_EXPR
| CAST_EXPR
- | CLOSURE_BINDER
| CLOSURE_EXPR
| CONST
| CONST_ARG
@@ -376,6 +375,7 @@
| FN_PTR_TYPE
| FORMAT_ARGS_ARG
| FORMAT_ARGS_EXPR
+ | FOR_BINDER
| FOR_EXPR
| FOR_TYPE
| GENERIC_ARG_LIST
diff --git a/crates/parser/test_data/generated/runner.rs b/crates/parser/test_data/generated/runner.rs
index cef7b0e..c642e1a 100644
--- a/crates/parser/test_data/generated/runner.rs
+++ b/crates/parser/test_data/generated/runner.rs
@@ -253,6 +253,10 @@
run_and_expect_no_errors("test_data/parser/inline/ok/fn_pointer_unnamed_arg.rs");
}
#[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"); }
#[test]
fn for_range_from() {
@@ -402,6 +406,10 @@
#[test]
fn match_guard() { run_and_expect_no_errors("test_data/parser/inline/ok/match_guard.rs"); }
#[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"); }
#[test]
fn method_call_expr() {
diff --git a/crates/parser/test_data/parser/err/0024_many_type_parens.rast b/crates/parser/test_data/parser/err/0024_many_type_parens.rast
index 025c12e..2fd1725 100644
--- a/crates/parser/test_data/parser/err/0024_many_type_parens.rast
+++ b/crates/parser/test_data/parser/err/0024_many_type_parens.rast
@@ -37,7 +37,7 @@
WHITESPACE " "
TYPE_BOUND
L_PAREN "("
- FOR_TYPE
+ FOR_BINDER
FOR_KW "for"
GENERIC_PARAM_LIST
L_ANGLE "<"
@@ -45,18 +45,18 @@
LIFETIME
LIFETIME_IDENT "'a"
R_ANGLE ">"
- WHITESPACE " "
- PATH_TYPE
- PATH
- PATH_SEGMENT
- NAME_REF
- IDENT "Trait"
- GENERIC_ARG_LIST
- L_ANGLE "<"
- LIFETIME_ARG
- LIFETIME
- LIFETIME_IDENT "'a"
- R_ANGLE ">"
+ WHITESPACE " "
+ PATH_TYPE
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "Trait"
+ GENERIC_ARG_LIST
+ L_ANGLE "<"
+ LIFETIME_ARG
+ LIFETIME
+ LIFETIME_IDENT "'a"
+ R_ANGLE ">"
R_PAREN ")"
R_ANGLE ">"
PARAM_LIST
@@ -124,7 +124,7 @@
WHITESPACE " "
TYPE_BOUND
L_PAREN "("
- FOR_TYPE
+ FOR_BINDER
FOR_KW "for"
GENERIC_PARAM_LIST
L_ANGLE "<"
@@ -132,18 +132,18 @@
LIFETIME
LIFETIME_IDENT "'a"
R_ANGLE ">"
- WHITESPACE " "
- PATH_TYPE
- PATH
- PATH_SEGMENT
- NAME_REF
- IDENT "Trait"
- GENERIC_ARG_LIST
- L_ANGLE "<"
- LIFETIME_ARG
- LIFETIME
- LIFETIME_IDENT "'a"
- R_ANGLE ">"
+ WHITESPACE " "
+ PATH_TYPE
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "Trait"
+ GENERIC_ARG_LIST
+ L_ANGLE "<"
+ LIFETIME_ARG
+ LIFETIME
+ LIFETIME_IDENT "'a"
+ R_ANGLE ">"
R_PAREN ")"
ERROR
R_ANGLE ">"
@@ -186,7 +186,7 @@
TUPLE_EXPR
L_PAREN "("
CLOSURE_EXPR
- CLOSURE_BINDER
+ FOR_BINDER
FOR_KW "for"
GENERIC_PARAM_LIST
L_ANGLE "<"
@@ -243,13 +243,14 @@
PAREN_TYPE
L_PAREN "("
FOR_TYPE
- FOR_KW "for"
- GENERIC_PARAM_LIST
- L_ANGLE "<"
- LIFETIME_PARAM
- LIFETIME
- LIFETIME_IDENT "'a"
- R_ANGLE ">"
+ FOR_BINDER
+ FOR_KW "for"
+ GENERIC_PARAM_LIST
+ L_ANGLE "<"
+ LIFETIME_PARAM
+ LIFETIME
+ LIFETIME_IDENT "'a"
+ R_ANGLE ">"
WHITESPACE " "
PATH_TYPE
PATH
diff --git a/crates/parser/test_data/parser/err/0027_incomplete_where_for.rast b/crates/parser/test_data/parser/err/0027_incomplete_where_for.rast
index 674c8d5..3768a55 100644
--- a/crates/parser/test_data/parser/err/0027_incomplete_where_for.rast
+++ b/crates/parser/test_data/parser/err/0027_incomplete_where_for.rast
@@ -12,13 +12,14 @@
WHERE_KW "where"
WHITESPACE " "
WHERE_PRED
- FOR_KW "for"
- GENERIC_PARAM_LIST
- L_ANGLE "<"
- LIFETIME_PARAM
- LIFETIME
- LIFETIME_IDENT "'a"
- R_ANGLE ">"
+ FOR_BINDER
+ FOR_KW "for"
+ GENERIC_PARAM_LIST
+ L_ANGLE "<"
+ LIFETIME_PARAM
+ LIFETIME
+ LIFETIME_IDENT "'a"
+ R_ANGLE ">"
WHITESPACE "\n"
BLOCK_EXPR
STMT_LIST
diff --git a/crates/parser/test_data/parser/err/0043_unexpected_for_type.rast b/crates/parser/test_data/parser/err/0043_unexpected_for_type.rast
index cb4fb16..9c4ee6f 100644
--- a/crates/parser/test_data/parser/err/0043_unexpected_for_type.rast
+++ b/crates/parser/test_data/parser/err/0043_unexpected_for_type.rast
@@ -8,13 +8,14 @@
EQ "="
WHITESPACE " "
FOR_TYPE
- FOR_KW "for"
- GENERIC_PARAM_LIST
- L_ANGLE "<"
- LIFETIME_PARAM
- LIFETIME
- LIFETIME_IDENT "'a"
- R_ANGLE ">"
+ FOR_BINDER
+ FOR_KW "for"
+ GENERIC_PARAM_LIST
+ L_ANGLE "<"
+ LIFETIME_PARAM
+ LIFETIME
+ LIFETIME_IDENT "'a"
+ R_ANGLE ">"
WHITESPACE " "
REF_TYPE
AMP "&"
@@ -37,13 +38,14 @@
EQ "="
WHITESPACE " "
FOR_TYPE
- FOR_KW "for"
- GENERIC_PARAM_LIST
- L_ANGLE "<"
- LIFETIME_PARAM
- LIFETIME
- LIFETIME_IDENT "'a"
- R_ANGLE ">"
+ FOR_BINDER
+ FOR_KW "for"
+ GENERIC_PARAM_LIST
+ L_ANGLE "<"
+ LIFETIME_PARAM
+ LIFETIME
+ LIFETIME_IDENT "'a"
+ R_ANGLE ">"
WHITESPACE " "
TUPLE_TYPE
L_PAREN "("
@@ -70,13 +72,14 @@
EQ "="
WHITESPACE " "
FOR_TYPE
- FOR_KW "for"
- GENERIC_PARAM_LIST
- L_ANGLE "<"
- LIFETIME_PARAM
- LIFETIME
- LIFETIME_IDENT "'a"
- R_ANGLE ">"
+ FOR_BINDER
+ FOR_KW "for"
+ GENERIC_PARAM_LIST
+ L_ANGLE "<"
+ LIFETIME_PARAM
+ LIFETIME
+ LIFETIME_IDENT "'a"
+ R_ANGLE ">"
WHITESPACE " "
SLICE_TYPE
L_BRACK "["
@@ -97,22 +100,24 @@
EQ "="
WHITESPACE " "
FOR_TYPE
- FOR_KW "for"
- GENERIC_PARAM_LIST
- L_ANGLE "<"
- LIFETIME_PARAM
- LIFETIME
- LIFETIME_IDENT "'a"
- R_ANGLE ">"
- WHITESPACE " "
- FOR_TYPE
+ FOR_BINDER
FOR_KW "for"
GENERIC_PARAM_LIST
L_ANGLE "<"
LIFETIME_PARAM
LIFETIME
- LIFETIME_IDENT "'b"
+ LIFETIME_IDENT "'a"
R_ANGLE ">"
+ WHITESPACE " "
+ FOR_TYPE
+ FOR_BINDER
+ FOR_KW "for"
+ GENERIC_PARAM_LIST
+ L_ANGLE "<"
+ LIFETIME_PARAM
+ LIFETIME
+ LIFETIME_IDENT "'b"
+ R_ANGLE ">"
WHITESPACE " "
FN_PTR_TYPE
FN_KW "fn"
@@ -164,31 +169,34 @@
WHERE_KW "where"
WHITESPACE "\n "
WHERE_PRED
- FOR_KW "for"
- GENERIC_PARAM_LIST
- L_ANGLE "<"
- LIFETIME_PARAM
- LIFETIME
- LIFETIME_IDENT "'a"
- R_ANGLE ">"
- WHITESPACE " "
- FOR_TYPE
+ FOR_BINDER
FOR_KW "for"
GENERIC_PARAM_LIST
L_ANGLE "<"
LIFETIME_PARAM
LIFETIME
- LIFETIME_IDENT "'b"
+ LIFETIME_IDENT "'a"
R_ANGLE ">"
- WHITESPACE " "
- FOR_TYPE
+ WHITESPACE " "
+ FOR_TYPE
+ FOR_BINDER
FOR_KW "for"
GENERIC_PARAM_LIST
L_ANGLE "<"
LIFETIME_PARAM
LIFETIME
- LIFETIME_IDENT "'c"
+ LIFETIME_IDENT "'b"
R_ANGLE ">"
+ WHITESPACE " "
+ FOR_TYPE
+ FOR_BINDER
+ FOR_KW "for"
+ GENERIC_PARAM_LIST
+ L_ANGLE "<"
+ LIFETIME_PARAM
+ LIFETIME
+ LIFETIME_IDENT "'c"
+ R_ANGLE ">"
WHITESPACE " "
FN_PTR_TYPE
FN_KW "fn"
diff --git a/crates/parser/test_data/parser/inline/ok/closure_binder.rast b/crates/parser/test_data/parser/inline/ok/closure_binder.rast
index c04dbe1..c96ccf7 100644
--- a/crates/parser/test_data/parser/inline/ok/closure_binder.rast
+++ b/crates/parser/test_data/parser/inline/ok/closure_binder.rast
@@ -14,7 +14,7 @@
WHITESPACE " "
EXPR_STMT
CLOSURE_EXPR
- CLOSURE_BINDER
+ FOR_BINDER
FOR_KW "for"
GENERIC_PARAM_LIST
L_ANGLE "<"
diff --git a/crates/parser/test_data/parser/inline/ok/dyn_trait_type_weak.rast b/crates/parser/test_data/parser/inline/ok/dyn_trait_type_weak.rast
index dcc66dc..6578809 100644
--- a/crates/parser/test_data/parser/inline/ok/dyn_trait_type_weak.rast
+++ b/crates/parser/test_data/parser/inline/ok/dyn_trait_type_weak.rast
@@ -103,7 +103,7 @@
WHITESPACE " "
TYPE_BOUND_LIST
TYPE_BOUND
- FOR_TYPE
+ FOR_BINDER
FOR_KW "for"
GENERIC_PARAM_LIST
L_ANGLE "<"
@@ -111,12 +111,12 @@
LIFETIME
LIFETIME_IDENT "'a"
R_ANGLE ">"
- WHITESPACE " "
- PATH_TYPE
- PATH
- PATH_SEGMENT
- NAME_REF
- IDENT "Path"
+ WHITESPACE " "
+ PATH_TYPE
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "Path"
SEMICOLON ";"
WHITESPACE "\n"
TYPE_ALIAS
diff --git a/crates/parser/test_data/parser/inline/ok/for_binder_bound.rast b/crates/parser/test_data/parser/inline/ok/for_binder_bound.rast
new file mode 100644
index 0000000..17dbbf3
--- /dev/null
+++ b/crates/parser/test_data/parser/inline/ok/for_binder_bound.rast
@@ -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"
diff --git a/crates/parser/test_data/parser/inline/ok/for_binder_bound.rs b/crates/parser/test_data/parser/inline/ok/for_binder_bound.rs
new file mode 100644
index 0000000..427cf55
--- /dev/null
+++ b/crates/parser/test_data/parser/inline/ok/for_binder_bound.rs
@@ -0,0 +1 @@
+fn foo<T: for<'a> [const] async Trait>() {}
diff --git a/crates/parser/test_data/parser/inline/ok/for_type.rast b/crates/parser/test_data/parser/inline/ok/for_type.rast
index 7600457..5862305 100644
--- a/crates/parser/test_data/parser/inline/ok/for_type.rast
+++ b/crates/parser/test_data/parser/inline/ok/for_type.rast
@@ -8,13 +8,14 @@
EQ "="
WHITESPACE " "
FOR_TYPE
- FOR_KW "for"
- GENERIC_PARAM_LIST
- L_ANGLE "<"
- LIFETIME_PARAM
- LIFETIME
- LIFETIME_IDENT "'a"
- R_ANGLE ">"
+ FOR_BINDER
+ FOR_KW "for"
+ GENERIC_PARAM_LIST
+ L_ANGLE "<"
+ LIFETIME_PARAM
+ LIFETIME
+ LIFETIME_IDENT "'a"
+ R_ANGLE ">"
WHITESPACE " "
FN_PTR_TYPE
FN_KW "fn"
@@ -39,13 +40,14 @@
EQ "="
WHITESPACE " "
FOR_TYPE
- FOR_KW "for"
- GENERIC_PARAM_LIST
- L_ANGLE "<"
- LIFETIME_PARAM
- LIFETIME
- LIFETIME_IDENT "'a"
- R_ANGLE ">"
+ FOR_BINDER
+ FOR_KW "for"
+ GENERIC_PARAM_LIST
+ L_ANGLE "<"
+ LIFETIME_PARAM
+ LIFETIME
+ LIFETIME_IDENT "'a"
+ R_ANGLE ">"
WHITESPACE " "
FN_PTR_TYPE
UNSAFE_KW "unsafe"
@@ -86,13 +88,14 @@
EQ "="
WHITESPACE " "
FOR_TYPE
- FOR_KW "for"
- GENERIC_PARAM_LIST
- L_ANGLE "<"
- LIFETIME_PARAM
- LIFETIME
- LIFETIME_IDENT "'a"
- R_ANGLE ">"
+ FOR_BINDER
+ FOR_KW "for"
+ GENERIC_PARAM_LIST
+ L_ANGLE "<"
+ LIFETIME_PARAM
+ LIFETIME
+ LIFETIME_IDENT "'a"
+ R_ANGLE ">"
WHITESPACE " "
PATH_TYPE
PATH
diff --git a/crates/parser/test_data/parser/inline/ok/lambda_expr.rast b/crates/parser/test_data/parser/inline/ok/lambda_expr.rast
index ea401d2..bf24a57 100644
--- a/crates/parser/test_data/parser/inline/ok/lambda_expr.rast
+++ b/crates/parser/test_data/parser/inline/ok/lambda_expr.rast
@@ -202,7 +202,7 @@
WHITESPACE "\n "
EXPR_STMT
CLOSURE_EXPR
- CLOSURE_BINDER
+ FOR_BINDER
FOR_KW "for"
GENERIC_PARAM_LIST
L_ANGLE "<"
@@ -223,7 +223,7 @@
WHITESPACE "\n "
EXPR_STMT
CLOSURE_EXPR
- CLOSURE_BINDER
+ FOR_BINDER
FOR_KW "for"
GENERIC_PARAM_LIST
L_ANGLE "<"
diff --git a/crates/parser/test_data/parser/inline/ok/maybe_const_trait_bound.rast b/crates/parser/test_data/parser/inline/ok/maybe_const_trait_bound.rast
new file mode 100644
index 0000000..8d12f81
--- /dev/null
+++ b/crates/parser/test_data/parser/inline/ok/maybe_const_trait_bound.rast
@@ -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"
diff --git a/crates/parser/test_data/parser/inline/ok/maybe_const_trait_bound.rs b/crates/parser/test_data/parser/inline/ok/maybe_const_trait_bound.rs
new file mode 100644
index 0000000..e1da920
--- /dev/null
+++ b/crates/parser/test_data/parser/inline/ok/maybe_const_trait_bound.rs
@@ -0,0 +1 @@
+const fn foo(_: impl [const] Trait) {}
diff --git a/crates/parser/test_data/parser/inline/ok/no_dyn_trait_leading_for.rast b/crates/parser/test_data/parser/inline/ok/no_dyn_trait_leading_for.rast
index 30a2842..6afa061 100644
--- a/crates/parser/test_data/parser/inline/ok/no_dyn_trait_leading_for.rast
+++ b/crates/parser/test_data/parser/inline/ok/no_dyn_trait_leading_for.rast
@@ -11,13 +11,14 @@
TYPE_BOUND_LIST
TYPE_BOUND
FOR_TYPE
- FOR_KW "for"
- GENERIC_PARAM_LIST
- L_ANGLE "<"
- LIFETIME_PARAM
- LIFETIME
- LIFETIME_IDENT "'a"
- R_ANGLE ">"
+ FOR_BINDER
+ FOR_KW "for"
+ GENERIC_PARAM_LIST
+ L_ANGLE "<"
+ LIFETIME_PARAM
+ LIFETIME
+ LIFETIME_IDENT "'a"
+ R_ANGLE ">"
WHITESPACE " "
PATH_TYPE
PATH
diff --git a/crates/parser/test_data/parser/inline/ok/question_for_type_trait_bound.rast b/crates/parser/test_data/parser/inline/ok/question_for_type_trait_bound.rast
index 56e2d10..cb29615 100644
--- a/crates/parser/test_data/parser/inline/ok/question_for_type_trait_bound.rast
+++ b/crates/parser/test_data/parser/inline/ok/question_for_type_trait_bound.rast
@@ -29,10 +29,11 @@
TYPE_BOUND
QUESTION "?"
FOR_TYPE
- FOR_KW "for"
- GENERIC_PARAM_LIST
- L_ANGLE "<"
- R_ANGLE ">"
+ FOR_BINDER
+ FOR_KW "for"
+ GENERIC_PARAM_LIST
+ L_ANGLE "<"
+ R_ANGLE ">"
WHITESPACE " "
PATH_TYPE
PATH
diff --git a/crates/parser/test_data/parser/inline/ok/where_pred_for.rast b/crates/parser/test_data/parser/inline/ok/where_pred_for.rast
index 0cc365e..b10b953 100644
--- a/crates/parser/test_data/parser/inline/ok/where_pred_for.rast
+++ b/crates/parser/test_data/parser/inline/ok/where_pred_for.rast
@@ -18,13 +18,14 @@
WHERE_KW "where"
WHITESPACE "\n "
WHERE_PRED
- FOR_KW "for"
- GENERIC_PARAM_LIST
- L_ANGLE "<"
- LIFETIME_PARAM
- LIFETIME
- LIFETIME_IDENT "'a"
- R_ANGLE ">"
+ FOR_BINDER
+ FOR_KW "for"
+ GENERIC_PARAM_LIST
+ L_ANGLE "<"
+ LIFETIME_PARAM
+ LIFETIME
+ LIFETIME_IDENT "'a"
+ R_ANGLE ">"
WHITESPACE " "
PATH_TYPE
PATH
diff --git a/crates/parser/test_data/parser/ok/0032_where_for.rast b/crates/parser/test_data/parser/ok/0032_where_for.rast
index 86f6af9..dcaf58f 100644
--- a/crates/parser/test_data/parser/ok/0032_where_for.rast
+++ b/crates/parser/test_data/parser/ok/0032_where_for.rast
@@ -36,7 +36,7 @@
PLUS "+"
WHITESPACE " "
TYPE_BOUND
- FOR_TYPE
+ FOR_BINDER
FOR_KW "for"
GENERIC_PARAM_LIST
L_ANGLE "<"
@@ -44,18 +44,18 @@
LIFETIME
LIFETIME_IDENT "'de"
R_ANGLE ">"
- WHITESPACE " "
- PATH_TYPE
- PATH
- PATH_SEGMENT
- NAME_REF
- IDENT "Deserialize"
- GENERIC_ARG_LIST
- L_ANGLE "<"
- LIFETIME_ARG
- LIFETIME
- LIFETIME_IDENT "'de"
- R_ANGLE ">"
+ WHITESPACE " "
+ PATH_TYPE
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "Deserialize"
+ GENERIC_ARG_LIST
+ L_ANGLE "<"
+ LIFETIME_ARG
+ LIFETIME
+ LIFETIME_IDENT "'de"
+ R_ANGLE ">"
WHITESPACE " "
PLUS "+"
WHITESPACE " "
diff --git a/crates/parser/test_data/parser/ok/0067_where_for_pred.rast b/crates/parser/test_data/parser/ok/0067_where_for_pred.rast
index 8bf1090..5cef4df 100644
--- a/crates/parser/test_data/parser/ok/0067_where_for_pred.rast
+++ b/crates/parser/test_data/parser/ok/0067_where_for_pred.rast
@@ -18,13 +18,14 @@
WHERE_KW "where"
WHITESPACE "\n "
WHERE_PRED
- FOR_KW "for"
- GENERIC_PARAM_LIST
- L_ANGLE "<"
- LIFETIME_PARAM
- LIFETIME
- LIFETIME_IDENT "'a"
- R_ANGLE ">"
+ FOR_BINDER
+ FOR_KW "for"
+ GENERIC_PARAM_LIST
+ L_ANGLE "<"
+ LIFETIME_PARAM
+ LIFETIME
+ LIFETIME_IDENT "'a"
+ R_ANGLE ">"
WHITESPACE " "
PATH_TYPE
PATH
@@ -81,13 +82,14 @@
WHERE_KW "where"
WHITESPACE "\n "
WHERE_PRED
- FOR_KW "for"
- GENERIC_PARAM_LIST
- L_ANGLE "<"
- LIFETIME_PARAM
- LIFETIME
- LIFETIME_IDENT "'a"
- R_ANGLE ">"
+ FOR_BINDER
+ FOR_KW "for"
+ GENERIC_PARAM_LIST
+ L_ANGLE "<"
+ LIFETIME_PARAM
+ LIFETIME
+ LIFETIME_IDENT "'a"
+ R_ANGLE ">"
WHITESPACE " "
REF_TYPE
AMP "&"
@@ -135,13 +137,14 @@
WHERE_KW "where"
WHITESPACE "\n "
WHERE_PRED
- FOR_KW "for"
- GENERIC_PARAM_LIST
- L_ANGLE "<"
- LIFETIME_PARAM
- LIFETIME
- LIFETIME_IDENT "'a"
- R_ANGLE ">"
+ FOR_BINDER
+ FOR_KW "for"
+ GENERIC_PARAM_LIST
+ L_ANGLE "<"
+ LIFETIME_PARAM
+ LIFETIME
+ LIFETIME_IDENT "'a"
+ R_ANGLE ">"
WHITESPACE " "
PAREN_TYPE
L_PAREN "("
@@ -206,13 +209,14 @@
WHERE_KW "where"
WHITESPACE "\n "
WHERE_PRED
- FOR_KW "for"
- GENERIC_PARAM_LIST
- L_ANGLE "<"
- LIFETIME_PARAM
- LIFETIME
- LIFETIME_IDENT "'a"
- R_ANGLE ">"
+ FOR_BINDER
+ FOR_KW "for"
+ GENERIC_PARAM_LIST
+ L_ANGLE "<"
+ LIFETIME_PARAM
+ LIFETIME
+ LIFETIME_IDENT "'a"
+ R_ANGLE ">"
WHITESPACE " "
SLICE_TYPE
L_BRACK "["
@@ -276,13 +280,14 @@
WHERE_KW "where"
WHITESPACE "\n "
WHERE_PRED
- FOR_KW "for"
- GENERIC_PARAM_LIST
- L_ANGLE "<"
- LIFETIME_PARAM
- LIFETIME
- LIFETIME_IDENT "'a"
- R_ANGLE ">"
+ FOR_BINDER
+ FOR_KW "for"
+ GENERIC_PARAM_LIST
+ L_ANGLE "<"
+ LIFETIME_PARAM
+ LIFETIME
+ LIFETIME_IDENT "'a"
+ R_ANGLE ">"
WHITESPACE " "
PATH_TYPE
PATH
@@ -349,22 +354,24 @@
WHERE_KW "where"
WHITESPACE "\n "
WHERE_PRED
- FOR_KW "for"
- GENERIC_PARAM_LIST
- L_ANGLE "<"
- LIFETIME_PARAM
- LIFETIME
- LIFETIME_IDENT "'a"
- R_ANGLE ">"
- WHITESPACE " "
- FOR_TYPE
+ FOR_BINDER
FOR_KW "for"
GENERIC_PARAM_LIST
L_ANGLE "<"
LIFETIME_PARAM
LIFETIME
- LIFETIME_IDENT "'b"
+ LIFETIME_IDENT "'a"
R_ANGLE ">"
+ WHITESPACE " "
+ FOR_TYPE
+ FOR_BINDER
+ FOR_KW "for"
+ GENERIC_PARAM_LIST
+ L_ANGLE "<"
+ LIFETIME_PARAM
+ LIFETIME
+ LIFETIME_IDENT "'b"
+ R_ANGLE ">"
WHITESPACE " "
FN_PTR_TYPE
FN_KW "fn"
diff --git a/crates/syntax/rust.ungram b/crates/syntax/rust.ungram
index 4cbc88c..6d8a360 100644
--- a/crates/syntax/rust.ungram
+++ b/crates/syntax/rust.ungram
@@ -101,7 +101,7 @@
'where' predicates:(WherePred (',' WherePred)* ','?)
WherePred =
- ('for' GenericParamList)? (Lifetime | Type) ':' TypeBoundList?
+ ForBinder? (Lifetime | Type) ':' TypeBoundList?
//*************************//
@@ -534,10 +534,10 @@
Attr* Expr '.' NameRef
ClosureExpr =
- Attr* ClosureBinder? 'const'? 'static'? 'async'? 'gen'? 'move'? ParamList RetType?
+ Attr* ForBinder? 'const'? 'static'? 'async'? 'gen'? 'move'? ParamList RetType?
body:Expr
-ClosureBinder =
+ForBinder =
'for' GenericParamList
IfExpr =
@@ -658,7 +658,7 @@
'const'? 'async'? 'unsafe'? Abi? 'fn' ParamList RetType?
ForType =
- 'for' GenericParamList Type
+ ForBinder Type
ImplTraitType =
'impl' TypeBoundList
@@ -671,7 +671,7 @@
TypeBound =
Lifetime
-| ('~' 'const' | '[' 'const' ']' | 'const')? 'async'? '?'? Type
+| ForBinder? ('~' 'const' | '[' 'const' ']' | 'const')? 'async'? '?'? Type
| 'use' UseBoundGenericArgs
UseBoundGenericArgs =
diff --git a/crates/syntax/src/ast.rs b/crates/syntax/src/ast.rs
index d787fd0..a9aeeed 100644
--- a/crates/syntax/src/ast.rs
+++ b/crates/syntax/src/ast.rs
@@ -393,8 +393,7 @@
let pred = predicates.next().unwrap();
let mut bounds = pred.type_bound_list().unwrap().bounds();
- assert!(pred.for_token().is_none());
- assert!(pred.generic_param_list().is_none());
+ assert!(pred.for_binder().is_none());
assert_eq!("T", pred.ty().unwrap().syntax().text().to_string());
assert_bound("Clone", bounds.next());
assert_bound("Copy", bounds.next());
@@ -432,8 +431,10 @@
let pred = predicates.next().unwrap();
let mut bounds = pred.type_bound_list().unwrap().bounds();
- assert!(pred.for_token().is_some());
- assert_eq!("<'a>", pred.generic_param_list().unwrap().syntax().text().to_string());
+ assert_eq!(
+ "<'a>",
+ pred.for_binder().unwrap().generic_param_list().unwrap().syntax().text().to_string()
+ );
assert_eq!("F", pred.ty().unwrap().syntax().text().to_string());
assert_bound("Fn(&'a str)", bounds.next());
}
diff --git a/crates/syntax/src/ast/generated/nodes.rs b/crates/syntax/src/ast/generated/nodes.rs
index 2b86246..ceb2866 100644
--- a/crates/syntax/src/ast/generated/nodes.rs
+++ b/crates/syntax/src/ast/generated/nodes.rs
@@ -377,22 +377,13 @@
#[inline]
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(crate) syntax: SyntaxNode,
}
impl ast::HasAttrs for ClosureExpr {}
impl ClosureExpr {
#[inline]
- pub fn closure_binder(&self) -> Option<ClosureBinder> { support::child(&self.syntax) }
+ pub fn for_binder(&self) -> Option<ForBinder> { support::child(&self.syntax) }
#[inline]
pub fn param_list(&self) -> Option<ParamList> { support::child(&self.syntax) }
#[inline]
@@ -615,6 +606,15 @@
#[inline]
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(crate) syntax: SyntaxNode,
}
@@ -632,11 +632,9 @@
}
impl ForType {
#[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]
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(crate) syntax: SyntaxNode,
@@ -1766,6 +1764,8 @@
}
impl TypeBound {
#[inline]
+ pub fn for_binder(&self) -> Option<ForBinder> { support::child(&self.syntax) }
+ #[inline]
pub fn lifetime(&self) -> Option<Lifetime> { support::child(&self.syntax) }
#[inline]
pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
@@ -1938,13 +1938,11 @@
impl ast::HasTypeBounds for WherePred {}
impl WherePred {
#[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]
pub fn lifetime(&self) -> Option<Lifetime> { support::child(&self.syntax) }
#[inline]
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(crate) syntax: SyntaxNode,
@@ -3239,42 +3237,6 @@
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 {
#[inline]
fn kind() -> SyntaxKind
@@ -3815,6 +3777,42 @@
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 {
#[inline]
fn kind() -> SyntaxKind
@@ -10146,11 +10144,6 @@
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 {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self.syntax(), f)
@@ -10226,6 +10219,11 @@
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 {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self.syntax(), f)
diff --git a/crates/syntax/src/ast/node_ext.rs b/crates/syntax/src/ast/node_ext.rs
index f5530c5..62a7d4d 100644
--- a/crates/syntax/src/ast/node_ext.rs
+++ b/crates/syntax/src/ast/node_ext.rs
@@ -805,9 +805,7 @@
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub enum TypeBoundKind {
/// Trait
- PathType(ast::PathType),
- /// for<'a> ...
- ForType(ast::ForType),
+ PathType(Option<ast::ForBinder>, ast::PathType),
/// use
Use(ast::UseBoundGenericArgs),
/// 'a
@@ -817,9 +815,7 @@
impl ast::TypeBound {
pub fn kind(&self) -> TypeBoundKind {
if let Some(path_type) = support::children(self.syntax()).next() {
- TypeBoundKind::PathType(path_type)
- } else if let Some(for_type) = support::children(self.syntax()).next() {
- TypeBoundKind::ForType(for_type)
+ TypeBoundKind::PathType(self.for_binder(), path_type)
} else if let Some(args) = self.use_bound_generic_args() {
TypeBoundKind::Use(args)
} else if let Some(lifetime) = self.lifetime() {