Skip to content

Commit

Permalink
Auto merge of #14465 - tamasfe:feat/rtn-syntax, r=Veykril
Browse files Browse the repository at this point in the history
Limited syntax support for return type notations (RTN)

Experimental RTN bound support was recently merged into rustc (rust-lang/rust#109417), the goal of this PR is to allow experimentation without syntax errors everywhere.

The parsing implemented currently aligns with the state of the tracking issue, it only supports the form `T<foo(..): Bounds>`. The parser always checks for the presence of `..` to disambiguate from `Fn*()` types, this is not ideal but I didn't want to spend too much time as it is an experimental feature.
  • Loading branch information
bors committed Apr 1, 2023
2 parents 1ce25f1 + 25910bc commit 1ebac28
Show file tree
Hide file tree
Showing 8 changed files with 103 additions and 2 deletions.
3 changes: 3 additions & 0 deletions crates/hir-def/src/path/lower.rs
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,9 @@ pub(super) fn lower_generic_args(
let arg = ConstRefOrPath::from_expr_opt(arg.expr());
args.push(GenericArg::Const(arg))
}
ast::GenericArg::ReturnTypeArg(_) => {
// FIXME: return type notation is experimental, we don't do anything with it yet.
}
}
}

Expand Down
18 changes: 18 additions & 0 deletions crates/parser/src/grammar/generic_args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ fn generic_arg(p: &mut Parser<'_>) -> bool {
}
}
}
IDENT if p.nth(1) == T!['('] && p.nth_at(2, T![..]) => return_type_arg(p),
_ if p.at_ts(types::TYPE_FIRST) => type_arg(p),
_ => return false,
}
Expand Down Expand Up @@ -139,3 +140,20 @@ fn type_arg(p: &mut Parser<'_>) {
types::type_(p);
m.complete(p, TYPE_ARG);
}

// test return_type_arg
// type T = S<foo(..): Send>;
pub(super) fn return_type_arg(p: &mut Parser<'_>) {
let m = p.start();
p.expect(IDENT);
p.expect(T!['(']);
p.expect(T![..]);
p.expect(T![')']);
if !p.at(T![:]) {
p.error("expected :");
m.abandon(p);
return;
}
generic_params::bounds(p);
m.complete(p, RETURN_TYPE_ARG);
}
1 change: 1 addition & 0 deletions crates/parser/src/syntax_kind/generated.rs
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,7 @@ pub enum SyntaxKind {
GENERIC_PARAM,
LIFETIME_PARAM,
TYPE_PARAM,
RETURN_TYPE_ARG,
CONST_PARAM,
GENERIC_ARG_LIST,
LIFETIME,
Expand Down
33 changes: 33 additions & 0 deletions crates/parser/test_data/parser/inline/ok/0206_return_type_arg.rast
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
SOURCE_FILE
TYPE_ALIAS
TYPE_KW "type"
WHITESPACE " "
NAME
IDENT "T"
WHITESPACE " "
EQ "="
WHITESPACE " "
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "S"
GENERIC_ARG_LIST
L_ANGLE "<"
RETURN_TYPE_ARG
IDENT "foo"
L_PAREN "("
DOT2 ".."
R_PAREN ")"
COLON ":"
WHITESPACE " "
TYPE_BOUND_LIST
TYPE_BOUND
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "Send"
R_ANGLE ">"
SEMICOLON ";"
WHITESPACE "\n"
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
type T = S<foo(..): Send>;
4 changes: 4 additions & 0 deletions crates/syntax/rust.ungram
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ GenericArg =
| AssocTypeArg
| LifetimeArg
| ConstArg
| ReturnTypeArg

TypeArg =
Type
Expand All @@ -59,6 +60,9 @@ LifetimeArg =
ConstArg =
Expr

ReturnTypeArg =
NameRef '(' '..' ')' ':' TypeBoundList

MacroCall =
Attr* Path '!' TokenTree ';'?

Expand Down
44 changes: 42 additions & 2 deletions crates/syntax/src/ast/generated/nodes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,18 @@ impl ConstArg {
pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
}

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct ReturnTypeArg {
pub(crate) syntax: SyntaxNode,
}
impl ast::HasTypeBounds for ReturnTypeArg {}
impl ReturnTypeArg {
pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) }
pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
pub fn dotdot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![..]) }
pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
}

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct TypeBoundList {
pub(crate) syntax: SyntaxNode,
Expand Down Expand Up @@ -1516,6 +1528,7 @@ pub enum GenericArg {
AssocTypeArg(AssocTypeArg),
LifetimeArg(LifetimeArg),
ConstArg(ConstArg),
ReturnTypeArg(ReturnTypeArg),
}

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
Expand Down Expand Up @@ -1865,6 +1878,17 @@ impl AstNode for ConstArg {
}
fn syntax(&self) -> &SyntaxNode { &self.syntax }
}
impl AstNode for ReturnTypeArg {
fn can_cast(kind: SyntaxKind) -> bool { kind == RETURN_TYPE_ARG }
fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
} else {
None
}
}
fn syntax(&self) -> &SyntaxNode { &self.syntax }
}
impl AstNode for TypeBoundList {
fn can_cast(kind: SyntaxKind) -> bool { kind == TYPE_BOUND_LIST }
fn cast(syntax: SyntaxNode) -> Option<Self> {
Expand Down Expand Up @@ -3219,16 +3243,20 @@ impl From<LifetimeArg> for GenericArg {
impl From<ConstArg> for GenericArg {
fn from(node: ConstArg) -> GenericArg { GenericArg::ConstArg(node) }
}
impl From<ReturnTypeArg> for GenericArg {
fn from(node: ReturnTypeArg) -> GenericArg { GenericArg::ReturnTypeArg(node) }
}
impl AstNode for GenericArg {
fn can_cast(kind: SyntaxKind) -> bool {
matches!(kind, TYPE_ARG | ASSOC_TYPE_ARG | LIFETIME_ARG | CONST_ARG)
matches!(kind, TYPE_ARG | ASSOC_TYPE_ARG | LIFETIME_ARG | CONST_ARG | RETURN_TYPE_ARG)
}
fn cast(syntax: SyntaxNode) -> Option<Self> {
let res = match syntax.kind() {
TYPE_ARG => GenericArg::TypeArg(TypeArg { syntax }),
ASSOC_TYPE_ARG => GenericArg::AssocTypeArg(AssocTypeArg { syntax }),
LIFETIME_ARG => GenericArg::LifetimeArg(LifetimeArg { syntax }),
CONST_ARG => GenericArg::ConstArg(ConstArg { syntax }),
RETURN_TYPE_ARG => GenericArg::ReturnTypeArg(ReturnTypeArg { syntax }),
_ => return None,
};
Some(res)
Expand All @@ -3239,6 +3267,7 @@ impl AstNode for GenericArg {
GenericArg::AssocTypeArg(it) => &it.syntax,
GenericArg::LifetimeArg(it) => &it.syntax,
GenericArg::ConstArg(it) => &it.syntax,
GenericArg::ReturnTypeArg(it) => &it.syntax,
}
}
}
Expand Down Expand Up @@ -4170,7 +4199,13 @@ impl AstNode for AnyHasTypeBounds {
fn can_cast(kind: SyntaxKind) -> bool {
matches!(
kind,
ASSOC_TYPE_ARG | TRAIT | TYPE_ALIAS | LIFETIME_PARAM | TYPE_PARAM | WHERE_PRED
ASSOC_TYPE_ARG
| RETURN_TYPE_ARG
| TRAIT
| TYPE_ALIAS
| LIFETIME_PARAM
| TYPE_PARAM
| WHERE_PRED
)
}
fn cast(syntax: SyntaxNode) -> Option<Self> {
Expand Down Expand Up @@ -4333,6 +4368,11 @@ impl std::fmt::Display for ConstArg {
std::fmt::Display::fmt(self.syntax(), f)
}
}
impl std::fmt::Display for ReturnTypeArg {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self.syntax(), f)
}
}
impl std::fmt::Display for TypeBoundList {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self.syntax(), f)
Expand Down
1 change: 1 addition & 0 deletions crates/syntax/src/tests/ast_src.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@ pub(crate) const KINDS_SRC: KindsSrc<'_> = KindsSrc {
"GENERIC_PARAM",
"LIFETIME_PARAM",
"TYPE_PARAM",
"RETURN_TYPE_ARG",
"CONST_PARAM",
"GENERIC_ARG_LIST",
"LIFETIME",
Expand Down

0 comments on commit 1ebac28

Please sign in to comment.