@@ -2,20 +2,18 @@ use rustc_data_structures::fx::FxHashSet;
2
2
use rustc_hir:: def_id:: DefId ;
3
3
use rustc_infer:: infer:: canonical:: { Canonical , QueryResponse } ;
4
4
use rustc_infer:: infer:: TyCtxtInferExt ;
5
- use rustc_infer:: traits:: TraitEngineExt as _;
6
5
use rustc_middle:: ty:: query:: Providers ;
7
6
use rustc_middle:: ty:: InternalSubsts ;
8
7
use rustc_middle:: ty:: { self , EarlyBinder , ParamEnvAnd , Ty , TyCtxt } ;
9
8
use rustc_span:: source_map:: { Span , DUMMY_SP } ;
9
+ use rustc_trait_selection:: infer:: InferCtxtBuilderExt ;
10
10
use rustc_trait_selection:: traits:: query:: dropck_outlives:: trivial_dropck_outlives;
11
11
use rustc_trait_selection:: traits:: query:: dropck_outlives:: {
12
12
DropckConstraint , DropckOutlivesResult ,
13
13
} ;
14
14
use rustc_trait_selection:: traits:: query:: normalize:: AtExt ;
15
15
use rustc_trait_selection:: traits:: query:: { CanonicalTyGoal , NoSolution } ;
16
- use rustc_trait_selection:: traits:: {
17
- Normalized , ObligationCause , TraitEngine , TraitEngineExt as _,
18
- } ;
16
+ use rustc_trait_selection:: traits:: { Normalized , ObligationCause } ;
19
17
20
18
pub ( crate ) fn provide ( p : & mut Providers ) {
21
19
* p = Providers { dropck_outlives, adt_dtorck_constraint, ..* p } ;
@@ -27,120 +25,109 @@ fn dropck_outlives<'tcx>(
27
25
) -> Result < & ' tcx Canonical < ' tcx , QueryResponse < ' tcx , DropckOutlivesResult < ' tcx > > > , NoSolution > {
28
26
debug ! ( "dropck_outlives(goal={:#?})" , canonical_goal) ;
29
27
30
- let ( ref infcx, goal, canonical_inference_vars) =
31
- tcx. infer_ctxt ( ) . build_with_canonical ( DUMMY_SP , & canonical_goal) ;
32
- let tcx = infcx. tcx ;
33
- let ParamEnvAnd { param_env, value : for_ty } = goal;
34
-
35
- let mut result = DropckOutlivesResult { kinds : vec ! [ ] , overflows : vec ! [ ] } ;
36
-
37
- // A stack of types left to process. Each round, we pop
38
- // something from the stack and invoke
39
- // `dtorck_constraint_for_ty`. This may produce new types that
40
- // have to be pushed on the stack. This continues until we have explored
41
- // all the reachable types from the type `for_ty`.
42
- //
43
- // Example: Imagine that we have the following code:
44
- //
45
- // ```rust
46
- // struct A {
47
- // value: B,
48
- // children: Vec<A>,
49
- // }
50
- //
51
- // struct B {
52
- // value: u32
53
- // }
54
- //
55
- // fn f() {
56
- // let a: A = ...;
57
- // ..
58
- // } // here, `a` is dropped
59
- // ```
60
- //
61
- // at the point where `a` is dropped, we need to figure out
62
- // which types inside of `a` contain region data that may be
63
- // accessed by any destructors in `a`. We begin by pushing `A`
64
- // onto the stack, as that is the type of `a`. We will then
65
- // invoke `dtorck_constraint_for_ty` which will expand `A`
66
- // into the types of its fields `(B, Vec<A>)`. These will get
67
- // pushed onto the stack. Eventually, expanding `Vec<A>` will
68
- // lead to us trying to push `A` a second time -- to prevent
69
- // infinite recursion, we notice that `A` was already pushed
70
- // once and stop.
71
- let mut ty_stack = vec ! [ ( for_ty, 0 ) ] ;
72
-
73
- // Set used to detect infinite recursion.
74
- let mut ty_set = FxHashSet :: default ( ) ;
75
-
76
- let mut fulfill_cx = <dyn TraitEngine < ' _ > >:: new ( infcx. tcx ) ;
77
-
78
- let cause = ObligationCause :: dummy ( ) ;
79
- let mut constraints = DropckConstraint :: empty ( ) ;
80
- while let Some ( ( ty, depth) ) = ty_stack. pop ( ) {
81
- debug ! (
82
- "{} kinds, {} overflows, {} ty_stack" ,
83
- result. kinds. len( ) ,
84
- result. overflows. len( ) ,
85
- ty_stack. len( )
86
- ) ;
87
- dtorck_constraint_for_ty ( tcx, DUMMY_SP , for_ty, depth, ty, & mut constraints) ?;
88
-
89
- // "outlives" represent types/regions that may be touched
90
- // by a destructor.
91
- result. kinds . append ( & mut constraints. outlives ) ;
92
- result. overflows . append ( & mut constraints. overflows ) ;
93
-
94
- // If we have even one overflow, we should stop trying to evaluate further --
95
- // chances are, the subsequent overflows for this evaluation won't provide useful
96
- // information and will just decrease the speed at which we can emit these errors
97
- // (since we'll be printing for just that much longer for the often enormous types
98
- // that result here).
99
- if !result. overflows . is_empty ( ) {
100
- break ;
101
- }
28
+ tcx. infer_ctxt ( ) . enter_canonical_trait_query ( & canonical_goal, |ocx, goal| {
29
+ let tcx = ocx. infcx . tcx ;
30
+ let ParamEnvAnd { param_env, value : for_ty } = goal;
31
+
32
+ let mut result = DropckOutlivesResult { kinds : vec ! [ ] , overflows : vec ! [ ] } ;
33
+
34
+ // A stack of types left to process. Each round, we pop
35
+ // something from the stack and invoke
36
+ // `dtorck_constraint_for_ty`. This may produce new types that
37
+ // have to be pushed on the stack. This continues until we have explored
38
+ // all the reachable types from the type `for_ty`.
39
+ //
40
+ // Example: Imagine that we have the following code:
41
+ //
42
+ // ```rust
43
+ // struct A {
44
+ // value: B,
45
+ // children: Vec<A>,
46
+ // }
47
+ //
48
+ // struct B {
49
+ // value: u32
50
+ // }
51
+ //
52
+ // fn f() {
53
+ // let a: A = ...;
54
+ // ..
55
+ // } // here, `a` is dropped
56
+ // ```
57
+ //
58
+ // at the point where `a` is dropped, we need to figure out
59
+ // which types inside of `a` contain region data that may be
60
+ // accessed by any destructors in `a`. We begin by pushing `A`
61
+ // onto the stack, as that is the type of `a`. We will then
62
+ // invoke `dtorck_constraint_for_ty` which will expand `A`
63
+ // into the types of its fields `(B, Vec<A>)`. These will get
64
+ // pushed onto the stack. Eventually, expanding `Vec<A>` will
65
+ // lead to us trying to push `A` a second time -- to prevent
66
+ // infinite recursion, we notice that `A` was already pushed
67
+ // once and stop.
68
+ let mut ty_stack = vec ! [ ( for_ty, 0 ) ] ;
69
+
70
+ // Set used to detect infinite recursion.
71
+ let mut ty_set = FxHashSet :: default ( ) ;
72
+
73
+ let cause = ObligationCause :: dummy ( ) ;
74
+ let mut constraints = DropckConstraint :: empty ( ) ;
75
+ while let Some ( ( ty, depth) ) = ty_stack. pop ( ) {
76
+ debug ! (
77
+ "{} kinds, {} overflows, {} ty_stack" ,
78
+ result. kinds. len( ) ,
79
+ result. overflows. len( ) ,
80
+ ty_stack. len( )
81
+ ) ;
82
+ dtorck_constraint_for_ty ( tcx, DUMMY_SP , for_ty, depth, ty, & mut constraints) ?;
83
+
84
+ // "outlives" represent types/regions that may be touched
85
+ // by a destructor.
86
+ result. kinds . append ( & mut constraints. outlives ) ;
87
+ result. overflows . append ( & mut constraints. overflows ) ;
88
+
89
+ // If we have even one overflow, we should stop trying to evaluate further --
90
+ // chances are, the subsequent overflows for this evaluation won't provide useful
91
+ // information and will just decrease the speed at which we can emit these errors
92
+ // (since we'll be printing for just that much longer for the often enormous types
93
+ // that result here).
94
+ if !result. overflows . is_empty ( ) {
95
+ break ;
96
+ }
102
97
103
- // dtorck types are "types that will get dropped but which
104
- // do not themselves define a destructor", more or less. We have
105
- // to push them onto the stack to be expanded.
106
- for ty in constraints. dtorck_types . drain ( ..) {
107
- match infcx . at ( & cause , param_env ) . normalize ( ty ) {
108
- Ok ( Normalized { value : ty , obligations } ) => {
109
- fulfill_cx . register_predicate_obligations ( infcx , obligations) ;
110
-
111
- debug ! ( "dropck_outlives: ty from dtorck_types = {:?}" , ty) ;
112
-
113
- match ty. kind ( ) {
114
- // All parameters live for the duration of the
115
- // function.
116
- ty:: Param ( ..) => { }
117
-
118
- // A projection that we couldn't resolve - it
119
- // might have a destructor.
120
- ty:: Projection ( ..) | ty:: Opaque ( ..) => {
121
- result. kinds . push ( ty. into ( ) ) ;
122
- }
98
+ // dtorck types are "types that will get dropped but which
99
+ // do not themselves define a destructor", more or less. We have
100
+ // to push them onto the stack to be expanded.
101
+ for ty in constraints. dtorck_types . drain ( ..) {
102
+ let Normalized { value : ty , obligations } =
103
+ ocx . infcx . at ( & cause , param_env ) . normalize ( ty ) ? ;
104
+ ocx . register_obligations ( obligations) ;
105
+
106
+ debug ! ( "dropck_outlives: ty from dtorck_types = {:?}" , ty) ;
107
+
108
+ match ty. kind ( ) {
109
+ // All parameters live for the duration of the
110
+ // function.
111
+ ty:: Param ( ..) => { }
112
+
113
+ // A projection that we couldn't resolve - it
114
+ // might have a destructor.
115
+ ty:: Projection ( ..) | ty:: Opaque ( ..) => {
116
+ result. kinds . push ( ty. into ( ) ) ;
117
+ }
123
118
124
- _ => {
125
- if ty_set. insert ( ty) {
126
- ty_stack. push ( ( ty, depth + 1 ) ) ;
127
- }
119
+ _ => {
120
+ if ty_set. insert ( ty) {
121
+ ty_stack. push ( ( ty, depth + 1 ) ) ;
128
122
}
129
123
}
130
124
}
131
-
132
- // We don't actually expect to fail to normalize.
133
- // That implies a WF error somewhere else.
134
- Err ( NoSolution ) => {
135
- return Err ( NoSolution ) ;
136
- }
137
125
}
138
126
}
139
- }
140
-
141
- debug ! ( "dropck_outlives: result = {:#?}" , result) ;
142
127
143
- infcx. make_canonicalized_query_response ( canonical_inference_vars, result, & mut * fulfill_cx)
128
+ debug ! ( "dropck_outlives: result = {:#?}" , result) ;
129
+ Ok ( result)
130
+ } )
144
131
}
145
132
146
133
/// Returns a set of constraints that needs to be satisfied in
0 commit comments