@@ -34,7 +34,10 @@ use rustc_infer::traits::TraitEngineExt as _;
3434use rustc_middle:: ty:: fold:: TypeFoldable ;
3535use rustc_middle:: ty:: subst:: { InternalSubsts , SubstsRef } ;
3636use rustc_middle:: ty:: visit:: TypeVisitable ;
37- use rustc_middle:: ty:: { self , GenericParamDefKind , ToPredicate , Ty , TyCtxt , VtblEntry } ;
37+ use rustc_middle:: ty:: {
38+ self , DefIdTree , GenericParamDefKind , Subst , ToPredicate , Ty , TyCtxt , TypeSuperVisitable ,
39+ VtblEntry ,
40+ } ;
3841use rustc_span:: { sym, Span } ;
3942use smallvec:: SmallVec ;
4043
@@ -503,6 +506,77 @@ fn subst_and_check_impossible_predicates<'tcx>(
503506 result
504507}
505508
509+ /// Checks whether a trait's method is impossible to call on a given impl.
510+ ///
511+ /// This only considers predicates that reference the impl's generics, and not
512+ /// those that reference the method's generics.
513+ fn is_impossible_method < ' tcx > (
514+ tcx : TyCtxt < ' tcx > ,
515+ ( impl_def_id, trait_item_def_id) : ( DefId , DefId ) ,
516+ ) -> bool {
517+ struct ReferencesOnlyParentGenerics < ' tcx > {
518+ tcx : TyCtxt < ' tcx > ,
519+ generics : & ' tcx ty:: Generics ,
520+ trait_item_def_id : DefId ,
521+ }
522+ impl < ' tcx > ty:: TypeVisitor < ' tcx > for ReferencesOnlyParentGenerics < ' tcx > {
523+ type BreakTy = ( ) ;
524+ fn visit_ty ( & mut self , t : Ty < ' tcx > ) -> ControlFlow < Self :: BreakTy > {
525+ // If this is a parameter from the trait item's own generics, then bail
526+ if let ty:: Param ( param) = t. kind ( )
527+ && let param_def_id = self . generics . type_param ( param, self . tcx ) . def_id
528+ && self . tcx . parent ( param_def_id) == self . trait_item_def_id
529+ {
530+ return ControlFlow :: BREAK ;
531+ }
532+ t. super_visit_with ( self )
533+ }
534+ fn visit_region ( & mut self , r : ty:: Region < ' tcx > ) -> ControlFlow < Self :: BreakTy > {
535+ if let ty:: ReEarlyBound ( param) = r. kind ( )
536+ && let param_def_id = self . generics . region_param ( & param, self . tcx ) . def_id
537+ && self . tcx . parent ( param_def_id) == self . trait_item_def_id
538+ {
539+ return ControlFlow :: BREAK ;
540+ }
541+ r. super_visit_with ( self )
542+ }
543+ fn visit_const ( & mut self , ct : ty:: Const < ' tcx > ) -> ControlFlow < Self :: BreakTy > {
544+ if let ty:: ConstKind :: Param ( param) = ct. kind ( )
545+ && let param_def_id = self . generics . const_param ( & param, self . tcx ) . def_id
546+ && self . tcx . parent ( param_def_id) == self . trait_item_def_id
547+ {
548+ return ControlFlow :: BREAK ;
549+ }
550+ ct. super_visit_with ( self )
551+ }
552+ }
553+
554+ let generics = tcx. generics_of ( trait_item_def_id) ;
555+ let predicates = tcx. predicates_of ( trait_item_def_id) ;
556+ let impl_trait_ref =
557+ tcx. impl_trait_ref ( impl_def_id) . expect ( "expected impl to correspond to trait" ) ;
558+ let param_env = tcx. param_env ( impl_def_id) ;
559+
560+ let mut visitor = ReferencesOnlyParentGenerics { tcx, generics, trait_item_def_id } ;
561+ let predicates_for_trait = predicates. predicates . iter ( ) . filter_map ( |( pred, span) | {
562+ if pred. visit_with ( & mut visitor) . is_continue ( ) {
563+ Some ( Obligation :: new (
564+ ObligationCause :: dummy_with_span ( * span) ,
565+ param_env,
566+ ty:: EarlyBinder ( * pred) . subst ( tcx, impl_trait_ref. substs ) ,
567+ ) )
568+ } else {
569+ None
570+ }
571+ } ) ;
572+
573+ tcx. infer_ctxt ( ) . ignoring_regions ( ) . enter ( |ref infcx| {
574+ let mut fulfill_ctxt = <dyn TraitEngine < ' _ > >:: new ( tcx) ;
575+ fulfill_ctxt. register_predicate_obligations ( infcx, predicates_for_trait) ;
576+ !fulfill_ctxt. select_all_or_error ( infcx) . is_empty ( )
577+ } )
578+ }
579+
506580#[ derive( Clone , Debug ) ]
507581enum VtblSegment < ' tcx > {
508582 MetadataDSA ,
@@ -883,6 +957,7 @@ pub fn provide(providers: &mut ty::query::Providers) {
883957 vtable_entries,
884958 vtable_trait_upcasting_coercion_new_vptr_slot,
885959 subst_and_check_impossible_predicates,
960+ is_impossible_method,
886961 try_unify_abstract_consts : |tcx, param_env_and| {
887962 let ( param_env, ( a, b) ) = param_env_and. into_parts ( ) ;
888963 const_evaluatable:: try_unify_abstract_consts ( tcx, ( a, b) , param_env)
0 commit comments