1
1
use crate :: FnCtxt ;
2
+ use rustc_infer:: traits:: solve:: Goal ;
3
+ use rustc_infer:: traits:: { self , ObligationCause } ;
2
4
use 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 } ;
5
7
6
8
impl < ' a , ' tcx > FnCtxt < ' a , ' tcx > {
7
9
#[ 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 ,
10
12
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
+ }
31
25
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
+ }
48
52
}
49
53
50
54
#[ instrument( level = "debug" , skip( self ) , ret) ]
@@ -53,12 +57,63 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
53
57
debug ! ( ?self_ty) ;
54
58
55
59
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) ,
61
61
_ => false ,
62
62
}
63
63
}
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