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