From c7ceb39f6758ed4dca9388d7e30da2f3f642d7e0 Mon Sep 17 00:00:00 2001 From: Chayim Refael Friedman Date: Tue, 22 Jul 2025 16:24:42 +0300 Subject: [PATCH] Parse `for<'a> [const]` And also refactor parsing of HRTB. --- crates/hir-def/src/expr_store/lower.rs | 41 +++---- .../hir-def/src/expr_store/lower/generics.rs | 23 ++-- crates/ide/src/inlay_hints/lifetime.rs | 18 +-- crates/parser/src/grammar/expressions/atom.rs | 2 - crates/parser/src/grammar/generic_params.rs | 89 +++++++------- crates/parser/src/grammar/types.rs | 5 +- crates/parser/src/syntax_kind/generated.rs | 4 +- crates/parser/test_data/generated/runner.rs | 8 ++ .../parser/err/0024_many_type_parens.rast | 69 +++++------ .../parser/err/0027_incomplete_where_for.rast | 15 +-- .../parser/err/0043_unexpected_for_type.rast | 96 ++++++++------- .../parser/inline/ok/closure_binder.rast | 2 +- .../parser/inline/ok/dyn_trait_type_weak.rast | 14 +-- .../parser/inline/ok/for_binder_bound.rast | 45 +++++++ .../parser/inline/ok/for_binder_bound.rs | 1 + .../test_data/parser/inline/ok/for_type.rast | 45 +++---- .../parser/inline/ok/lambda_expr.rast | 4 +- .../inline/ok/maybe_const_trait_bound.rast | 36 ++++++ .../inline/ok/maybe_const_trait_bound.rs | 1 + .../inline/ok/no_dyn_trait_leading_for.rast | 15 +-- .../ok/question_for_type_trait_bound.rast | 9 +- .../parser/inline/ok/where_pred_for.rast | 15 +-- .../test_data/parser/ok/0032_where_for.rast | 26 ++-- .../parser/ok/0067_where_for_pred.rast | 97 ++++++++------- crates/syntax/rust.ungram | 10 +- crates/syntax/src/ast.rs | 9 +- crates/syntax/src/ast/generated/nodes.rs | 112 +++++++++--------- crates/syntax/src/ast/node_ext.rs | 8 +- 28 files changed, 465 insertions(+), 354 deletions(-) create mode 100644 crates/parser/test_data/parser/inline/ok/for_binder_bound.rast create mode 100644 crates/parser/test_data/parser/inline/ok/for_binder_bound.rs create mode 100644 crates/parser/test_data/parser/inline/ok/maybe_const_trait_bound.rast create mode 100644 crates/parser/test_data/parser/inline/ok/maybe_const_trait_bound.rs diff --git a/crates/hir-def/src/expr_store/lower.rs b/crates/hir-def/src/expr_store/lower.rs index 4e877748ca..7990a6436a 100644 --- a/crates/hir-def/src/expr_store/lower.rs +++ b/crates/hir-def/src/expr_store/lower.rs @@ -960,37 +960,28 @@ impl ExprCollector<'_> { 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 02a1d274fb..c570df42b2 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 @@ impl GenericParamsCollector { continue; }; - let lifetimes: Option> = 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> = + 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 0069452e7b..49fec0a793 100644 --- a/crates/ide/src/inlay_hints/lifetime.rs +++ b/crates/ide/src/inlay_hints/lifetime.rs @@ -77,17 +77,18 @@ pub(super) fn fn_ptr_hints( 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 @@ pub(super) fn fn_path_hints( // 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 76656567e7..ed8a91c39c 100644 --- a/crates/parser/src/grammar/expressions/atom.rs +++ b/crates/parser/src/grammar/expressions/atom.rs @@ -572,9 +572,7 @@ fn closure_expr(p: &mut Parser<'_>) -> CompletedMarker { // 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 55c5dc400b..cb1b59f649 100644 --- a/crates/parser/src/grammar/generic_params.rs +++ b/crates/parser/src/grammar/generic_params.rs @@ -13,7 +13,7 @@ pub(super) fn opt_generic_param_list(p: &mut Parser<'_>) { // test_err generic_param_list_recover // fn f() {} -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 @@ fn type_bound(p: &mut Parser<'_>) -> bool { 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 [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 @@ fn type_bound(p: &mut Parser<'_>) -> bool { 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() -> Box {} - 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 @@ fn type_bound(p: &mut Parser<'_>) -> bool { 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() -> Box {} + 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 908440b5d0..a7e97c5f85 100644 --- a/crates/parser/src/grammar/types.rs +++ b/crates/parser/src/grammar/types.rs @@ -249,13 +249,14 @@ fn fn_ptr_type(p: &mut Parser<'_>) { } 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 12a13caa4d..3a8041d2df 100644 --- a/crates/parser/src/syntax_kind/generated.rs +++ b/crates/parser/src/syntax_kind/generated.rs @@ -185,7 +185,6 @@ pub enum SyntaxKind { BREAK_EXPR, CALL_EXPR, CAST_EXPR, - CLOSURE_BINDER, CLOSURE_EXPR, CONST, CONST_ARG, @@ -203,6 +202,7 @@ pub enum SyntaxKind { FN_PTR_TYPE, FORMAT_ARGS_ARG, FORMAT_ARGS_EXPR, + FOR_BINDER, FOR_EXPR, FOR_TYPE, GENERIC_ARG_LIST, @@ -358,7 +358,6 @@ impl SyntaxKind { | BREAK_EXPR | CALL_EXPR | CAST_EXPR - | CLOSURE_BINDER | CLOSURE_EXPR | CONST | CONST_ARG @@ -376,6 +375,7 @@ impl SyntaxKind { | 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 cef7b0ee23..c642e1a335 100644 --- a/crates/parser/test_data/generated/runner.rs +++ b/crates/parser/test_data/generated/runner.rs @@ -253,6 +253,10 @@ mod ok { 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 @@ mod ok { #[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 025c12e4c2..2fd172539e 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 @@ SOURCE_FILE WHITESPACE " " TYPE_BOUND L_PAREN "(" - FOR_TYPE + FOR_BINDER FOR_KW "for" GENERIC_PARAM_LIST L_ANGLE "<" @@ -45,18 +45,18 @@ SOURCE_FILE 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 @@ SOURCE_FILE WHITESPACE " " TYPE_BOUND L_PAREN "(" - FOR_TYPE + FOR_BINDER FOR_KW "for" GENERIC_PARAM_LIST L_ANGLE "<" @@ -132,18 +132,18 @@ SOURCE_FILE 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 @@ SOURCE_FILE TUPLE_EXPR L_PAREN "(" CLOSURE_EXPR - CLOSURE_BINDER + FOR_BINDER FOR_KW "for" GENERIC_PARAM_LIST L_ANGLE "<" @@ -243,13 +243,14 @@ SOURCE_FILE 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 674c8d536c..3768a55d53 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 @@ SOURCE_FILE 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 cb4fb1642d..9c4ee6f712 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 @@ SOURCE_FILE 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 @@ SOURCE_FILE 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 @@ SOURCE_FILE 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 @@ SOURCE_FILE 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 @@ SOURCE_FILE 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 c04dbe1ea0..c96ccf7c7f 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 @@ SOURCE_FILE 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 dcc66dc1e2..6578809cb0 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 @@ SOURCE_FILE WHITESPACE " " TYPE_BOUND_LIST TYPE_BOUND - FOR_TYPE + FOR_BINDER FOR_KW "for" GENERIC_PARAM_LIST L_ANGLE "<" @@ -111,12 +111,12 @@ SOURCE_FILE 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 0000000000..17dbbf30a7 --- /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 0000000000..427cf55871 --- /dev/null +++ b/crates/parser/test_data/parser/inline/ok/for_binder_bound.rs @@ -0,0 +1 @@ +fn foo [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 7600457a9b..58623058ca 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 @@ SOURCE_FILE 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 @@ SOURCE_FILE 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 @@ SOURCE_FILE 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 ea401d224e..bf24a57912 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 @@ SOURCE_FILE WHITESPACE "\n " EXPR_STMT CLOSURE_EXPR - CLOSURE_BINDER + FOR_BINDER FOR_KW "for" GENERIC_PARAM_LIST L_ANGLE "<" @@ -223,7 +223,7 @@ SOURCE_FILE 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 0000000000..8d12f814c2 --- /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 0000000000..e1da920609 --- /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 30a2842e53..6afa0613f3 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 @@ SOURCE_FILE 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 56e2d1095d..cb296153c8 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 @@ SOURCE_FILE 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 0cc365efbe..b10b953f2f 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 @@ SOURCE_FILE 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 86f6af97c7..dcaf58f7f9 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 @@ SOURCE_FILE PLUS "+" WHITESPACE " " TYPE_BOUND - FOR_TYPE + FOR_BINDER FOR_KW "for" GENERIC_PARAM_LIST L_ANGLE "<" @@ -44,18 +44,18 @@ SOURCE_FILE 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 8bf1090f9c..5cef4dff06 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 @@ SOURCE_FILE 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 @@ SOURCE_FILE 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 @@ SOURCE_FILE 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 @@ SOURCE_FILE 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 @@ SOURCE_FILE 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 @@ SOURCE_FILE 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 4cbc88cfb5..6d8a360d71 100644 --- a/crates/syntax/rust.ungram +++ b/crates/syntax/rust.ungram @@ -101,7 +101,7 @@ WhereClause = 'where' predicates:(WherePred (',' WherePred)* ','?) WherePred = - ('for' GenericParamList)? (Lifetime | Type) ':' TypeBoundList? + ForBinder? (Lifetime | Type) ':' TypeBoundList? //*************************// @@ -534,10 +534,10 @@ FieldExpr = 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 @@ FnPtrType = 'const'? 'async'? 'unsafe'? Abi? 'fn' ParamList RetType? ForType = - 'for' GenericParamList Type + ForBinder Type ImplTraitType = 'impl' TypeBoundList @@ -671,7 +671,7 @@ TypeBoundList = 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 d787fd076f..a9aeeedb65 100644 --- a/crates/syntax/src/ast.rs +++ b/crates/syntax/src/ast.rs @@ -393,8 +393,7 @@ where 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 @@ where 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 2b86246542..ceb2866ebc 100644 --- a/crates/syntax/src/ast/generated/nodes.rs +++ b/crates/syntax/src/ast/generated/nodes.rs @@ -377,22 +377,13 @@ impl CastExpr { #[inline] pub fn as_token(&self) -> Option { support::token(&self.syntax, T![as]) } } -pub struct ClosureBinder { - pub(crate) syntax: SyntaxNode, -} -impl ClosureBinder { - #[inline] - pub fn generic_param_list(&self) -> Option { support::child(&self.syntax) } - #[inline] - pub fn for_token(&self) -> Option { 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 { support::child(&self.syntax) } + pub fn for_binder(&self) -> Option { support::child(&self.syntax) } #[inline] pub fn param_list(&self) -> Option { support::child(&self.syntax) } #[inline] @@ -615,6 +606,15 @@ impl FnPtrType { #[inline] pub fn unsafe_token(&self) -> Option { support::token(&self.syntax, T![unsafe]) } } +pub struct ForBinder { + pub(crate) syntax: SyntaxNode, +} +impl ForBinder { + #[inline] + pub fn generic_param_list(&self) -> Option { support::child(&self.syntax) } + #[inline] + pub fn for_token(&self) -> Option { support::token(&self.syntax, T![for]) } +} pub struct ForExpr { pub(crate) syntax: SyntaxNode, } @@ -632,11 +632,9 @@ pub struct ForType { } impl ForType { #[inline] - pub fn generic_param_list(&self) -> Option { support::child(&self.syntax) } + pub fn for_binder(&self) -> Option { support::child(&self.syntax) } #[inline] pub fn ty(&self) -> Option { support::child(&self.syntax) } - #[inline] - pub fn for_token(&self) -> Option { support::token(&self.syntax, T![for]) } } pub struct FormatArgsArg { pub(crate) syntax: SyntaxNode, @@ -1765,6 +1763,8 @@ pub struct TypeBound { pub(crate) syntax: SyntaxNode, } impl TypeBound { + #[inline] + pub fn for_binder(&self) -> Option { support::child(&self.syntax) } #[inline] pub fn lifetime(&self) -> Option { support::child(&self.syntax) } #[inline] @@ -1938,13 +1938,11 @@ pub struct WherePred { impl ast::HasTypeBounds for WherePred {} impl WherePred { #[inline] - pub fn generic_param_list(&self) -> Option { support::child(&self.syntax) } + pub fn for_binder(&self) -> Option { support::child(&self.syntax) } #[inline] pub fn lifetime(&self) -> Option { support::child(&self.syntax) } #[inline] pub fn ty(&self) -> Option { support::child(&self.syntax) } - #[inline] - pub fn for_token(&self) -> Option { support::token(&self.syntax, T![for]) } } pub struct WhileExpr { pub(crate) syntax: SyntaxNode, @@ -3239,42 +3237,6 @@ impl fmt::Debug for CastExpr { 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 { - 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(&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 @@ impl fmt::Debug for FnPtrType { 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 { + 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(&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 @@ impl std::fmt::Display for CastExpr { 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 @@ impl std::fmt::Display for FnPtrType { 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 f5530c5fff..62a7d4df2c 100644 --- a/crates/syntax/src/ast/node_ext.rs +++ b/crates/syntax/src/ast/node_ext.rs @@ -805,9 +805,7 @@ impl ast::SelfParam { #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub enum TypeBoundKind { /// Trait - PathType(ast::PathType), - /// for<'a> ... - ForType(ast::ForType), + PathType(Option, ast::PathType), /// use Use(ast::UseBoundGenericArgs), /// 'a @@ -817,9 +815,7 @@ pub enum TypeBoundKind { 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() {