@@ -16,6 +16,7 @@ pub struct InlayHintsConfig {
16
16
pub type_hints : bool ,
17
17
pub parameter_hints : bool ,
18
18
pub chaining_hints : bool ,
19
+ pub closure_return_type_hints : bool ,
19
20
pub hide_named_constructor_hints : bool ,
20
21
pub max_length : Option < usize > ,
21
22
}
@@ -24,6 +25,7 @@ pub struct InlayHintsConfig {
24
25
pub enum InlayKind {
25
26
TypeHint ,
26
27
ParameterHint ,
28
+ ClosureReturnTypeHint ,
27
29
ChainingHint ,
28
30
}
29
31
@@ -67,48 +69,86 @@ pub(crate) fn inlay_hints(
67
69
let file = sema. parse ( file_id) ;
68
70
let file = file. syntax ( ) ;
69
71
70
- let mut hints = Vec :: new ( ) ;
72
+ let mut acc = Vec :: new ( ) ;
71
73
72
- let get_hints = |node| get_hints ( & mut hints , & sema, config, node) ;
74
+ let hints = |node| hints ( & mut acc , & sema, config, node) ;
73
75
match range_limit {
74
76
Some ( FileRange { range, .. } ) => match file. covering_element ( range) {
75
- NodeOrToken :: Token ( _) => return hints ,
77
+ NodeOrToken :: Token ( _) => return acc ,
76
78
NodeOrToken :: Node ( n) => n
77
79
. descendants ( )
78
80
. filter ( |descendant| range. contains_range ( descendant. text_range ( ) ) )
79
- . for_each ( get_hints ) ,
81
+ . for_each ( hints ) ,
80
82
} ,
81
- None => file. descendants ( ) . for_each ( get_hints ) ,
83
+ None => file. descendants ( ) . for_each ( hints ) ,
82
84
} ;
83
85
84
- hints
86
+ acc
85
87
}
86
88
87
- fn get_hints (
89
+ fn hints (
88
90
hints : & mut Vec < InlayHint > ,
89
91
sema : & Semantics < RootDatabase > ,
90
92
config : & InlayHintsConfig ,
91
93
node : SyntaxNode ,
92
94
) {
95
+ let krate = sema. scope ( & node) . module ( ) . map ( |it| it. krate ( ) ) ;
96
+ let famous_defs = FamousDefs ( sema, krate) ;
93
97
if let Some ( expr) = ast:: Expr :: cast ( node. clone ( ) ) {
94
- get_chaining_hints ( hints, sema, config, & expr) ;
98
+ chaining_hints ( hints, sema, & famous_defs , config, & expr) ;
95
99
match expr {
96
100
ast:: Expr :: CallExpr ( it) => {
97
- get_param_name_hints ( hints, sema, config, ast:: Expr :: from ( it) ) ;
101
+ param_name_hints ( hints, sema, config, ast:: Expr :: from ( it) ) ;
98
102
}
99
103
ast:: Expr :: MethodCallExpr ( it) => {
100
- get_param_name_hints ( hints, sema, config, ast:: Expr :: from ( it) ) ;
104
+ param_name_hints ( hints, sema, config, ast:: Expr :: from ( it) ) ;
105
+ }
106
+ ast:: Expr :: ClosureExpr ( it) => {
107
+ closure_ret_hints ( hints, sema, & famous_defs, config, it) ;
101
108
}
102
109
_ => ( ) ,
103
110
}
104
111
} else if let Some ( it) = ast:: IdentPat :: cast ( node) {
105
- get_bind_pat_hints ( hints, sema, config, & it) ;
112
+ bind_pat_hints ( hints, sema, config, & it) ;
106
113
}
107
114
}
108
115
109
- fn get_chaining_hints (
116
+ fn closure_ret_hints (
110
117
acc : & mut Vec < InlayHint > ,
111
118
sema : & Semantics < RootDatabase > ,
119
+ famous_defs : & FamousDefs ,
120
+ config : & InlayHintsConfig ,
121
+ closure : ast:: ClosureExpr ,
122
+ ) -> Option < ( ) > {
123
+ if !config. closure_return_type_hints {
124
+ return None ;
125
+ }
126
+
127
+ let closure = sema. descend_node_into_attributes ( closure. clone ( ) ) . pop ( ) ?;
128
+
129
+ let param_list = match closure. body ( ) {
130
+ Some ( ast:: Expr :: BlockExpr ( _) ) => closure. param_list ( ) ?,
131
+ _ => return None ,
132
+ } ;
133
+ let ty = sema. type_of_expr ( & ast:: Expr :: ClosureExpr ( closure) ) ?. adjusted ( ) ;
134
+ let callable = ty. as_callable ( sema. db ) ?;
135
+ let ty = callable. return_type ( ) ;
136
+ if ty. is_unit ( ) {
137
+ return None ;
138
+ }
139
+ acc. push ( InlayHint {
140
+ range : param_list. syntax ( ) . text_range ( ) ,
141
+ kind : InlayKind :: ClosureReturnTypeHint ,
142
+ label : hint_iterator ( sema, & famous_defs, config, & ty)
143
+ . unwrap_or_else ( || ty. display_truncated ( sema. db , config. max_length ) . to_string ( ) . into ( ) ) ,
144
+ } ) ;
145
+ Some ( ( ) )
146
+ }
147
+
148
+ fn chaining_hints (
149
+ acc : & mut Vec < InlayHint > ,
150
+ sema : & Semantics < RootDatabase > ,
151
+ famous_defs : & FamousDefs ,
112
152
config : & InlayHintsConfig ,
113
153
expr : & ast:: Expr ,
114
154
) -> Option < ( ) > {
@@ -122,8 +162,6 @@ fn get_chaining_hints(
122
162
123
163
let descended = sema. descend_node_into_attributes ( expr. clone ( ) ) . pop ( ) ;
124
164
let desc_expr = descended. as_ref ( ) . unwrap_or ( expr) ;
125
- let krate = sema. scope ( desc_expr. syntax ( ) ) . module ( ) . map ( |it| it. krate ( ) ) ;
126
- let famous_defs = FamousDefs ( sema, krate) ;
127
165
128
166
let mut tokens = expr
129
167
. syntax ( )
@@ -167,7 +205,7 @@ fn get_chaining_hints(
167
205
Some ( ( ) )
168
206
}
169
207
170
- fn get_param_name_hints (
208
+ fn param_name_hints (
171
209
acc : & mut Vec < InlayHint > ,
172
210
sema : & Semantics < RootDatabase > ,
173
211
config : & InlayHintsConfig ,
@@ -207,7 +245,7 @@ fn get_param_name_hints(
207
245
Some ( ( ) )
208
246
}
209
247
210
- fn get_bind_pat_hints (
248
+ fn bind_pat_hints (
211
249
acc : & mut Vec < InlayHint > ,
212
250
sema : & Semantics < RootDatabase > ,
213
251
config : & InlayHintsConfig ,
@@ -567,13 +605,21 @@ mod tests {
567
605
568
606
use crate :: { fixture, inlay_hints:: InlayHintsConfig } ;
569
607
608
+ const DISABLED_CONFIG : InlayHintsConfig = InlayHintsConfig {
609
+ render_colons : false ,
610
+ type_hints : false ,
611
+ parameter_hints : false ,
612
+ chaining_hints : false ,
613
+ hide_named_constructor_hints : false ,
614
+ closure_return_type_hints : false ,
615
+ max_length : None ,
616
+ } ;
570
617
const TEST_CONFIG : InlayHintsConfig = InlayHintsConfig {
571
- render_colons : true ,
572
618
type_hints : true ,
573
619
parameter_hints : true ,
574
620
chaining_hints : true ,
575
- hide_named_constructor_hints : false ,
576
- max_length : None ,
621
+ closure_return_type_hints : true ,
622
+ .. DISABLED_CONFIG
577
623
} ;
578
624
579
625
#[ track_caller]
@@ -584,46 +630,19 @@ mod tests {
584
630
#[ track_caller]
585
631
fn check_params ( ra_fixture : & str ) {
586
632
check_with_config (
587
- InlayHintsConfig {
588
- render_colons : true ,
589
- parameter_hints : true ,
590
- type_hints : false ,
591
- chaining_hints : false ,
592
- hide_named_constructor_hints : false ,
593
- max_length : None ,
594
- } ,
633
+ InlayHintsConfig { parameter_hints : true , ..DISABLED_CONFIG } ,
595
634
ra_fixture,
596
635
) ;
597
636
}
598
637
599
638
#[ track_caller]
600
639
fn check_types ( ra_fixture : & str ) {
601
- check_with_config (
602
- InlayHintsConfig {
603
- render_colons : true ,
604
- parameter_hints : false ,
605
- type_hints : true ,
606
- chaining_hints : false ,
607
- hide_named_constructor_hints : false ,
608
- max_length : None ,
609
- } ,
610
- ra_fixture,
611
- ) ;
640
+ check_with_config ( InlayHintsConfig { type_hints : true , ..DISABLED_CONFIG } , ra_fixture) ;
612
641
}
613
642
614
643
#[ track_caller]
615
644
fn check_chains ( ra_fixture : & str ) {
616
- check_with_config (
617
- InlayHintsConfig {
618
- render_colons : true ,
619
- parameter_hints : false ,
620
- type_hints : false ,
621
- chaining_hints : true ,
622
- hide_named_constructor_hints : false ,
623
- max_length : None ,
624
- } ,
625
- ra_fixture,
626
- ) ;
645
+ check_with_config ( InlayHintsConfig { chaining_hints : true , ..DISABLED_CONFIG } , ra_fixture) ;
627
646
}
628
647
629
648
#[ track_caller]
@@ -646,14 +665,7 @@ mod tests {
646
665
#[ test]
647
666
fn hints_disabled ( ) {
648
667
check_with_config (
649
- InlayHintsConfig {
650
- render_colons : true ,
651
- type_hints : false ,
652
- parameter_hints : false ,
653
- chaining_hints : false ,
654
- hide_named_constructor_hints : false ,
655
- max_length : None ,
656
- } ,
668
+ InlayHintsConfig { render_colons : true , ..DISABLED_CONFIG } ,
657
669
r#"
658
670
fn foo(a: i32, b: i32) -> i32 { a + b }
659
671
fn main() {
@@ -1102,14 +1114,7 @@ fn main() {
1102
1114
let expected = extract_annotations ( & * analysis. file_text ( file_id) . unwrap ( ) ) ;
1103
1115
let inlay_hints = analysis
1104
1116
. inlay_hints (
1105
- & InlayHintsConfig {
1106
- render_colons : true ,
1107
- parameter_hints : false ,
1108
- type_hints : true ,
1109
- chaining_hints : false ,
1110
- hide_named_constructor_hints : false ,
1111
- max_length : None ,
1112
- } ,
1117
+ & InlayHintsConfig { type_hints : true , ..DISABLED_CONFIG } ,
1113
1118
file_id,
1114
1119
Some ( FileRange {
1115
1120
file_id,
@@ -1418,7 +1423,7 @@ fn main() {
1418
1423
parameter_hints : true ,
1419
1424
chaining_hints : true ,
1420
1425
hide_named_constructor_hints : true ,
1421
- max_length : None ,
1426
+ .. DISABLED_CONFIG
1422
1427
} ,
1423
1428
r#"
1424
1429
//- minicore: try, option
@@ -1546,13 +1551,14 @@ fn fallible() -> ControlFlow<()> {
1546
1551
fn main() {
1547
1552
let mut start = 0;
1548
1553
//^^^^^ i32
1549
- (0..2).for_each(|increment| { start += increment; });
1554
+ (0..2).for_each(|increment | { start += increment; });
1550
1555
//^^^^^^^^^ i32
1551
1556
1552
1557
let multiply =
1553
1558
//^^^^^^^^ |i32, i32| -> i32
1554
1559
| a, b| a * b
1555
1560
//^ i32 ^ i32
1561
+
1556
1562
;
1557
1563
1558
1564
let _: i32 = multiply(1, 2);
@@ -1561,6 +1567,8 @@ fn main() {
1561
1567
1562
1568
let return_42 = || 42;
1563
1569
//^^^^^^^^^ || -> i32
1570
+ || { 42 };
1571
+ //^^ i32
1564
1572
}"# ,
1565
1573
) ;
1566
1574
}
@@ -1590,14 +1598,7 @@ fn main() {
1590
1598
#[ test]
1591
1599
fn chaining_hints_ignore_comments ( ) {
1592
1600
check_expect (
1593
- InlayHintsConfig {
1594
- render_colons : true ,
1595
- parameter_hints : false ,
1596
- type_hints : false ,
1597
- chaining_hints : true ,
1598
- hide_named_constructor_hints : false ,
1599
- max_length : None ,
1600
- } ,
1601
+ InlayHintsConfig { type_hints : false , chaining_hints : true , ..DISABLED_CONFIG } ,
1601
1602
r#"
1602
1603
struct A(B);
1603
1604
impl A { fn into_b(self) -> B { self.0 } }
@@ -1648,14 +1649,7 @@ fn main() {
1648
1649
#[ test]
1649
1650
fn struct_access_chaining_hints ( ) {
1650
1651
check_expect (
1651
- InlayHintsConfig {
1652
- render_colons : true ,
1653
- parameter_hints : false ,
1654
- type_hints : false ,
1655
- chaining_hints : true ,
1656
- hide_named_constructor_hints : false ,
1657
- max_length : None ,
1658
- } ,
1652
+ InlayHintsConfig { chaining_hints : true , ..DISABLED_CONFIG } ,
1659
1653
r#"
1660
1654
struct A { pub b: B }
1661
1655
struct B { pub c: C }
@@ -1694,14 +1688,7 @@ fn main() {
1694
1688
#[ test]
1695
1689
fn generic_chaining_hints ( ) {
1696
1690
check_expect (
1697
- InlayHintsConfig {
1698
- render_colons : true ,
1699
- parameter_hints : false ,
1700
- type_hints : false ,
1701
- chaining_hints : true ,
1702
- hide_named_constructor_hints : false ,
1703
- max_length : None ,
1704
- } ,
1691
+ InlayHintsConfig { chaining_hints : true , ..DISABLED_CONFIG } ,
1705
1692
r#"
1706
1693
struct A<T>(T);
1707
1694
struct B<T>(T);
@@ -1741,14 +1728,7 @@ fn main() {
1741
1728
#[ test]
1742
1729
fn shorten_iterator_chaining_hints ( ) {
1743
1730
check_expect (
1744
- InlayHintsConfig {
1745
- render_colons : true ,
1746
- parameter_hints : false ,
1747
- type_hints : false ,
1748
- chaining_hints : true ,
1749
- hide_named_constructor_hints : false ,
1750
- max_length : None ,
1751
- } ,
1731
+ InlayHintsConfig { chaining_hints : true , ..DISABLED_CONFIG } ,
1752
1732
r#"
1753
1733
//- minicore: iterators
1754
1734
use core::iter;
0 commit comments