From 21e6058ab73fd915207433d4924b04f702061309 Mon Sep 17 00:00:00 2001 From: Chayim Refael Friedman Date: Mon, 26 Aug 2024 01:45:52 +0300 Subject: [PATCH] Fix Return Type Syntax to include `..` (i.e. `method(..)` and not `method()`) as specified in the RFC --- crates/parser/src/grammar/generic_args.rs | 13 +++-- crates/parser/src/grammar/generic_params.rs | 3 +- crates/parser/src/grammar/paths.rs | 21 ++++++-- crates/parser/src/syntax_kind/generated.rs | 1 + crates/parser/test_data/generated/runner.rs | 14 ++++-- .../ok/associated_return_type_bounds.rs | 1 - .../return_type_syntax_assoc_type_bound.rast | 49 ++++++++++++++++++ .../ok/return_type_syntax_assoc_type_bound.rs | 1 + .../inline/ok/return_type_syntax_in_path.rast | 50 +++++++++++++++++++ .../inline/ok/return_type_syntax_in_path.rs | 4 ++ crates/syntax/rust.ungram | 6 ++- crates/syntax/src/ast/generated/nodes.rs | 36 +++++++++++++ 12 files changed, 183 insertions(+), 16 deletions(-) delete mode 100644 crates/parser/test_data/parser/inline/ok/associated_return_type_bounds.rs create mode 100644 crates/parser/test_data/parser/inline/ok/return_type_syntax_assoc_type_bound.rast create mode 100644 crates/parser/test_data/parser/inline/ok/return_type_syntax_assoc_type_bound.rs create mode 100644 crates/parser/test_data/parser/inline/ok/return_type_syntax_in_path.rast create mode 100644 crates/parser/test_data/parser/inline/ok/return_type_syntax_in_path.rs diff --git a/crates/parser/src/grammar/generic_args.rs b/crates/parser/src/grammar/generic_args.rs index 249be2a333..c62c8a9d3f 100644 --- a/crates/parser/src/grammar/generic_args.rs +++ b/crates/parser/src/grammar/generic_args.rs @@ -102,13 +102,18 @@ fn generic_arg(p: &mut Parser<'_>) -> bool { IDENT if p.nth_at(1, T!['(']) => { let m = p.start(); name_ref(p); - params::param_list_fn_trait(p); - if p.at(T![:]) && !p.at(T![::]) { - // test associated_return_type_bounds - // fn foo>() {} + if p.nth_at(1, T![..]) { + let rtn = p.start(); + p.bump(T!['(']); + p.bump(T![..]); + p.expect(T![')']); + rtn.complete(p, RETURN_TYPE_SYNTAX); + // test return_type_syntax_assoc_type_bound + // fn foo>() {} generic_params::bounds(p); m.complete(p, ASSOC_TYPE_ARG); } else { + params::param_list_fn_trait(p); // test bare_dyn_types_with_paren_as_generic_args // type A = S; // type A = S; diff --git a/crates/parser/src/grammar/generic_params.rs b/crates/parser/src/grammar/generic_params.rs index cf80a535ac..e0fa753fa7 100644 --- a/crates/parser/src/grammar/generic_params.rs +++ b/crates/parser/src/grammar/generic_params.rs @@ -119,8 +119,7 @@ fn lifetime_bounds(p: &mut Parser<'_>) { // test type_param_bounds // struct S; pub(super) fn bounds(p: &mut Parser<'_>) { - assert!(p.at(T![:])); - p.bump(T![:]); + p.expect(T![:]); bounds_without_colon(p); } diff --git a/crates/parser/src/grammar/paths.rs b/crates/parser/src/grammar/paths.rs index 01b8f9e918..09db921803 100644 --- a/crates/parser/src/grammar/paths.rs +++ b/crates/parser/src/grammar/paths.rs @@ -140,11 +140,24 @@ fn opt_path_type_args(p: &mut Parser<'_>, mode: Mode) { if p.at(T![::]) && p.nth_at(2, T!['(']) { p.bump(T![::]); } - // test path_fn_trait_args - // type F = Box ()>; if p.at(T!['(']) { - params::param_list_fn_trait(p); - opt_ret_type(p); + if p.nth_at(1, T![..]) { + // test return_type_syntax_in_path + // fn foo() + // where + // T::method(..): Send, + // {} + let rtn = p.start(); + p.bump(T!['(']); + p.bump(T![..]); + p.expect(T![')']); + rtn.complete(p, RETURN_TYPE_SYNTAX); + } else { + // test path_fn_trait_args + // type F = Box ()>; + params::param_list_fn_trait(p); + opt_ret_type(p); + } } else { generic_args::opt_generic_arg_list(p, false); } diff --git a/crates/parser/src/syntax_kind/generated.rs b/crates/parser/src/syntax_kind/generated.rs index eaacd88e3e..00f212487a 100644 --- a/crates/parser/src/syntax_kind/generated.rs +++ b/crates/parser/src/syntax_kind/generated.rs @@ -253,6 +253,7 @@ pub enum SyntaxKind { RENAME, REST_PAT, RETURN_EXPR, + RETURN_TYPE_SYNTAX, RET_TYPE, SELF_PARAM, SLICE_PAT, diff --git a/crates/parser/test_data/generated/runner.rs b/crates/parser/test_data/generated/runner.rs index 1907f03b44..9ce5a2ae74 100644 --- a/crates/parser/test_data/generated/runner.rs +++ b/crates/parser/test_data/generated/runner.rs @@ -37,10 +37,6 @@ mod ok { #[test] fn assoc_type_eq() { run_and_expect_no_errors("test_data/parser/inline/ok/assoc_type_eq.rs"); } #[test] - fn associated_return_type_bounds() { - run_and_expect_no_errors("test_data/parser/inline/ok/associated_return_type_bounds.rs"); - } - #[test] fn associated_type_bounds() { run_and_expect_no_errors("test_data/parser/inline/ok/associated_type_bounds.rs"); } @@ -519,6 +515,16 @@ mod ok { #[test] fn return_expr() { run_and_expect_no_errors("test_data/parser/inline/ok/return_expr.rs"); } #[test] + fn return_type_syntax_assoc_type_bound() { + run_and_expect_no_errors( + "test_data/parser/inline/ok/return_type_syntax_assoc_type_bound.rs", + ); + } + #[test] + fn return_type_syntax_in_path() { + run_and_expect_no_errors("test_data/parser/inline/ok/return_type_syntax_in_path.rs"); + } + #[test] fn self_param() { run_and_expect_no_errors("test_data/parser/inline/ok/self_param.rs"); } #[test] fn self_param_outer_attr() { diff --git a/crates/parser/test_data/parser/inline/ok/associated_return_type_bounds.rs b/crates/parser/test_data/parser/inline/ok/associated_return_type_bounds.rs deleted file mode 100644 index 42029ac592..0000000000 --- a/crates/parser/test_data/parser/inline/ok/associated_return_type_bounds.rs +++ /dev/null @@ -1 +0,0 @@ -fn foo>() {} diff --git a/crates/parser/test_data/parser/inline/ok/return_type_syntax_assoc_type_bound.rast b/crates/parser/test_data/parser/inline/ok/return_type_syntax_assoc_type_bound.rast new file mode 100644 index 0000000000..30e0e73bbd --- /dev/null +++ b/crates/parser/test_data/parser/inline/ok/return_type_syntax_assoc_type_bound.rast @@ -0,0 +1,49 @@ +SOURCE_FILE + FN + FN_KW "fn" + WHITESPACE " " + NAME + IDENT "foo" + GENERIC_PARAM_LIST + L_ANGLE "<" + TYPE_PARAM + NAME + IDENT "T" + COLON ":" + WHITESPACE " " + TYPE_BOUND_LIST + TYPE_BOUND + PATH_TYPE + PATH + PATH_SEGMENT + NAME_REF + IDENT "Trait" + GENERIC_ARG_LIST + L_ANGLE "<" + ASSOC_TYPE_ARG + NAME_REF + IDENT "method" + RETURN_TYPE_SYNTAX + L_PAREN "(" + DOT2 ".." + R_PAREN ")" + COLON ":" + WHITESPACE " " + TYPE_BOUND_LIST + TYPE_BOUND + PATH_TYPE + PATH + PATH_SEGMENT + NAME_REF + IDENT "Send" + R_ANGLE ">" + R_ANGLE ">" + PARAM_LIST + L_PAREN "(" + R_PAREN ")" + WHITESPACE " " + BLOCK_EXPR + STMT_LIST + L_CURLY "{" + R_CURLY "}" + WHITESPACE "\n" diff --git a/crates/parser/test_data/parser/inline/ok/return_type_syntax_assoc_type_bound.rs b/crates/parser/test_data/parser/inline/ok/return_type_syntax_assoc_type_bound.rs new file mode 100644 index 0000000000..8a4cf4c3a0 --- /dev/null +++ b/crates/parser/test_data/parser/inline/ok/return_type_syntax_assoc_type_bound.rs @@ -0,0 +1 @@ +fn foo>() {} diff --git a/crates/parser/test_data/parser/inline/ok/return_type_syntax_in_path.rast b/crates/parser/test_data/parser/inline/ok/return_type_syntax_in_path.rast new file mode 100644 index 0000000000..501dccd79d --- /dev/null +++ b/crates/parser/test_data/parser/inline/ok/return_type_syntax_in_path.rast @@ -0,0 +1,50 @@ +SOURCE_FILE + FN + FN_KW "fn" + WHITESPACE " " + NAME + IDENT "foo" + GENERIC_PARAM_LIST + L_ANGLE "<" + TYPE_PARAM + NAME + IDENT "T" + R_ANGLE ">" + PARAM_LIST + L_PAREN "(" + R_PAREN ")" + WHITESPACE "\n" + WHERE_CLAUSE + WHERE_KW "where" + WHITESPACE "\n " + WHERE_PRED + PATH_TYPE + PATH + PATH + PATH_SEGMENT + NAME_REF + IDENT "T" + COLON2 "::" + PATH_SEGMENT + NAME_REF + IDENT "method" + RETURN_TYPE_SYNTAX + L_PAREN "(" + DOT2 ".." + R_PAREN ")" + COLON ":" + WHITESPACE " " + TYPE_BOUND_LIST + TYPE_BOUND + PATH_TYPE + PATH + PATH_SEGMENT + NAME_REF + IDENT "Send" + COMMA "," + WHITESPACE "\n" + BLOCK_EXPR + STMT_LIST + L_CURLY "{" + R_CURLY "}" + WHITESPACE "\n" diff --git a/crates/parser/test_data/parser/inline/ok/return_type_syntax_in_path.rs b/crates/parser/test_data/parser/inline/ok/return_type_syntax_in_path.rs new file mode 100644 index 0000000000..a9b63fb01c --- /dev/null +++ b/crates/parser/test_data/parser/inline/ok/return_type_syntax_in_path.rs @@ -0,0 +1,4 @@ +fn foo() +where + T::method(..): Send, +{} diff --git a/crates/syntax/rust.ungram b/crates/syntax/rust.ungram index 069be2df3a..ba7d8bacfb 100644 --- a/crates/syntax/rust.ungram +++ b/crates/syntax/rust.ungram @@ -38,8 +38,12 @@ PathSegment = '::'? NameRef | NameRef GenericArgList? | NameRef ParamList RetType? +| NameRef ReturnTypeSyntax | '<' Type ('as' PathType)? '>' +ReturnTypeSyntax = + '(' '..' ')' + //*************************// // Generics // @@ -59,7 +63,7 @@ TypeArg = AssocTypeArg = NameRef - (GenericArgList | ParamList RetType?)? + (GenericArgList | ParamList RetType? | ReturnTypeSyntax)? (':' TypeBoundList | ('=' Type | ConstArg)) LifetimeArg = diff --git a/crates/syntax/src/ast/generated/nodes.rs b/crates/syntax/src/ast/generated/nodes.rs index 01886d119d..bd8092d7f0 100644 --- a/crates/syntax/src/ast/generated/nodes.rs +++ b/crates/syntax/src/ast/generated/nodes.rs @@ -114,6 +114,8 @@ impl AssocTypeArg { #[inline] pub fn ret_type(&self) -> Option { support::child(&self.syntax) } #[inline] + pub fn return_type_syntax(&self) -> Option { support::child(&self.syntax) } + #[inline] pub fn ty(&self) -> Option { support::child(&self.syntax) } #[inline] pub fn eq_token(&self) -> Option { support::token(&self.syntax, T![=]) } @@ -1221,6 +1223,8 @@ impl PathSegment { #[inline] pub fn ret_type(&self) -> Option { support::child(&self.syntax) } #[inline] + pub fn return_type_syntax(&self) -> Option { support::child(&self.syntax) } + #[inline] pub fn ty(&self) -> Option { support::child(&self.syntax) } #[inline] pub fn coloncolon_token(&self) -> Option { support::token(&self.syntax, T![::]) } @@ -1485,6 +1489,19 @@ impl ReturnExpr { pub fn return_token(&self) -> Option { support::token(&self.syntax, T![return]) } } +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct ReturnTypeSyntax { + pub(crate) syntax: SyntaxNode, +} +impl ReturnTypeSyntax { + #[inline] + pub fn l_paren_token(&self) -> Option { support::token(&self.syntax, T!['(']) } + #[inline] + pub fn r_paren_token(&self) -> Option { support::token(&self.syntax, T![')']) } + #[inline] + pub fn dotdot_token(&self) -> Option { support::token(&self.syntax, T![..]) } +} + #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct SelfParam { pub(crate) syntax: SyntaxNode, @@ -3697,6 +3714,20 @@ impl AstNode for ReturnExpr { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl AstNode for ReturnTypeSyntax { + #[inline] + fn can_cast(kind: SyntaxKind) -> bool { kind == RETURN_TYPE_SYNTAX } + #[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 AstNode for SelfParam { #[inline] fn can_cast(kind: SyntaxKind) -> bool { kind == SELF_PARAM } @@ -6609,6 +6640,11 @@ impl std::fmt::Display for ReturnExpr { std::fmt::Display::fmt(self.syntax(), f) } } +impl std::fmt::Display for ReturnTypeSyntax { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} impl std::fmt::Display for SelfParam { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { std::fmt::Display::fmt(self.syntax(), f)