Skip to content

Commit fa2340a

Browse files
committed
Parse associated return type bounds
1 parent d7d8971 commit fa2340a

12 files changed

+361
-5
lines changed

crates/hir-def/src/path/lower.rs

+4
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,10 @@ pub(super) fn lower_generic_args(
189189
args.push(GenericArg::Type(type_ref));
190190
}
191191
ast::GenericArg::AssocTypeArg(assoc_type_arg) => {
192+
if assoc_type_arg.param_list().is_some() {
193+
// We currently ignore associated return type bounds.
194+
continue;
195+
}
192196
if let Some(name_ref) = assoc_type_arg.name_ref() {
193197
let name = name_ref.as_name();
194198
let args = assoc_type_arg

crates/parser/src/grammar/generic_args.rs

+23
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,29 @@ fn generic_arg(p: &mut Parser<'_>) -> bool {
7676
}
7777
}
7878
}
79+
IDENT if p.nth_at(1, T!['(']) => {
80+
let m = p.start();
81+
name_ref(p);
82+
params::param_list_fn_trait(p);
83+
if p.at(T![:]) && !p.at(T![::]) {
84+
// test associated_return_type_bounds
85+
// fn foo<T: Foo<foo(): Send, bar(i32): Send, baz(i32, i32): Send>>() {}
86+
generic_params::bounds(p);
87+
m.complete(p, ASSOC_TYPE_ARG);
88+
} else {
89+
// test bare_dyn_types_with_paren_as_generic_args
90+
// type A = S<Fn(i32)>;
91+
// type A = S<Fn(i32) + Send>;
92+
// type B = S<Fn(i32) -> i32>;
93+
// type C = S<Fn(i32) -> i32 + Send>;
94+
opt_ret_type(p);
95+
let m = m.complete(p, PATH_SEGMENT).precede(p).complete(p, PATH);
96+
let m = paths::type_path_for_qualifier(p, m);
97+
let m = m.precede(p).complete(p, PATH_TYPE);
98+
let m = types::opt_type_bounds_as_dyn_trait_type(p, m);
99+
m.precede(p).complete(p, TYPE_ARG);
100+
}
101+
}
79102
_ if p.at_ts(types::TYPE_FIRST) => type_arg(p),
80103
_ => return false,
81104
}

crates/parser/src/grammar/paths.rs

+1
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ fn opt_path_type_args(p: &mut Parser<'_>, mode: Mode) {
136136
Mode::Type => {
137137
// test typepathfn_with_coloncolon
138138
// type F = Start::(Middle) -> (Middle)::End;
139+
// type GenericArg = S<Start(Middle)::End>;
139140
if p.at(T![::]) && p.nth_at(2, T!['(']) {
140141
p.bump(T![::]);
141142
}

crates/parser/src/grammar/types.rs

+6-3
Original file line numberDiff line numberDiff line change
@@ -337,13 +337,16 @@ pub(super) fn path_type_(p: &mut Parser<'_>, allow_bounds: bool) {
337337

338338
/// This turns a parsed PATH_TYPE or FOR_TYPE optionally into a DYN_TRAIT_TYPE
339339
/// with a TYPE_BOUND_LIST
340-
fn opt_type_bounds_as_dyn_trait_type(p: &mut Parser<'_>, type_marker: CompletedMarker) {
340+
pub(super) fn opt_type_bounds_as_dyn_trait_type(
341+
p: &mut Parser<'_>,
342+
type_marker: CompletedMarker,
343+
) -> CompletedMarker {
341344
assert!(matches!(
342345
type_marker.kind(),
343346
SyntaxKind::PATH_TYPE | SyntaxKind::FOR_TYPE | SyntaxKind::MACRO_TYPE
344347
));
345348
if !p.at(T![+]) {
346-
return;
349+
return type_marker;
347350
}
348351

349352
// 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
360363
let m = generic_params::bounds_without_colon_m(p, m);
361364

362365
// Finally precede everything with DYN_TRAIT_TYPE
363-
m.precede(p).complete(p, DYN_TRAIT_TYPE);
366+
m.precede(p).complete(p, DYN_TRAIT_TYPE)
364367
}

crates/parser/test_data/parser/inline/ok/0202_typepathfn_with_coloncolon.rast

+38
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,41 @@ SOURCE_FILE
4141
IDENT "End"
4242
SEMICOLON ";"
4343
WHITESPACE "\n"
44+
TYPE_ALIAS
45+
TYPE_KW "type"
46+
WHITESPACE " "
47+
NAME
48+
IDENT "GenericArg"
49+
WHITESPACE " "
50+
EQ "="
51+
WHITESPACE " "
52+
PATH_TYPE
53+
PATH
54+
PATH_SEGMENT
55+
NAME_REF
56+
IDENT "S"
57+
GENERIC_ARG_LIST
58+
L_ANGLE "<"
59+
TYPE_ARG
60+
PATH_TYPE
61+
PATH
62+
PATH
63+
PATH_SEGMENT
64+
NAME_REF
65+
IDENT "Start"
66+
PARAM_LIST
67+
L_PAREN "("
68+
PARAM
69+
PATH_TYPE
70+
PATH
71+
PATH_SEGMENT
72+
NAME_REF
73+
IDENT "Middle"
74+
R_PAREN ")"
75+
COLON2 "::"
76+
PATH_SEGMENT
77+
NAME_REF
78+
IDENT "End"
79+
R_ANGLE ">"
80+
SEMICOLON ";"
81+
WHITESPACE "\n"
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
type F = Start::(Middle) -> (Middle)::End;
2+
type GenericArg = S<Start(Middle)::End>;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
SOURCE_FILE
2+
FN
3+
FN_KW "fn"
4+
WHITESPACE " "
5+
NAME
6+
IDENT "foo"
7+
GENERIC_PARAM_LIST
8+
L_ANGLE "<"
9+
TYPE_PARAM
10+
NAME
11+
IDENT "T"
12+
COLON ":"
13+
WHITESPACE " "
14+
TYPE_BOUND_LIST
15+
TYPE_BOUND
16+
PATH_TYPE
17+
PATH
18+
PATH_SEGMENT
19+
NAME_REF
20+
IDENT "Foo"
21+
GENERIC_ARG_LIST
22+
L_ANGLE "<"
23+
ASSOC_TYPE_ARG
24+
NAME_REF
25+
IDENT "foo"
26+
PARAM_LIST
27+
L_PAREN "("
28+
R_PAREN ")"
29+
COLON ":"
30+
WHITESPACE " "
31+
TYPE_BOUND_LIST
32+
TYPE_BOUND
33+
PATH_TYPE
34+
PATH
35+
PATH_SEGMENT
36+
NAME_REF
37+
IDENT "Send"
38+
COMMA ","
39+
WHITESPACE " "
40+
ASSOC_TYPE_ARG
41+
NAME_REF
42+
IDENT "bar"
43+
PARAM_LIST
44+
L_PAREN "("
45+
PARAM
46+
PATH_TYPE
47+
PATH
48+
PATH_SEGMENT
49+
NAME_REF
50+
IDENT "i32"
51+
R_PAREN ")"
52+
COLON ":"
53+
WHITESPACE " "
54+
TYPE_BOUND_LIST
55+
TYPE_BOUND
56+
PATH_TYPE
57+
PATH
58+
PATH_SEGMENT
59+
NAME_REF
60+
IDENT "Send"
61+
COMMA ","
62+
WHITESPACE " "
63+
ASSOC_TYPE_ARG
64+
NAME_REF
65+
IDENT "baz"
66+
PARAM_LIST
67+
L_PAREN "("
68+
PARAM
69+
PATH_TYPE
70+
PATH
71+
PATH_SEGMENT
72+
NAME_REF
73+
IDENT "i32"
74+
COMMA ","
75+
WHITESPACE " "
76+
PARAM
77+
PATH_TYPE
78+
PATH
79+
PATH_SEGMENT
80+
NAME_REF
81+
IDENT "i32"
82+
R_PAREN ")"
83+
COLON ":"
84+
WHITESPACE " "
85+
TYPE_BOUND_LIST
86+
TYPE_BOUND
87+
PATH_TYPE
88+
PATH
89+
PATH_SEGMENT
90+
NAME_REF
91+
IDENT "Send"
92+
R_ANGLE ">"
93+
R_ANGLE ">"
94+
PARAM_LIST
95+
L_PAREN "("
96+
R_PAREN ")"
97+
WHITESPACE " "
98+
BLOCK_EXPR
99+
STMT_LIST
100+
L_CURLY "{"
101+
R_CURLY "}"
102+
WHITESPACE "\n"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
fn foo<T: Foo<foo(): Send, bar(i32): Send, baz(i32, i32): Send>>() {}

0 commit comments

Comments
 (0)