Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--crates/hir-def/src/path/lower.rs4
-rw-r--r--crates/parser/src/grammar/generic_args.rs23
-rw-r--r--crates/parser/src/grammar/paths.rs1
-rw-r--r--crates/parser/src/grammar/types.rs9
-rw-r--r--crates/parser/test_data/parser/inline/ok/0202_typepathfn_with_coloncolon.rast38
-rw-r--r--crates/parser/test_data/parser/inline/ok/0202_typepathfn_with_coloncolon.rs1
-rw-r--r--crates/parser/test_data/parser/inline/ok/0208_associated_return_type_bounds.rast102
-rw-r--r--crates/parser/test_data/parser/inline/ok/0208_associated_return_type_bounds.rs1
-rw-r--r--crates/parser/test_data/parser/inline/ok/0209_bare_dyn_types_with_paren_as_generic_args.rast175
-rw-r--r--crates/parser/test_data/parser/inline/ok/0209_bare_dyn_types_with_paren_as_generic_args.rs4
-rw-r--r--crates/syntax/rust.ungram6
-rw-r--r--crates/syntax/src/ast/generated/nodes.rs2
12 files changed, 361 insertions, 5 deletions
diff --git a/crates/hir-def/src/path/lower.rs b/crates/hir-def/src/path/lower.rs
index 7e4b7ac34b..26d2706175 100644
--- a/crates/hir-def/src/path/lower.rs
+++ b/crates/hir-def/src/path/lower.rs
@@ -189,6 +189,10 @@ pub(super) fn lower_generic_args(
args.push(GenericArg::Type(type_ref));
}
ast::GenericArg::AssocTypeArg(assoc_type_arg) => {
+ if assoc_type_arg.param_list().is_some() {
+ // We currently ignore associated return type bounds.
+ continue;
+ }
if let Some(name_ref) = assoc_type_arg.name_ref() {
let name = name_ref.as_name();
let args = assoc_type_arg
diff --git a/crates/parser/src/grammar/generic_args.rs b/crates/parser/src/grammar/generic_args.rs
index e583a4de71..b7d72b8d33 100644
--- a/crates/parser/src/grammar/generic_args.rs
+++ b/crates/parser/src/grammar/generic_args.rs
@@ -76,6 +76,29 @@ 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<T: Foo<foo(): Send, bar(i32): Send, baz(i32, i32): Send>>() {}
+ generic_params::bounds(p);
+ m.complete(p, ASSOC_TYPE_ARG);
+ } else {
+ // test bare_dyn_types_with_paren_as_generic_args
+ // type A = S<Fn(i32)>;
+ // type A = S<Fn(i32) + Send>;
+ // type B = S<Fn(i32) -> i32>;
+ // type C = S<Fn(i32) -> i32 + Send>;
+ opt_ret_type(p);
+ let m = m.complete(p, PATH_SEGMENT).precede(p).complete(p, PATH);
+ let m = paths::type_path_for_qualifier(p, m);
+ let m = m.precede(p).complete(p, PATH_TYPE);
+ let m = types::opt_type_bounds_as_dyn_trait_type(p, m);
+ m.precede(p).complete(p, TYPE_ARG);
+ }
+ }
_ if p.at_ts(types::TYPE_FIRST) => type_arg(p),
_ => return false,
}
diff --git a/crates/parser/src/grammar/paths.rs b/crates/parser/src/grammar/paths.rs
index 26490aa97e..01b8f9e918 100644
--- a/crates/parser/src/grammar/paths.rs
+++ b/crates/parser/src/grammar/paths.rs
@@ -136,6 +136,7 @@ fn opt_path_type_args(p: &mut Parser<'_>, mode: Mode) {
Mode::Type => {
// test typepathfn_with_coloncolon
// type F = Start::(Middle) -> (Middle)::End;
+ // type GenericArg = S<Start(Middle)::End>;
if p.at(T![::]) && p.nth_at(2, T!['(']) {
p.bump(T![::]);
}
diff --git a/crates/parser/src/grammar/types.rs b/crates/parser/src/grammar/types.rs
index 26dac87956..93ef483502 100644
--- a/crates/parser/src/grammar/types.rs
+++ b/crates/parser/src/grammar/types.rs
@@ -337,13 +337,16 @@ pub(super) fn path_type_(p: &mut Parser<'_>, allow_bounds: bool) {
/// This turns a parsed PATH_TYPE or FOR_TYPE optionally into a DYN_TRAIT_TYPE
/// with a TYPE_BOUND_LIST
-fn opt_type_bounds_as_dyn_trait_type(p: &mut Parser<'_>, type_marker: CompletedMarker) {
+pub(super) fn opt_type_bounds_as_dyn_trait_type(
+ p: &mut Parser<'_>,
+ type_marker: CompletedMarker,
+) -> CompletedMarker {
assert!(matches!(
type_marker.kind(),
SyntaxKind::PATH_TYPE | SyntaxKind::FOR_TYPE | SyntaxKind::MACRO_TYPE
));
if !p.at(T![+]) {
- return;
+ return type_marker;
}
// First create a TYPE_BOUND from the completed PATH_TYPE
@@ -360,5 +363,5 @@ fn opt_type_bounds_as_dyn_trait_type(p: &mut Parser<'_>, type_marker: CompletedM
let m = generic_params::bounds_without_colon_m(p, m);
// Finally precede everything with DYN_TRAIT_TYPE
- m.precede(p).complete(p, DYN_TRAIT_TYPE);
+ m.precede(p).complete(p, DYN_TRAIT_TYPE)
}
diff --git a/crates/parser/test_data/parser/inline/ok/0202_typepathfn_with_coloncolon.rast b/crates/parser/test_data/parser/inline/ok/0202_typepathfn_with_coloncolon.rast
index b47a5a5c14..67277d0639 100644
--- a/crates/parser/test_data/parser/inline/ok/0202_typepathfn_with_coloncolon.rast
+++ b/crates/parser/test_data/parser/inline/ok/0202_typepathfn_with_coloncolon.rast
@@ -41,3 +41,41 @@ SOURCE_FILE
IDENT "End"
SEMICOLON ";"
WHITESPACE "\n"
+ TYPE_ALIAS
+ TYPE_KW "type"
+ WHITESPACE " "
+ NAME
+ IDENT "GenericArg"
+ WHITESPACE " "
+ EQ "="
+ WHITESPACE " "
+ PATH_TYPE
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "S"
+ GENERIC_ARG_LIST
+ L_ANGLE "<"
+ TYPE_ARG
+ PATH_TYPE
+ PATH
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "Start"
+ PARAM_LIST
+ L_PAREN "("
+ PARAM
+ PATH_TYPE
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "Middle"
+ R_PAREN ")"
+ COLON2 "::"
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "End"
+ R_ANGLE ">"
+ SEMICOLON ";"
+ WHITESPACE "\n"
diff --git a/crates/parser/test_data/parser/inline/ok/0202_typepathfn_with_coloncolon.rs b/crates/parser/test_data/parser/inline/ok/0202_typepathfn_with_coloncolon.rs
index 8efd93a7ff..8c54f6704b 100644
--- a/crates/parser/test_data/parser/inline/ok/0202_typepathfn_with_coloncolon.rs
+++ b/crates/parser/test_data/parser/inline/ok/0202_typepathfn_with_coloncolon.rs
@@ -1 +1,2 @@
type F = Start::(Middle) -> (Middle)::End;
+type GenericArg = S<Start(Middle)::End>;
diff --git a/crates/parser/test_data/parser/inline/ok/0208_associated_return_type_bounds.rast b/crates/parser/test_data/parser/inline/ok/0208_associated_return_type_bounds.rast
new file mode 100644
index 0000000000..2fa52068c9
--- /dev/null
+++ b/crates/parser/test_data/parser/inline/ok/0208_associated_return_type_bounds.rast
@@ -0,0 +1,102 @@
+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 "Foo"
+ GENERIC_ARG_LIST
+ L_ANGLE "<"
+ ASSOC_TYPE_ARG
+ NAME_REF
+ IDENT "foo"
+ PARAM_LIST
+ L_PAREN "("
+ R_PAREN ")"
+ COLON ":"
+ WHITESPACE " "
+ TYPE_BOUND_LIST
+ TYPE_BOUND
+ PATH_TYPE
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "Send"
+ COMMA ","
+ WHITESPACE " "
+ ASSOC_TYPE_ARG
+ NAME_REF
+ IDENT "bar"
+ PARAM_LIST
+ L_PAREN "("
+ PARAM
+ PATH_TYPE
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "i32"
+ R_PAREN ")"
+ COLON ":"
+ WHITESPACE " "
+ TYPE_BOUND_LIST
+ TYPE_BOUND
+ PATH_TYPE
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "Send"
+ COMMA ","
+ WHITESPACE " "
+ ASSOC_TYPE_ARG
+ NAME_REF
+ IDENT "baz"
+ PARAM_LIST
+ L_PAREN "("
+ PARAM
+ PATH_TYPE
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "i32"
+ COMMA ","
+ WHITESPACE " "
+ PARAM
+ PATH_TYPE
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "i32"
+ 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/0208_associated_return_type_bounds.rs b/crates/parser/test_data/parser/inline/ok/0208_associated_return_type_bounds.rs
new file mode 100644
index 0000000000..42029ac592
--- /dev/null
+++ b/crates/parser/test_data/parser/inline/ok/0208_associated_return_type_bounds.rs
@@ -0,0 +1 @@
+fn foo<T: Foo<foo(): Send, bar(i32): Send, baz(i32, i32): Send>>() {}
diff --git a/crates/parser/test_data/parser/inline/ok/0209_bare_dyn_types_with_paren_as_generic_args.rast b/crates/parser/test_data/parser/inline/ok/0209_bare_dyn_types_with_paren_as_generic_args.rast
new file mode 100644
index 0000000000..d5f97bad89
--- /dev/null
+++ b/crates/parser/test_data/parser/inline/ok/0209_bare_dyn_types_with_paren_as_generic_args.rast
@@ -0,0 +1,175 @@
+SOURCE_FILE
+ TYPE_ALIAS
+ TYPE_KW "type"
+ WHITESPACE " "
+ NAME
+ IDENT "A"
+ WHITESPACE " "
+ EQ "="
+ WHITESPACE " "
+ PATH_TYPE
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "S"
+ GENERIC_ARG_LIST
+ L_ANGLE "<"
+ TYPE_ARG
+ PATH_TYPE
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "Fn"
+ PARAM_LIST
+ L_PAREN "("
+ PARAM
+ PATH_TYPE
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "i32"
+ R_PAREN ")"
+ R_ANGLE ">"
+ SEMICOLON ";"
+ WHITESPACE "\n"
+ TYPE_ALIAS
+ TYPE_KW "type"
+ WHITESPACE " "
+ NAME
+ IDENT "A"
+ WHITESPACE " "
+ EQ "="
+ WHITESPACE " "
+ PATH_TYPE
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "S"
+ GENERIC_ARG_LIST
+ L_ANGLE "<"
+ TYPE_ARG
+ DYN_TRAIT_TYPE
+ TYPE_BOUND_LIST
+ TYPE_BOUND
+ PATH_TYPE
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "Fn"
+ PARAM_LIST
+ L_PAREN "("
+ PARAM
+ PATH_TYPE
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "i32"
+ R_PAREN ")"
+ WHITESPACE " "
+ PLUS "+"
+ WHITESPACE " "
+ TYPE_BOUND
+ PATH_TYPE
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "Send"
+ R_ANGLE ">"
+ SEMICOLON ";"
+ WHITESPACE "\n"
+ TYPE_ALIAS
+ TYPE_KW "type"
+ WHITESPACE " "
+ NAME
+ IDENT "B"
+ WHITESPACE " "
+ EQ "="
+ WHITESPACE " "
+ PATH_TYPE
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "S"
+ GENERIC_ARG_LIST
+ L_ANGLE "<"
+ TYPE_ARG
+ PATH_TYPE
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "Fn"
+ PARAM_LIST
+ L_PAREN "("
+ PARAM
+ PATH_TYPE
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "i32"
+ R_PAREN ")"
+ WHITESPACE " "
+ RET_TYPE
+ THIN_ARROW "->"
+ WHITESPACE " "
+ PATH_TYPE
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "i32"
+ R_ANGLE ">"
+ SEMICOLON ";"
+ WHITESPACE "\n"
+ TYPE_ALIAS
+ TYPE_KW "type"
+ WHITESPACE " "
+ NAME
+ IDENT "C"
+ WHITESPACE " "
+ EQ "="
+ WHITESPACE " "
+ PATH_TYPE
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "S"
+ GENERIC_ARG_LIST
+ L_ANGLE "<"
+ TYPE_ARG
+ DYN_TRAIT_TYPE
+ TYPE_BOUND_LIST
+ TYPE_BOUND
+ PATH_TYPE
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "Fn"
+ PARAM_LIST
+ L_PAREN "("
+ PARAM
+ PATH_TYPE
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "i32"
+ R_PAREN ")"
+ WHITESPACE " "
+ RET_TYPE
+ THIN_ARROW "->"
+ WHITESPACE " "
+ PATH_TYPE
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "i32"
+ WHITESPACE " "
+ PLUS "+"
+ WHITESPACE " "
+ TYPE_BOUND
+ PATH_TYPE
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "Send"
+ R_ANGLE ">"
+ SEMICOLON ";"
+ WHITESPACE "\n"
diff --git a/crates/parser/test_data/parser/inline/ok/0209_bare_dyn_types_with_paren_as_generic_args.rs b/crates/parser/test_data/parser/inline/ok/0209_bare_dyn_types_with_paren_as_generic_args.rs
new file mode 100644
index 0000000000..800002b1b8
--- /dev/null
+++ b/crates/parser/test_data/parser/inline/ok/0209_bare_dyn_types_with_paren_as_generic_args.rs
@@ -0,0 +1,4 @@
+type A = S<Fn(i32)>;
+type A = S<Fn(i32) + Send>;
+type B = S<Fn(i32) -> i32>;
+type C = S<Fn(i32) -> i32 + Send>;
diff --git a/crates/syntax/rust.ungram b/crates/syntax/rust.ungram
index 1c15a606f9..4c9027dec6 100644
--- a/crates/syntax/rust.ungram
+++ b/crates/syntax/rust.ungram
@@ -51,7 +51,9 @@ TypeArg =
Type
AssocTypeArg =
- NameRef GenericArgList? (':' TypeBoundList | ('=' Type | ConstArg))
+ NameRef
+ (GenericArgList | ParamList RetType?)?
+ (':' TypeBoundList | ('=' Type | ConstArg))
LifetimeArg =
Lifetime
@@ -581,7 +583,7 @@ ImplTraitType =
'impl' TypeBoundList
DynTraitType =
- 'dyn' TypeBoundList
+ 'dyn'? TypeBoundList
TypeBoundList =
bounds:(TypeBound ('+' TypeBound)* '+'?)
diff --git a/crates/syntax/src/ast/generated/nodes.rs b/crates/syntax/src/ast/generated/nodes.rs
index 0e84aca5c7..61f6a04c98 100644
--- a/crates/syntax/src/ast/generated/nodes.rs
+++ b/crates/syntax/src/ast/generated/nodes.rs
@@ -121,6 +121,8 @@ impl ast::HasTypeBounds for AssocTypeArg {}
impl AssocTypeArg {
pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) }
pub fn generic_arg_list(&self) -> Option<GenericArgList> { support::child(&self.syntax) }
+ pub fn param_list(&self) -> Option<ParamList> { support::child(&self.syntax) }
+ pub fn ret_type(&self) -> Option<RetType> { support::child(&self.syntax) }
pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
pub fn const_arg(&self) -> Option<ConstArg> { support::child(&self.syntax) }