@@ -83,17 +83,18 @@ struct FunctionTemplate {
83
83
leading_ws : String ,
84
84
fn_def : ast:: Fn ,
85
85
ret_type : ast:: RetType ,
86
+ should_render_snippet : bool ,
86
87
trailing_ws : String ,
87
88
file : FileId ,
88
89
}
89
90
90
91
impl FunctionTemplate {
91
92
fn to_string ( & self , cap : Option < SnippetCap > ) -> String {
92
- let f = match cap {
93
- Some ( cap) => {
93
+ let f = match ( cap, self . should_render_snippet ) {
94
+ ( Some ( cap) , true ) => {
94
95
render_snippet ( cap, self . fn_def . syntax ( ) , Cursor :: Replace ( self . ret_type . syntax ( ) ) )
95
96
}
96
- None => self . fn_def . to_string ( ) ,
97
+ _ => self . fn_def . to_string ( ) ,
97
98
} ;
98
99
format ! ( "{}{}{}" , self . leading_ws, f, self . trailing_ws)
99
100
}
@@ -104,7 +105,8 @@ struct FunctionBuilder {
104
105
fn_name : ast:: Name ,
105
106
type_params : Option < ast:: GenericParamList > ,
106
107
params : ast:: ParamList ,
107
- ret_type : Option < ast:: RetType > ,
108
+ ret_type : ast:: RetType ,
109
+ should_render_snippet : bool ,
108
110
file : FileId ,
109
111
needs_pub : bool ,
110
112
}
@@ -132,9 +134,44 @@ impl FunctionBuilder {
132
134
let target_module = target_module. or_else ( || ctx. sema . scope ( target. syntax ( ) ) . module ( ) ) ?;
133
135
let fn_name = fn_name ( & path) ?;
134
136
let ( type_params, params) = fn_args ( ctx, target_module, & call) ?;
135
- let ret_type = fn_ret_type ( ctx, target_module, & call) ;
136
137
137
- Some ( Self { target, fn_name, type_params, params, ret_type, file, needs_pub } )
138
+ // should_render_snippet intends to express a rough level of confidence about
139
+ // the correctness of the return type.
140
+ //
141
+ // If we are able to infer some return type, and that return type is not unit, we
142
+ // don't want to render the snippet. The assumption here is in this situation the
143
+ // return type is just as likely to be correct as any other part of the generated
144
+ // function.
145
+ //
146
+ // In the case where the return type is inferred as unit it is likely that the
147
+ // user does in fact intend for this generated function to return some non unit
148
+ // type, but that the current state of their code doesn't allow that return type
149
+ // to be accurately inferred.
150
+ let ( ret_ty, should_render_snippet) = {
151
+ match ctx. sema . type_of_expr ( & ast:: Expr :: CallExpr ( call. clone ( ) ) ) {
152
+ Some ( ty) if ty. is_unknown ( ) || ty. is_unit ( ) => ( make:: ty_unit ( ) , true ) ,
153
+ Some ( ty) => {
154
+ let rendered = ty. display_source_code ( ctx. db ( ) , target_module. into ( ) ) ;
155
+ match rendered {
156
+ Ok ( rendered) => ( make:: ty ( & rendered) , false ) ,
157
+ Err ( _) => ( make:: ty_unit ( ) , true ) ,
158
+ }
159
+ }
160
+ None => ( make:: ty_unit ( ) , true ) ,
161
+ }
162
+ } ;
163
+ let ret_type = make:: ret_type ( ret_ty) ;
164
+
165
+ Some ( Self {
166
+ target,
167
+ fn_name,
168
+ type_params,
169
+ params,
170
+ ret_type,
171
+ should_render_snippet,
172
+ file,
173
+ needs_pub,
174
+ } )
138
175
}
139
176
140
177
fn render ( self ) -> FunctionTemplate {
@@ -147,7 +184,7 @@ impl FunctionBuilder {
147
184
self . type_params ,
148
185
self . params ,
149
186
fn_body,
150
- Some ( self . ret_type . unwrap_or_else ( || make :: ret_type ( make :: ty_unit ( ) ) ) ) ,
187
+ Some ( self . ret_type ) ,
151
188
) ;
152
189
let leading_ws;
153
190
let trailing_ws;
@@ -173,6 +210,7 @@ impl FunctionBuilder {
173
210
insert_offset,
174
211
leading_ws,
175
212
ret_type : fn_def. ret_type ( ) . unwrap ( ) ,
213
+ should_render_snippet : self . should_render_snippet ,
176
214
fn_def,
177
215
trailing_ws,
178
216
file : self . file ,
@@ -225,23 +263,6 @@ fn fn_args(
225
263
Some ( ( None , make:: param_list ( None , params) ) )
226
264
}
227
265
228
- fn fn_ret_type (
229
- ctx : & AssistContext ,
230
- target_module : hir:: Module ,
231
- call : & ast:: CallExpr ,
232
- ) -> Option < ast:: RetType > {
233
- let ty = ctx. sema . type_of_expr ( & ast:: Expr :: CallExpr ( call. clone ( ) ) ) ?;
234
- if ty. is_unknown ( ) {
235
- return None ;
236
- }
237
-
238
- if let Ok ( rendered) = ty. display_source_code ( ctx. db ( ) , target_module. into ( ) ) {
239
- Some ( make:: ret_type ( make:: ty ( & rendered) ) )
240
- } else {
241
- None
242
- }
243
- }
244
-
245
266
/// Makes duplicate argument names unique by appending incrementing numbers.
246
267
///
247
268
/// ```
@@ -565,7 +586,7 @@ impl Baz {
565
586
}
566
587
}
567
588
568
- fn bar(baz: Baz) ${0: -> Baz} {
589
+ fn bar(baz: Baz) -> Baz {
569
590
todo!()
570
591
}
571
592
" ,
@@ -1092,7 +1113,7 @@ fn main() {
1092
1113
let x: u32 = foo();
1093
1114
}
1094
1115
1095
- fn foo() ${0: -> u32} {
1116
+ fn foo() -> u32 {
1096
1117
todo!()
1097
1118
}
1098
1119
" ,
0 commit comments