31
31
//! }
32
32
//! ```
33
33
34
+ use hir:: HirDisplay ;
34
35
use hir:: { MacroFileId , Name , db:: ExpandDatabase } ;
35
36
use ide_db:: text_edit:: TextEdit ;
36
37
use ide_db:: {
@@ -39,7 +40,7 @@ use ide_db::{
39
40
} ;
40
41
use syntax:: {
41
42
AstNode , SmolStr , SyntaxElement , SyntaxKind , T , TextRange , ToSmolStr ,
42
- ast:: { self , HasGenericArgs , HasTypeBounds , edit_in_place:: AttrsOwnerEdit , make} ,
43
+ ast:: { self , HasTypeBounds , edit_in_place:: AttrsOwnerEdit , make} ,
43
44
format_smolstr, ted,
44
45
} ;
45
46
@@ -185,12 +186,12 @@ fn add_function_impl(
185
186
let fn_name = & func. name ( ctx. db ) ;
186
187
let sugar: & [ _ ] = if func. is_async ( ctx. db ) {
187
188
& [ AsyncSugaring :: Async , AsyncSugaring :: Desugar ]
188
- } else if func. returns_impl_future ( ctx. db ) {
189
- & [ AsyncSugaring :: Plain , AsyncSugaring :: Resugar ]
189
+ } else if let Some ( future_output ) = func. returns_impl_future ( ctx. db ) {
190
+ & [ AsyncSugaring :: Plain , AsyncSugaring :: Resugar { future_output } ]
190
191
} else {
191
192
& [ AsyncSugaring :: Plain ]
192
193
} ;
193
- for & sugaring in sugar {
194
+ for sugaring in sugar {
194
195
add_function_impl_ ( acc, ctx, replacement_range, func, impl_def, fn_name, sugaring) ;
195
196
}
196
197
}
@@ -202,9 +203,9 @@ fn add_function_impl_(
202
203
func : hir:: Function ,
203
204
impl_def : hir:: Impl ,
204
205
fn_name : & Name ,
205
- async_sugaring : AsyncSugaring ,
206
+ async_sugaring : & AsyncSugaring ,
206
207
) {
207
- let async_ = if let AsyncSugaring :: Async | AsyncSugaring :: Resugar = async_sugaring {
208
+ let async_ = if let AsyncSugaring :: Async | AsyncSugaring :: Resugar { .. } = async_sugaring {
208
209
"async "
209
210
} else {
210
211
""
@@ -248,10 +249,10 @@ fn add_function_impl_(
248
249
}
249
250
}
250
251
251
- #[ derive( Copy , Clone ) ]
252
+ #[ derive( Clone ) ]
252
253
enum AsyncSugaring {
253
254
Desugar ,
254
- Resugar ,
255
+ Resugar { future_output : hir :: Type } ,
255
256
Async ,
256
257
Plain ,
257
258
}
@@ -285,7 +286,7 @@ fn get_transformed_fn(
285
286
ctx : & CompletionContext < ' _ > ,
286
287
fn_ : ast:: Fn ,
287
288
impl_def : hir:: Impl ,
288
- async_ : AsyncSugaring ,
289
+ async_ : & AsyncSugaring ,
289
290
) -> Option < ast:: Fn > {
290
291
let trait_ = impl_def. trait_ ( ctx. db ) ?;
291
292
let source_scope = & ctx. sema . scope ( fn_. syntax ( ) ) ?;
@@ -323,31 +324,16 @@ fn get_transformed_fn(
323
324
}
324
325
fn_. async_token ( ) . unwrap ( ) . detach ( ) ;
325
326
}
326
- AsyncSugaring :: Resugar => {
327
- let ty = fn_. ret_type ( ) ?. ty ( ) ?;
328
- match & ty {
329
- // best effort guessing here
330
- ast:: Type :: ImplTraitType ( t) => {
331
- let output = t. type_bound_list ( ) ?. bounds ( ) . find_map ( |b| match b. ty ( ) ? {
332
- ast:: Type :: PathType ( p) => {
333
- let p = p. path ( ) ?. segment ( ) ?;
334
- if p. name_ref ( ) ?. text ( ) != "Future" {
335
- return None ;
336
- }
337
- match p. generic_arg_list ( ) ?. generic_args ( ) . next ( ) ? {
338
- ast:: GenericArg :: AssocTypeArg ( a)
339
- if a. name_ref ( ) ?. text ( ) == "Output" =>
340
- {
341
- a. ty ( )
342
- }
343
- _ => None ,
344
- }
345
- }
346
- _ => None ,
347
- } ) ?;
348
- ted:: replace ( ty. syntax ( ) , output. syntax ( ) ) ;
349
- }
350
- _ => ( ) ,
327
+ AsyncSugaring :: Resugar { future_output } => {
328
+ let ast_ret = fn_. ret_type ( ) ?;
329
+ if future_output. is_unit ( ) {
330
+ ted:: remove ( ast_ret. syntax ( ) ) ;
331
+ } else {
332
+ let ret = future_output
333
+ . display_source_code ( ctx. db , ctx. module . into ( ) , true )
334
+ . unwrap_or_else ( |_| "_" . to_owned ( ) ) ;
335
+ let ast_ret_ty = ast_ret. ty ( ) ?;
336
+ ted:: replace ( ast_ret_ty. syntax ( ) , make:: ty ( & ret) . syntax ( ) . clone_for_update ( ) ) ;
351
337
}
352
338
ted:: prepend_child ( fn_. syntax ( ) , make:: token ( T ! [ async ] ) ) ;
353
339
}
0 commit comments