@@ -697,7 +697,9 @@ impl FunctionBody {
697697 }
698698 } ;
699699
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+
701703 let ( is_const, expr, ty) = loop {
702704 let anc = ancestors. next ( ) ?;
703705 break match_ast ! {
@@ -1346,93 +1348,144 @@ fn format_function(
13461348 let const_kw = if fun. mods . is_const { "const " } else { "" } ;
13471349 let async_kw = if fun. control_flow . is_async { "async " } else { "" } ;
13481350 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) ;
13501352 match ctx. config . snippet_cap {
13511353 Some ( _) => format_to ! (
13521354 fn_def,
1353- "\n \n {}{}{}{}fn $0{}{}{}{} " ,
1355+ "\n \n {}{}{}{}fn $0{}" ,
13541356 new_indent,
13551357 const_kw,
13561358 async_kw,
13571359 unsafe_kw,
13581360 fun. name,
1359- generic_params,
1360- params,
1361- where_clause
13621361 ) ,
13631362 None => format_to ! (
13641363 fn_def,
1365- "\n \n {}{}{}{}fn {}{}{}{} " ,
1364+ "\n \n {}{}{}{}fn {}" ,
13661365 new_indent,
13671366 const_kw,
13681367 async_kw,
13691368 unsafe_kw,
13701369 fun. name,
1371- generic_params,
1372- params,
1373- where_clause,
13741370 ) ,
13751371 }
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+
13761383 if let Some ( ret_ty) = ret_ty {
13771384 format_to ! ( fn_def, " {}" , ret_ty) ;
13781385 }
1386+
13791387 format_to ! ( fn_def, " {}" , body) ;
13801388
13811389 fn_def
13821390}
13831391
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)
13931408 } ) ;
13941409
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+ }
13961412
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+ }
13991428
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+ } ,
14091440 }
14101441}
14111442
1412- fn filter_generic_param_list (
1443+ fn make_where_clause (
14131444 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)
14261452}
14271453
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 ,
14321474 }
14331475}
14341476
14351477impl 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+
14361489 fn make_param_list ( & self , ctx : & AssistContext , module : hir:: Module ) -> ast:: ParamList {
14371490 let self_param = self . self_param . clone ( ) ;
14381491 let params = self . params . iter ( ) . map ( |param| param. to_param ( ctx, module) ) ;
@@ -4906,6 +4959,29 @@ fn func<T>(i: T) where T: Debug {
49064959 fun_name(i);
49074960}
49084961
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+
49094985fn $0fun_name<T>(i: T) where T: Debug {
49104986 foo(i);
49114987}
0 commit comments