@@ -40,7 +40,7 @@ pub use self::select::{EvaluationCache, SelectionContext, SelectionCache};
4040pub use self :: select:: { MethodMatchResult , MethodMatched , MethodAmbiguous , MethodDidNotMatch } ;
4141pub use self :: select:: { MethodMatchedData } ; // intentionally don't export variants
4242pub use self :: specialize:: { OverlapError , specialization_graph, specializes, translate_substs} ;
43- pub use self :: specialize:: { SpecializesCache } ;
43+ pub use self :: specialize:: { SpecializesCache , find_method } ;
4444pub use self :: util:: elaborate_predicates;
4545pub use self :: util:: supertraits;
4646pub use self :: util:: Supertraits ;
@@ -527,6 +527,88 @@ pub fn fully_normalize<'a, 'gcx, 'tcx, T>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
527527 Ok ( resolved_value)
528528}
529529
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+
530612impl < ' tcx , O > Obligation < ' tcx , O > {
531613 pub fn new ( cause : ObligationCause < ' tcx > ,
532614 trait_ref : O )
0 commit comments