@@ -438,6 +438,8 @@ pub(super) fn impl_method<'a, DB: HirDatabase>(
438438 lookup
439439 . new_types ( NewTypesKey :: ImplMethod )
440440 . into_iter ( )
441+ . filter ( |ty| !ty. type_arguments ( ) . any ( |it| it. contains_unknown ( ) ) )
442+ . filter ( |_| should_continue ( ) )
441443 . flat_map ( |ty| {
442444 Impl :: all_for_type ( db, ty. clone ( ) ) . into_iter ( ) . map ( move |imp| ( ty. clone ( ) , imp) )
443445 } )
@@ -450,22 +452,10 @@ pub(super) fn impl_method<'a, DB: HirDatabase>(
450452 let fn_generics = GenericDef :: from ( it) ;
451453 let imp_generics = GenericDef :: from ( imp) ;
452454
453- // Ignore const params for now
454- let imp_type_params = imp_generics
455- . type_or_const_params ( db)
456- . into_iter ( )
457- . map ( |it| it. as_type_param ( db) )
458- . collect :: < Option < Vec < TypeParam > > > ( ) ?;
459-
460- // Ignore const params for now
461- let fn_type_params = fn_generics
462- . type_or_const_params ( db)
463- . into_iter ( )
464- . map ( |it| it. as_type_param ( db) )
465- . collect :: < Option < Vec < TypeParam > > > ( ) ?;
466-
467455 // Ignore all functions that have something to do with lifetimes as we don't check them
468- if !fn_generics. lifetime_params ( db) . is_empty ( ) {
456+ if !fn_generics. lifetime_params ( db) . is_empty ( )
457+ || !imp_generics. lifetime_params ( db) . is_empty ( )
458+ {
469459 return None ;
470460 }
471461
@@ -479,112 +469,59 @@ pub(super) fn impl_method<'a, DB: HirDatabase>(
479469 return None ;
480470 }
481471
482- // Only account for stable type parameters for now, unstable params can be default
483- // tho, for example in `Box<T, #[unstable] A: Allocator>`
484- if imp_type_params. iter ( ) . any ( |it| it. is_unstable ( db) && it. default ( db) . is_none ( ) )
485- || fn_type_params. iter ( ) . any ( |it| it. is_unstable ( db) && it. default ( db) . is_none ( ) )
486- {
472+ // Ignore functions with generics for now as they kill the performance
473+ // Also checking bounds for generics is problematic
474+ if fn_generics. type_or_const_params ( db) . len ( ) > 0 {
487475 return None ;
488476 }
489477
490- // Double check that we have fully known type
491- if ty. type_arguments ( ) . any ( |it| it. contains_unknown ( ) ) {
478+ let ret_ty = it. ret_type_with_args ( db, ty. type_arguments ( ) ) ;
479+ // Filter out functions that return references
480+ if ctx. config . enable_borrowcheck && ret_ty. contains_reference ( db) || ret_ty. is_raw_ptr ( )
481+ {
492482 return None ;
493483 }
494484
495- let non_default_fn_type_params_len =
496- fn_type_params. iter ( ) . filter ( |it| it. default ( db) . is_none ( ) ) . count ( ) ;
497-
498- // Ignore functions with generics for now as they kill the performance
499- // Also checking bounds for generics is problematic
500- if non_default_fn_type_params_len > 0 {
485+ // Ignore functions that do not change the type
486+ if ty. could_unify_with_deeply ( db, & ret_ty) {
501487 return None ;
502488 }
503489
504- let generic_params = lookup
505- . iter_types ( )
506- . collect :: < Vec < _ > > ( ) // Force take ownership
507- . into_iter ( )
508- . permutations ( non_default_fn_type_params_len) ;
490+ let self_ty =
491+ it. self_param ( db) . expect ( "No self param" ) . ty_with_args ( db, ty. type_arguments ( ) ) ;
509492
510- let exprs: Vec < _ > = generic_params
511- . filter ( |_| should_continue ( ) )
512- . filter_map ( |generics| {
513- // Insert default type params
514- let mut g = generics. into_iter ( ) ;
515- let generics: Vec < _ > = ty
516- . type_arguments ( )
517- . map ( Some )
518- . chain ( fn_type_params. iter ( ) . map ( |it| match it. default ( db) {
519- Some ( ty) => Some ( ty) ,
520- None => {
521- let generic = g. next ( ) . expect ( "Missing type param" ) ;
522- // Filter out generics that do not unify due to trait bounds
523- it. ty ( db) . could_unify_with ( db, & generic) . then_some ( generic)
524- }
525- } ) )
526- . collect :: < Option < _ > > ( ) ?;
527-
528- let ret_ty = it. ret_type_with_args (
529- db,
530- ty. type_arguments ( ) . chain ( generics. iter ( ) . cloned ( ) ) ,
531- ) ;
532- // Filter out functions that return references
533- if ctx. config . enable_borrowcheck && ret_ty. contains_reference ( db)
534- || ret_ty. is_raw_ptr ( )
535- {
536- return None ;
537- }
493+ // Ignore functions that have different self type
494+ if !self_ty. autoderef ( db) . any ( |s_ty| ty == s_ty) {
495+ return None ;
496+ }
538497
539- // Ignore functions that do not change the type
540- if ty. could_unify_with_deeply ( db, & ret_ty) {
541- return None ;
542- }
498+ let target_type_exprs = lookup. find ( db, & ty) . expect ( "Type not in lookup" ) ;
543499
544- let self_ty = it
545- . self_param ( db)
546- . expect ( "No self param" )
547- . ty_with_args ( db, ty. type_arguments ( ) . chain ( generics. iter ( ) . cloned ( ) ) ) ;
500+ // Early exit if some param cannot be filled from lookup
501+ let param_exprs: Vec < Vec < Expr > > = it
502+ . params_without_self_with_args ( db, ty. type_arguments ( ) )
503+ . into_iter ( )
504+ . map ( |field| lookup. find_autoref ( db, field. ty ( ) ) )
505+ . collect :: < Option < _ > > ( ) ?;
548506
549- // Ignore functions that have different self type
550- if !self_ty. autoderef ( db) . any ( |s_ty| ty == s_ty) {
551- return None ;
507+ let generics: Vec < _ > = ty. type_arguments ( ) . collect ( ) ;
508+ let fn_exprs: Vec < Expr > = std:: iter:: once ( target_type_exprs)
509+ . chain ( param_exprs)
510+ . multi_cartesian_product ( )
511+ . map ( |params| {
512+ let mut params = params. into_iter ( ) ;
513+ let target = Box :: new ( params. next ( ) . unwrap ( ) ) ;
514+ Expr :: Method {
515+ func : it,
516+ generics : generics. clone ( ) ,
517+ target,
518+ params : params. collect ( ) ,
552519 }
553-
554- let target_type_exprs = lookup. find ( db, & ty) . expect ( "Type not in lookup" ) ;
555-
556- // Early exit if some param cannot be filled from lookup
557- let param_exprs: Vec < Vec < Expr > > = it
558- . params_without_self_with_args (
559- db,
560- ty. type_arguments ( ) . chain ( generics. iter ( ) . cloned ( ) ) ,
561- )
562- . into_iter ( )
563- . map ( |field| lookup. find_autoref ( db, field. ty ( ) ) )
564- . collect :: < Option < _ > > ( ) ?;
565-
566- let fn_exprs: Vec < Expr > = std:: iter:: once ( target_type_exprs)
567- . chain ( param_exprs)
568- . multi_cartesian_product ( )
569- . map ( |params| {
570- let mut params = params. into_iter ( ) ;
571- let target = Box :: new ( params. next ( ) . unwrap ( ) ) ;
572- Expr :: Method {
573- func : it,
574- generics : generics. clone ( ) ,
575- target,
576- params : params. collect ( ) ,
577- }
578- } )
579- . collect ( ) ;
580-
581- lookup. insert ( ret_ty. clone ( ) , fn_exprs. iter ( ) . cloned ( ) ) ;
582- Some ( ( ret_ty, fn_exprs) )
583520 } )
584521 . collect ( ) ;
585- Some ( exprs)
522+
523+ Some ( ( ret_ty, fn_exprs) )
586524 } )
587- . flatten ( )
588525 . filter_map ( |( ty, exprs) | ty. could_unify_with_deeply ( db, & ctx. goal ) . then_some ( exprs) )
589526 . flatten ( )
590527}
0 commit comments