Auto merge of #17962 - ChayimFriedman2:update-rtn, r=Veykril

fix: Fix Return Type Syntax to include `..` (i.e. `method(..)` and not `method()`) as specified in the RFC

Fixes #17952.
This commit is contained in:
bors 2024-08-26 07:51:30 +00:00
commit cd734cb7ae
12 changed files with 183 additions and 16 deletions

View file

@ -102,13 +102,18 @@ fn generic_arg(p: &mut Parser<'_>) -> bool {
IDENT if p.nth_at(1, T!['(']) => { IDENT if p.nth_at(1, T!['(']) => {
let m = p.start(); let m = p.start();
name_ref(p); name_ref(p);
params::param_list_fn_trait(p); if p.nth_at(1, T![..]) {
if p.at(T![:]) && !p.at(T![::]) { let rtn = p.start();
// test associated_return_type_bounds p.bump(T!['(']);
// fn foo<T: Foo<foo(): Send, bar(i32): Send, baz(i32, i32): Send>>() {} p.bump(T![..]);
p.expect(T![')']);
rtn.complete(p, RETURN_TYPE_SYNTAX);
// test return_type_syntax_assoc_type_bound
// fn foo<T: Trait<method(..): Send>>() {}
generic_params::bounds(p); generic_params::bounds(p);
m.complete(p, ASSOC_TYPE_ARG); m.complete(p, ASSOC_TYPE_ARG);
} else { } else {
params::param_list_fn_trait(p);
// test bare_dyn_types_with_paren_as_generic_args // test bare_dyn_types_with_paren_as_generic_args
// type A = S<Fn(i32)>; // type A = S<Fn(i32)>;
// type A = S<Fn(i32) + Send>; // type A = S<Fn(i32) + Send>;

View file

@ -119,8 +119,7 @@ fn lifetime_bounds(p: &mut Parser<'_>) {
// test type_param_bounds // test type_param_bounds
// struct S<T: 'a + ?Sized + (Copy) + ~const Drop>; // struct S<T: 'a + ?Sized + (Copy) + ~const Drop>;
pub(super) fn bounds(p: &mut Parser<'_>) { pub(super) fn bounds(p: &mut Parser<'_>) {
assert!(p.at(T![:])); p.expect(T![:]);
p.bump(T![:]);
bounds_without_colon(p); bounds_without_colon(p);
} }

View file

@ -140,11 +140,24 @@ fn opt_path_type_args(p: &mut Parser<'_>, mode: Mode) {
if p.at(T![::]) && p.nth_at(2, T!['(']) { if p.at(T![::]) && p.nth_at(2, T!['(']) {
p.bump(T![::]); p.bump(T![::]);
} }
if p.at(T!['(']) {
if p.nth_at(1, T![..]) {
// test return_type_syntax_in_path
// fn foo<T>()
// where
// T::method(..): Send,
// {}
let rtn = p.start();
p.bump(T!['(']);
p.bump(T![..]);
p.expect(T![')']);
rtn.complete(p, RETURN_TYPE_SYNTAX);
} else {
// test path_fn_trait_args // test path_fn_trait_args
// type F = Box<Fn(i32) -> ()>; // type F = Box<Fn(i32) -> ()>;
if p.at(T!['(']) {
params::param_list_fn_trait(p); params::param_list_fn_trait(p);
opt_ret_type(p); opt_ret_type(p);
}
} else { } else {
generic_args::opt_generic_arg_list(p, false); generic_args::opt_generic_arg_list(p, false);
} }

View file

@ -253,6 +253,7 @@ pub enum SyntaxKind {
RENAME, RENAME,
REST_PAT, REST_PAT,
RETURN_EXPR, RETURN_EXPR,
RETURN_TYPE_SYNTAX,
RET_TYPE, RET_TYPE,
SELF_PARAM, SELF_PARAM,
SLICE_PAT, SLICE_PAT,

View file

@ -37,10 +37,6 @@ mod ok {
#[test] #[test]
fn assoc_type_eq() { run_and_expect_no_errors("test_data/parser/inline/ok/assoc_type_eq.rs"); } fn assoc_type_eq() { run_and_expect_no_errors("test_data/parser/inline/ok/assoc_type_eq.rs"); }
#[test] #[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() { fn associated_type_bounds() {
run_and_expect_no_errors("test_data/parser/inline/ok/associated_type_bounds.rs"); run_and_expect_no_errors("test_data/parser/inline/ok/associated_type_bounds.rs");
} }
@ -519,6 +515,16 @@ mod ok {
#[test] #[test]
fn return_expr() { run_and_expect_no_errors("test_data/parser/inline/ok/return_expr.rs"); } fn return_expr() { run_and_expect_no_errors("test_data/parser/inline/ok/return_expr.rs"); }
#[test] #[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"); } fn self_param() { run_and_expect_no_errors("test_data/parser/inline/ok/self_param.rs"); }
#[test] #[test]
fn self_param_outer_attr() { fn self_param_outer_attr() {

View file

@ -1 +0,0 @@
fn foo<T: Foo<foo(): Send, bar(i32): Send, baz(i32, i32): Send>>() {}

View file

@ -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"

View file

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

View file

@ -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"

View file

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

View file

@ -38,8 +38,12 @@ PathSegment =
'::'? NameRef '::'? NameRef
| NameRef GenericArgList? | NameRef GenericArgList?
| NameRef ParamList RetType? | NameRef ParamList RetType?
| NameRef ReturnTypeSyntax
| '<' Type ('as' PathType)? '>' | '<' Type ('as' PathType)? '>'
ReturnTypeSyntax =
'(' '..' ')'
//*************************// //*************************//
// Generics // // Generics //
@ -59,7 +63,7 @@ TypeArg =
AssocTypeArg = AssocTypeArg =
NameRef NameRef
(GenericArgList | ParamList RetType?)? (GenericArgList | ParamList RetType? | ReturnTypeSyntax)?
(':' TypeBoundList | ('=' Type | ConstArg)) (':' TypeBoundList | ('=' Type | ConstArg))
LifetimeArg = LifetimeArg =

View file

@ -114,6 +114,8 @@ impl AssocTypeArg {
#[inline] #[inline]
pub fn ret_type(&self) -> Option<RetType> { support::child(&self.syntax) } pub fn ret_type(&self) -> Option<RetType> { support::child(&self.syntax) }
#[inline] #[inline]
pub fn return_type_syntax(&self) -> Option<ReturnTypeSyntax> { support::child(&self.syntax) }
#[inline]
pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) } pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
#[inline] #[inline]
pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) } pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
@ -1221,6 +1223,8 @@ impl PathSegment {
#[inline] #[inline]
pub fn ret_type(&self) -> Option<RetType> { support::child(&self.syntax) } pub fn ret_type(&self) -> Option<RetType> { support::child(&self.syntax) }
#[inline] #[inline]
pub fn return_type_syntax(&self) -> Option<ReturnTypeSyntax> { support::child(&self.syntax) }
#[inline]
pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) } pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
#[inline] #[inline]
pub fn coloncolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![::]) } pub fn coloncolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![::]) }
@ -1485,6 +1489,19 @@ impl ReturnExpr {
pub fn return_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![return]) } pub fn return_token(&self) -> Option<SyntaxToken> { 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<SyntaxToken> { support::token(&self.syntax, T!['(']) }
#[inline]
pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
#[inline]
pub fn dotdot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![..]) }
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct SelfParam { pub struct SelfParam {
pub(crate) syntax: SyntaxNode, pub(crate) syntax: SyntaxNode,
@ -3697,6 +3714,20 @@ impl AstNode for ReturnExpr {
#[inline] #[inline]
fn syntax(&self) -> &SyntaxNode { &self.syntax } 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<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
} else {
None
}
}
#[inline]
fn syntax(&self) -> &SyntaxNode { &self.syntax }
}
impl AstNode for SelfParam { impl AstNode for SelfParam {
#[inline] #[inline]
fn can_cast(kind: SyntaxKind) -> bool { kind == SELF_PARAM } 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) 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 { impl std::fmt::Display for SelfParam {
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)