@@ -697,7 +697,9 @@ impl FunctionBody {
697
697
}
698
698
} ;
699
699
700
- let ( mut generic_param_list, mut where_clause) = ( None , None ) ;
700
+ let mut generic_param_list = None ;
701
+ let mut where_clause = None ;
702
+
701
703
let ( is_const, expr, ty) = loop {
702
704
let anc = ancestors. next ( ) ?;
703
705
break match_ast ! {
@@ -1346,93 +1348,144 @@ fn format_function(
1346
1348
let const_kw = if fun. mods . is_const { "const " } else { "" } ;
1347
1349
let async_kw = if fun. control_flow . is_async { "async " } else { "" } ;
1348
1350
let unsafe_kw = if fun. control_flow . is_unsafe { "unsafe " } else { "" } ;
1349
- let ( generic_params, where_clause) = format_generic_params_and_where_clause ( ctx, fun) ;
1351
+ let ( generic_params, where_clause) = make_generic_params_and_where_clause ( ctx, fun) ;
1350
1352
match ctx. config . snippet_cap {
1351
1353
Some ( _) => format_to ! (
1352
1354
fn_def,
1353
- "\n \n {}{}{}{}fn $0{}{}{}{} " ,
1355
+ "\n \n {}{}{}{}fn $0{}" ,
1354
1356
new_indent,
1355
1357
const_kw,
1356
1358
async_kw,
1357
1359
unsafe_kw,
1358
1360
fun. name,
1359
- generic_params,
1360
- params,
1361
- where_clause
1362
1361
) ,
1363
1362
None => format_to ! (
1364
1363
fn_def,
1365
- "\n \n {}{}{}{}fn {}{}{}{} " ,
1364
+ "\n \n {}{}{}{}fn {}" ,
1366
1365
new_indent,
1367
1366
const_kw,
1368
1367
async_kw,
1369
1368
unsafe_kw,
1370
1369
fun. name,
1371
- generic_params,
1372
- params,
1373
- where_clause,
1374
1370
) ,
1375
1371
}
1372
+
1373
+ if let Some ( generic_params) = generic_params {
1374
+ format_to ! ( fn_def, "{}" , generic_params) ;
1375
+ }
1376
+
1377
+ format_to ! ( fn_def, "{}" , params) ;
1378
+
1379
+ if let Some ( where_clause) = where_clause {
1380
+ format_to ! ( fn_def, " {}" , where_clause) ;
1381
+ }
1382
+
1376
1383
if let Some ( ret_ty) = ret_ty {
1377
1384
format_to ! ( fn_def, " {}" , ret_ty) ;
1378
1385
}
1386
+
1379
1387
format_to ! ( fn_def, " {}" , body) ;
1380
1388
1381
1389
fn_def
1382
1390
}
1383
1391
1384
- fn format_generic_params_and_where_clause ( ctx : & AssistContext , fun : & Function ) -> ( String , String ) {
1385
- ( format_generic_param_list ( fun, ctx) , format_where_clause ( fun) )
1386
- }
1387
-
1388
- fn format_generic_param_list ( fun : & Function , ctx : & AssistContext ) -> String {
1389
- let type_params_in_descendant_paths =
1390
- fun. body . descendant_paths ( ) . filter_map ( |it| match ctx. sema . resolve_path ( & it) {
1391
- Some ( PathResolution :: TypeParam ( type_param) ) => Some ( type_param) ,
1392
- _ => None ,
1392
+ fn make_generic_params_and_where_clause (
1393
+ ctx : & AssistContext ,
1394
+ fun : & Function ,
1395
+ ) -> ( Option < ast:: GenericParamList > , Option < ast:: WhereClause > ) {
1396
+ let used_type_params = fun. type_params ( ctx) ;
1397
+
1398
+ let generic_param_list = fun
1399
+ . mods
1400
+ . generic_param_list
1401
+ . as_ref ( )
1402
+ . map ( |parent_params| make_generic_param_list ( ctx, parent_params, & used_type_params) )
1403
+ . flatten ( ) ;
1404
+
1405
+ let where_clause =
1406
+ fun. mods . where_clause . as_ref ( ) . map ( |parent_where_clause| {
1407
+ make_where_clause ( ctx, parent_where_clause, & used_type_params)
1393
1408
} ) ;
1394
1409
1395
- let type_params_in_params = fun. params . iter ( ) . filter_map ( |p| p. ty . as_type_param ( ctx. db ( ) ) ) ;
1410
+ ( generic_param_list, where_clause)
1411
+ }
1396
1412
1397
- let used_type_params: Vec < TypeParam > =
1398
- type_params_in_descendant_paths. chain ( type_params_in_params) . collect ( ) ;
1413
+ fn make_generic_param_list (
1414
+ ctx : & AssistContext ,
1415
+ parent_params : & ast:: GenericParamList ,
1416
+ used_type_params : & [ TypeParam ] ,
1417
+ ) -> Option < ast:: GenericParamList > {
1418
+ let required_generic_params: Vec < ast:: GenericParam > = parent_params
1419
+ . generic_params ( )
1420
+ . filter ( |param| param_is_required ( ctx, param, used_type_params) )
1421
+ . collect ( ) ;
1422
+ if required_generic_params. is_empty ( ) {
1423
+ None
1424
+ } else {
1425
+ Some ( make:: generic_param_list ( required_generic_params) )
1426
+ }
1427
+ }
1399
1428
1400
- match & fun. mods . generic_param_list {
1401
- Some ( list) => {
1402
- let filtered_generic_params = filter_generic_param_list ( ctx, list, used_type_params) ;
1403
- if filtered_generic_params. is_empty ( ) {
1404
- return "" . to_string ( ) ;
1405
- }
1406
- format ! ( "{}" , make:: generic_param_list( filtered_generic_params) )
1407
- }
1408
- None => "" . to_string ( ) ,
1429
+ fn param_is_required (
1430
+ ctx : & AssistContext ,
1431
+ param : & ast:: GenericParam ,
1432
+ used_type_params : & [ TypeParam ] ,
1433
+ ) -> bool {
1434
+ match param {
1435
+ ast:: GenericParam :: ConstParam ( _) | ast:: GenericParam :: LifetimeParam ( _) => true ,
1436
+ ast:: GenericParam :: TypeParam ( type_param) => match & ctx. sema . to_def ( type_param) {
1437
+ Some ( def) => used_type_params. iter ( ) . contains ( def) ,
1438
+ _ => false ,
1439
+ } ,
1409
1440
}
1410
1441
}
1411
1442
1412
- fn filter_generic_param_list (
1443
+ fn make_where_clause (
1413
1444
ctx : & AssistContext ,
1414
- list : & ast:: GenericParamList ,
1415
- used_type_params : Vec < TypeParam > ,
1416
- ) -> Vec < ast:: GenericParam > {
1417
- list. generic_params ( )
1418
- . filter ( |p| match p {
1419
- ast:: GenericParam :: ConstParam ( _) | ast:: GenericParam :: LifetimeParam ( _) => true ,
1420
- ast:: GenericParam :: TypeParam ( type_param) => match & ctx. sema . to_def ( type_param) {
1421
- Some ( def) => used_type_params. iter ( ) . contains ( def) ,
1422
- _ => false ,
1423
- } ,
1424
- } )
1425
- . collect ( )
1445
+ parent_where_clause : & ast:: WhereClause ,
1446
+ used_type_params : & [ TypeParam ] ,
1447
+ ) -> ast:: WhereClause {
1448
+ let preds = parent_where_clause
1449
+ . predicates ( )
1450
+ . filter ( |pred| pred_is_required ( ctx, pred, used_type_params) ) ;
1451
+ make:: where_clause ( preds)
1426
1452
}
1427
1453
1428
- fn format_where_clause ( fun : & Function ) -> String {
1429
- match & fun. mods . where_clause {
1430
- Some ( it) => format ! ( " {}" , it) ,
1431
- None => "" . to_string ( ) ,
1454
+ fn pred_is_required (
1455
+ ctx : & AssistContext ,
1456
+ pred : & ast:: WherePred ,
1457
+ used_type_params : & [ TypeParam ] ,
1458
+ ) -> bool {
1459
+ match resolved_type_param ( ctx, pred) {
1460
+ Some ( it) => used_type_params. contains ( & it) ,
1461
+ None => false ,
1462
+ }
1463
+ }
1464
+
1465
+ fn resolved_type_param ( ctx : & AssistContext , pred : & ast:: WherePred ) -> Option < TypeParam > {
1466
+ let path = match pred. ty ( ) ? {
1467
+ ast:: Type :: PathType ( path_type) => path_type. path ( ) ,
1468
+ _ => None ,
1469
+ } ?;
1470
+
1471
+ match ctx. sema . resolve_path ( & path) ? {
1472
+ PathResolution :: TypeParam ( type_param) => Some ( type_param) ,
1473
+ _ => None ,
1432
1474
}
1433
1475
}
1434
1476
1435
1477
impl Function {
1478
+ /// Collect all the `TypeParam`s used in the `body` and `params`.
1479
+ fn type_params ( & self , ctx : & AssistContext ) -> Vec < TypeParam > {
1480
+ let type_params_in_descendant_paths =
1481
+ self . body . descendant_paths ( ) . filter_map ( |it| match ctx. sema . resolve_path ( & it) {
1482
+ Some ( PathResolution :: TypeParam ( type_param) ) => Some ( type_param) ,
1483
+ _ => None ,
1484
+ } ) ;
1485
+ let type_params_in_params = self . params . iter ( ) . filter_map ( |p| p. ty . as_type_param ( ctx. db ( ) ) ) ;
1486
+ type_params_in_descendant_paths. chain ( type_params_in_params) . collect ( )
1487
+ }
1488
+
1436
1489
fn make_param_list ( & self , ctx : & AssistContext , module : hir:: Module ) -> ast:: ParamList {
1437
1490
let self_param = self . self_param . clone ( ) ;
1438
1491
let params = self . params . iter ( ) . map ( |param| param. to_param ( ctx, module) ) ;
@@ -4906,6 +4959,29 @@ fn func<T>(i: T) where T: Debug {
4906
4959
fun_name(i);
4907
4960
}
4908
4961
4962
+ fn $0fun_name<T>(i: T) where T: Debug {
4963
+ foo(i);
4964
+ }
4965
+ "# ,
4966
+ ) ;
4967
+ }
4968
+
4969
+ #[ test]
4970
+ fn filter_unused_where_clause ( ) {
4971
+ check_assist (
4972
+ extract_function,
4973
+ r#"
4974
+ fn func<T, U>(i: T, u: U) where T: Debug, U: Copy {
4975
+ bar(u);
4976
+ $0foo(i);$0
4977
+ }
4978
+ "# ,
4979
+ r#"
4980
+ fn func<T, U>(i: T, u: U) where T: Debug, U: Copy {
4981
+ bar(u);
4982
+ fun_name(i);
4983
+ }
4984
+
4909
4985
fn $0fun_name<T>(i: T) where T: Debug {
4910
4986
foo(i);
4911
4987
}
0 commit comments