@@ -30,10 +30,14 @@ use rustc_errors::ErrorGuaranteed;
30
30
use rustc_hir as hir;
31
31
use rustc_hir:: def_id:: DefId ;
32
32
use rustc_hir:: lang_items:: LangItem ;
33
+ use rustc_infer:: traits:: TraitEngineExt as _;
33
34
use rustc_middle:: ty:: fold:: TypeFoldable ;
34
35
use rustc_middle:: ty:: subst:: { InternalSubsts , SubstsRef } ;
35
36
use rustc_middle:: ty:: visit:: TypeVisitable ;
36
- 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
+ } ;
37
41
use rustc_span:: { sym, Span } ;
38
42
use smallvec:: SmallVec ;
39
43
@@ -474,6 +478,77 @@ fn subst_and_check_impossible_predicates<'tcx>(
474
478
result
475
479
}
476
480
481
+ /// Checks whether a trait's method is impossible to call on a given impl.
482
+ ///
483
+ /// This only considers predicates that reference the impl's generics, and not
484
+ /// those that reference the method's generics.
485
+ fn is_impossible_method < ' tcx > (
486
+ tcx : TyCtxt < ' tcx > ,
487
+ ( impl_def_id, trait_item_def_id) : ( DefId , DefId ) ,
488
+ ) -> bool {
489
+ struct ReferencesOnlyParentGenerics < ' tcx > {
490
+ tcx : TyCtxt < ' tcx > ,
491
+ generics : & ' tcx ty:: Generics ,
492
+ trait_item_def_id : DefId ,
493
+ }
494
+ impl < ' tcx > ty:: TypeVisitor < ' tcx > for ReferencesOnlyParentGenerics < ' tcx > {
495
+ type BreakTy = ( ) ;
496
+ fn visit_ty ( & mut self , t : Ty < ' tcx > ) -> ControlFlow < Self :: BreakTy > {
497
+ // If this is a parameter from the trait item's own generics, then bail
498
+ if let ty:: Param ( param) = t. kind ( )
499
+ && let param_def_id = self . generics . type_param ( param, self . tcx ) . def_id
500
+ && self . tcx . parent ( param_def_id) == self . trait_item_def_id
501
+ {
502
+ return ControlFlow :: BREAK ;
503
+ }
504
+ t. super_visit_with ( self )
505
+ }
506
+ fn visit_region ( & mut self , r : ty:: Region < ' tcx > ) -> ControlFlow < Self :: BreakTy > {
507
+ if let ty:: ReEarlyBound ( param) = r. kind ( )
508
+ && let param_def_id = self . generics . region_param ( & param, self . tcx ) . def_id
509
+ && self . tcx . parent ( param_def_id) == self . trait_item_def_id
510
+ {
511
+ return ControlFlow :: BREAK ;
512
+ }
513
+ r. super_visit_with ( self )
514
+ }
515
+ fn visit_const ( & mut self , ct : ty:: Const < ' tcx > ) -> ControlFlow < Self :: BreakTy > {
516
+ if let ty:: ConstKind :: Param ( param) = ct. kind ( )
517
+ && let param_def_id = self . generics . const_param ( & param, self . tcx ) . def_id
518
+ && self . tcx . parent ( param_def_id) == self . trait_item_def_id
519
+ {
520
+ return ControlFlow :: BREAK ;
521
+ }
522
+ ct. super_visit_with ( self )
523
+ }
524
+ }
525
+
526
+ let generics = tcx. generics_of ( trait_item_def_id) ;
527
+ let predicates = tcx. predicates_of ( trait_item_def_id) ;
528
+ let impl_trait_ref =
529
+ tcx. impl_trait_ref ( impl_def_id) . expect ( "expected impl to correspond to trait" ) ;
530
+ let param_env = tcx. param_env ( impl_def_id) ;
531
+
532
+ let mut visitor = ReferencesOnlyParentGenerics { tcx, generics, trait_item_def_id } ;
533
+ let predicates_for_trait = predicates. predicates . iter ( ) . filter_map ( |( pred, span) | {
534
+ if pred. visit_with ( & mut visitor) . is_continue ( ) {
535
+ Some ( Obligation :: new (
536
+ ObligationCause :: dummy_with_span ( * span) ,
537
+ param_env,
538
+ ty:: EarlyBinder ( * pred) . subst ( tcx, impl_trait_ref. substs ) ,
539
+ ) )
540
+ } else {
541
+ None
542
+ }
543
+ } ) ;
544
+
545
+ tcx. infer_ctxt ( ) . ignoring_regions ( ) . enter ( |ref infcx| {
546
+ let mut fulfill_ctxt = <dyn TraitEngine < ' _ > >:: new ( tcx) ;
547
+ fulfill_ctxt. register_predicate_obligations ( infcx, predicates_for_trait) ;
548
+ !fulfill_ctxt. select_all_or_error ( infcx) . is_empty ( )
549
+ } )
550
+ }
551
+
477
552
#[ derive( Clone , Debug ) ]
478
553
enum VtblSegment < ' tcx > {
479
554
MetadataDSA ,
@@ -854,6 +929,7 @@ pub fn provide(providers: &mut ty::query::Providers) {
854
929
vtable_entries,
855
930
vtable_trait_upcasting_coercion_new_vptr_slot,
856
931
subst_and_check_impossible_predicates,
932
+ is_impossible_method,
857
933
try_unify_abstract_consts : |tcx, param_env_and| {
858
934
let ( param_env, ( a, b) ) = param_env_and. into_parts ( ) ;
859
935
const_evaluatable:: try_unify_abstract_consts ( tcx, ( a, b) , param_env)
0 commit comments