11use crate :: FnCtxt ;
2+ use rustc_infer:: traits:: solve:: Goal ;
3+ use rustc_infer:: traits:: { self , ObligationCause } ;
24use rustc_middle:: ty:: { self , Ty } ;
3- use rustc_infer :: traits ;
4- use rustc_data_structures :: captures :: Captures ;
5+ use rustc_trait_selection :: solve :: inspect :: ProofTreeInferCtxtExt ;
6+ use rustc_trait_selection :: solve :: inspect :: { InspectConfig , InspectGoal , ProofTreeVisitor } ;
57
68impl < ' a , ' tcx > FnCtxt < ' a , ' tcx > {
79 #[ instrument( skip( self ) , level = "debug" ) ]
8- pub ( crate ) fn obligations_for_self_ty < ' b > (
9- & ' b self ,
10+ pub ( crate ) fn obligations_for_self_ty (
11+ & self ,
1012 self_ty : ty:: TyVid ,
11- ) -> impl DoubleEndedIterator < Item = traits:: PredicateObligation < ' tcx > > + Captures < ' tcx > + ' b
12- {
13- let ty_var_root = self . root_var ( self_ty) ;
14- trace ! ( "pending_obligations = {:#?}" , self . fulfillment_cx. borrow( ) . pending_obligations( ) ) ;
15-
16- self . fulfillment_cx . borrow ( ) . pending_obligations ( ) . into_iter ( ) . filter_map (
17- move |obligation| match & obligation. predicate . kind ( ) . skip_binder ( ) {
18- ty:: PredicateKind :: Clause ( ty:: ClauseKind :: Projection ( data) )
19- if self . self_type_matches_expected_vid (
20- data. projection_ty . self_ty ( ) ,
21- ty_var_root,
22- ) =>
23- {
24- Some ( obligation)
25- }
26- ty:: PredicateKind :: Clause ( ty:: ClauseKind :: Trait ( data) )
27- if self . self_type_matches_expected_vid ( data. self_ty ( ) , ty_var_root) =>
28- {
29- Some ( obligation)
30- }
13+ ) -> Vec < traits:: PredicateObligation < ' tcx > > {
14+ if self . next_trait_solver ( ) {
15+ self . obligations_for_self_ty_next ( self_ty)
16+ } else {
17+ let ty_var_root = self . root_var ( self_ty) ;
18+ let mut obligations = self . fulfillment_cx . borrow ( ) . pending_obligations ( ) ;
19+ trace ! ( "pending_obligations = {:#?}" , obligations) ;
20+ obligations
21+ . retain ( |obligation| self . predicate_has_self_ty ( obligation. predicate , ty_var_root) ) ;
22+ obligations
23+ }
24+ }
3125
32- ty:: PredicateKind :: Clause ( ty:: ClauseKind :: Trait ( ..) )
33- | ty:: PredicateKind :: Clause ( ty:: ClauseKind :: Projection ( ..) )
34- | ty:: PredicateKind :: Clause ( ty:: ClauseKind :: ConstArgHasType ( ..) )
35- | ty:: PredicateKind :: Subtype ( ..)
36- | ty:: PredicateKind :: Coerce ( ..)
37- | ty:: PredicateKind :: Clause ( ty:: ClauseKind :: RegionOutlives ( ..) )
38- | ty:: PredicateKind :: Clause ( ty:: ClauseKind :: TypeOutlives ( ..) )
39- | ty:: PredicateKind :: Clause ( ty:: ClauseKind :: WellFormed ( ..) )
40- | ty:: PredicateKind :: ObjectSafe ( ..)
41- | ty:: PredicateKind :: NormalizesTo ( ..)
42- | ty:: PredicateKind :: AliasRelate ( ..)
43- | ty:: PredicateKind :: Clause ( ty:: ClauseKind :: ConstEvaluatable ( ..) )
44- | ty:: PredicateKind :: ConstEquate ( ..)
45- | ty:: PredicateKind :: Ambiguous => None ,
46- } ,
47- )
26+ #[ instrument( level = "debug" , skip( self ) , ret) ]
27+ fn predicate_has_self_ty (
28+ & self ,
29+ predicate : ty:: Predicate < ' tcx > ,
30+ expected_vid : ty:: TyVid ,
31+ ) -> bool {
32+ match predicate. kind ( ) . skip_binder ( ) {
33+ ty:: PredicateKind :: Clause ( ty:: ClauseKind :: Trait ( data) ) => {
34+ self . self_type_matches_expected_vid ( data. self_ty ( ) , expected_vid)
35+ }
36+ ty:: PredicateKind :: Clause ( ty:: ClauseKind :: Projection ( data) ) => {
37+ self . self_type_matches_expected_vid ( data. projection_ty . self_ty ( ) , expected_vid)
38+ }
39+ ty:: PredicateKind :: Clause ( ty:: ClauseKind :: ConstArgHasType ( ..) )
40+ | ty:: PredicateKind :: Subtype ( ..)
41+ | ty:: PredicateKind :: Coerce ( ..)
42+ | ty:: PredicateKind :: Clause ( ty:: ClauseKind :: RegionOutlives ( ..) )
43+ | ty:: PredicateKind :: Clause ( ty:: ClauseKind :: TypeOutlives ( ..) )
44+ | ty:: PredicateKind :: Clause ( ty:: ClauseKind :: WellFormed ( ..) )
45+ | ty:: PredicateKind :: ObjectSafe ( ..)
46+ | ty:: PredicateKind :: NormalizesTo ( ..)
47+ | ty:: PredicateKind :: AliasRelate ( ..)
48+ | ty:: PredicateKind :: Clause ( ty:: ClauseKind :: ConstEvaluatable ( ..) )
49+ | ty:: PredicateKind :: ConstEquate ( ..)
50+ | ty:: PredicateKind :: Ambiguous => false ,
51+ }
4852 }
4953
5054 #[ instrument( level = "debug" , skip( self ) , ret) ]
@@ -53,12 +57,63 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
5357 debug ! ( ?self_ty) ;
5458
5559 match * self_ty. kind ( ) {
56- ty:: Infer ( ty:: TyVar ( found_vid) ) => {
57- let found_vid = self . root_var ( found_vid) ;
58- debug ! ( "self_type_matches_expected_vid - found_vid={:?}" , found_vid) ;
59- expected_vid == found_vid
60- }
60+ ty:: Infer ( ty:: TyVar ( found_vid) ) => expected_vid == self . root_var ( found_vid) ,
6161 _ => false ,
6262 }
6363 }
64- }
64+
65+ pub ( crate ) fn obligations_for_self_ty_next (
66+ & self ,
67+ self_ty : ty:: TyVid ,
68+ ) -> Vec < traits:: PredicateObligation < ' tcx > > {
69+ let obligations = self . fulfillment_cx . borrow ( ) . pending_obligations ( ) ;
70+ let mut obligations_for_self_ty = vec ! [ ] ;
71+ for obligation in obligations {
72+ let mut visitor = NestedObligationsForSelfTy {
73+ fcx : self ,
74+ ty_var_root : self . root_var ( self_ty) ,
75+ obligations_for_self_ty : & mut obligations_for_self_ty,
76+ root_cause : & obligation. cause ,
77+ } ;
78+
79+ let goal = Goal :: new ( self . tcx , obligation. param_env , obligation. predicate ) ;
80+ self . visit_proof_tree ( goal, & mut visitor) ;
81+ }
82+ obligations_for_self_ty
83+ }
84+ }
85+
86+ struct NestedObligationsForSelfTy < ' a , ' tcx > {
87+ fcx : & ' a FnCtxt < ' a , ' tcx > ,
88+ ty_var_root : ty:: TyVid ,
89+ root_cause : & ' a ObligationCause < ' tcx > ,
90+ obligations_for_self_ty : & ' a mut Vec < traits:: PredicateObligation < ' tcx > > ,
91+ }
92+
93+ impl < ' a , ' tcx > ProofTreeVisitor < ' tcx > for NestedObligationsForSelfTy < ' a , ' tcx > {
94+ type Result = ( ) ;
95+
96+ fn config ( & self ) -> InspectConfig {
97+ // Using an intentionally low depth to minimize the chance of future
98+ // breaking changes in case we adapt the approach later on. This also
99+ // avoids any hangs for exponentially growing proof trees.
100+ InspectConfig { max_depth : 3 }
101+ }
102+
103+ fn visit_goal ( & mut self , inspect_goal : & InspectGoal < ' _ , ' tcx > ) {
104+ let tcx = self . fcx . tcx ;
105+ let goal = inspect_goal. goal ( ) ;
106+ if self . fcx . predicate_has_self_ty ( goal. predicate , self . ty_var_root ) {
107+ self . obligations_for_self_ty . push ( traits:: Obligation :: new (
108+ tcx,
109+ self . root_cause . clone ( ) ,
110+ goal. param_env ,
111+ goal. predicate ,
112+ ) ) ;
113+ }
114+
115+ if let Some ( candidate) = inspect_goal. unique_applicable_candidate ( ) {
116+ candidate. visit_nested_no_probe ( self )
117+ }
118+ }
119+ }
0 commit comments