@@ -40,7 +40,7 @@ pub use self::select::{EvaluationCache, SelectionContext, SelectionCache};
40
40
pub use self :: select:: { MethodMatchResult , MethodMatched , MethodAmbiguous , MethodDidNotMatch } ;
41
41
pub use self :: select:: { MethodMatchedData } ; // intentionally don't export variants
42
42
pub use self :: specialize:: { OverlapError , specialization_graph, specializes, translate_substs} ;
43
- pub use self :: specialize:: { SpecializesCache } ;
43
+ pub use self :: specialize:: { SpecializesCache , find_method } ;
44
44
pub use self :: util:: elaborate_predicates;
45
45
pub use self :: util:: supertraits;
46
46
pub use self :: util:: Supertraits ;
@@ -527,6 +527,88 @@ pub fn fully_normalize<'a, 'gcx, 'tcx, T>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
527
527
Ok ( resolved_value)
528
528
}
529
529
530
+ /// Normalizes the predicates and checks whether they hold. If this
531
+ /// returns false, then either normalize encountered an error or one
532
+ /// of the predicates did not hold. Used when creating vtables to
533
+ /// check for unsatisfiable methods.
534
+ pub fn normalize_and_test_predicates < ' a , ' tcx > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
535
+ predicates : Vec < ty:: Predicate < ' tcx > > )
536
+ -> bool
537
+ {
538
+ debug ! ( "normalize_and_test_predicates(predicates={:?})" ,
539
+ predicates) ;
540
+
541
+ tcx. infer_ctxt ( None , None , Reveal :: All ) . enter ( |infcx| {
542
+ let mut selcx = SelectionContext :: new ( & infcx) ;
543
+ let mut fulfill_cx = FulfillmentContext :: new ( ) ;
544
+ let cause = ObligationCause :: dummy ( ) ;
545
+ let Normalized { value : predicates, obligations } =
546
+ normalize ( & mut selcx, cause. clone ( ) , & predicates) ;
547
+ for obligation in obligations {
548
+ fulfill_cx. register_predicate_obligation ( & infcx, obligation) ;
549
+ }
550
+ for predicate in predicates {
551
+ let obligation = Obligation :: new ( cause. clone ( ) , predicate) ;
552
+ fulfill_cx. register_predicate_obligation ( & infcx, obligation) ;
553
+ }
554
+
555
+ fulfill_cx. select_all_or_error ( & infcx) . is_ok ( )
556
+ } )
557
+ }
558
+
559
+ /// Given a trait `trait_ref`, iterates the vtable entries
560
+ /// that come from `trait_ref`, including its supertraits.
561
+ #[ inline] // FIXME(#35870) Avoid closures being unexported due to impl Trait.
562
+ pub fn get_vtable_methods < ' a , ' tcx > (
563
+ tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
564
+ trait_ref : ty:: PolyTraitRef < ' tcx > )
565
+ -> impl Iterator < Item =Option < ( DefId , & ' tcx Substs < ' tcx > ) > > + ' a
566
+ {
567
+ debug ! ( "get_vtable_methods({:?})" , trait_ref) ;
568
+
569
+ supertraits ( tcx, trait_ref) . flat_map ( move |trait_ref| {
570
+ tcx. populate_implementations_for_trait_if_necessary ( trait_ref. def_id ( ) ) ;
571
+
572
+ let trait_item_def_ids = tcx. impl_or_trait_items ( trait_ref. def_id ( ) ) ;
573
+ let trait_methods = ( 0 ..trait_item_def_ids. len ( ) ) . filter_map ( move |i| {
574
+ match tcx. impl_or_trait_item ( trait_item_def_ids[ i] ) {
575
+ ty:: MethodTraitItem ( m) => Some ( m) ,
576
+ _ => None
577
+ }
578
+ } ) ;
579
+
580
+ // Now list each method's DefId and Substs (for within its trait).
581
+ // If the method can never be called from this object, produce None.
582
+ trait_methods. map ( move |trait_method| {
583
+ debug ! ( "get_vtable_methods: trait_method={:?}" , trait_method) ;
584
+
585
+ // Some methods cannot be called on an object; skip those.
586
+ if !tcx. is_vtable_safe_method ( trait_ref. def_id ( ) , & trait_method) {
587
+ debug ! ( "get_vtable_methods: not vtable safe" ) ;
588
+ return None ;
589
+ }
590
+
591
+ // the method may have some early-bound lifetimes, add
592
+ // regions for those
593
+ let substs = Substs :: for_item ( tcx, trait_method. def_id ,
594
+ |_, _| tcx. mk_region ( ty:: ReErased ) ,
595
+ |def, _| trait_ref. substs ( ) . type_for_def ( def) ) ;
596
+
597
+ // It's possible that the method relies on where clauses that
598
+ // do not hold for this particular set of type parameters.
599
+ // Note that this method could then never be called, so we
600
+ // do not want to try and trans it, in that case (see #23435).
601
+ let predicates = trait_method. predicates . instantiate_own ( tcx, substs) ;
602
+ if !normalize_and_test_predicates ( tcx, predicates. predicates ) {
603
+ debug ! ( "get_vtable_methods: predicates do not hold" ) ;
604
+ return None ;
605
+ }
606
+
607
+ Some ( ( trait_method. def_id , substs) )
608
+ } )
609
+ } )
610
+ }
611
+
530
612
impl < ' tcx , O > Obligation < ' tcx , O > {
531
613
pub fn new ( cause : ObligationCause < ' tcx > ,
532
614
trait_ref : O )
0 commit comments