8
8
// option. This file may not be copied, modified, or distributed
9
9
// except according to those terms.
10
10
11
- use rustc:: mir:: Mir ;
11
+ use rustc:: mir:: { Location , Mir } ;
12
+ use rustc:: mir:: transform:: MirSource ;
12
13
use rustc:: infer:: InferCtxt ;
14
+ use rustc:: traits:: { self , ObligationCause } ;
15
+ use rustc:: ty:: { self , Ty } ;
16
+ use rustc:: ty:: fold:: TypeFoldable ;
17
+ use rustc:: util:: common:: ErrorReported ;
18
+ use rustc_data_structures:: fx:: FxHashSet ;
19
+ use syntax:: codemap:: DUMMY_SP ;
13
20
14
21
use super :: LivenessResults ;
15
22
use super :: ToRegionIndex ;
@@ -19,13 +26,15 @@ pub(super) fn generate_constraints<'a, 'gcx, 'tcx>(
19
26
infcx : & InferCtxt < ' a , ' gcx , ' tcx > ,
20
27
regioncx : & mut RegionInferenceContext ,
21
28
mir : & Mir < ' tcx > ,
29
+ mir_source : MirSource ,
22
30
liveness : & LivenessResults ,
23
31
) {
24
32
ConstraintGeneration {
25
33
infcx,
26
34
regioncx,
27
35
mir,
28
36
liveness,
37
+ mir_source,
29
38
} . add_constraints ( ) ;
30
39
}
31
40
@@ -34,6 +43,7 @@ struct ConstraintGeneration<'constrain, 'gcx: 'tcx, 'tcx: 'constrain> {
34
43
regioncx : & ' constrain mut RegionInferenceContext ,
35
44
mir : & ' constrain Mir < ' tcx > ,
36
45
liveness : & ' constrain LivenessResults ,
46
+ mir_source : MirSource ,
37
47
}
38
48
39
49
impl < ' constrain , ' gcx , ' tcx > ConstraintGeneration < ' constrain , ' gcx , ' tcx > {
@@ -47,29 +57,119 @@ impl<'constrain, 'gcx, 'tcx> ConstraintGeneration<'constrain, 'gcx, 'tcx> {
47
57
/// > If a variable V is live at point P, then all regions R in the type of V
48
58
/// > must include the point P.
49
59
fn add_liveness_constraints ( & mut self ) {
50
- let tcx = self . infcx . tcx ;
51
-
52
60
debug ! ( "add_liveness_constraints()" ) ;
53
61
for bb in self . mir . basic_blocks ( ) . indices ( ) {
54
62
debug ! ( "add_liveness_constraints: bb={:?}" , bb) ;
55
63
56
64
self . liveness
57
65
. regular
58
66
. simulate_block ( self . mir , bb, |location, live_locals| {
59
- debug ! (
60
- "add_liveness_constraints: location={:?} live_locals={:?}" ,
61
- location ,
62
- live_locals
63
- ) ;
67
+ for live_local in live_locals . iter ( ) {
68
+ let live_local_ty = self . mir . local_decls [ live_local ] . ty ;
69
+ self . add_regular_live_constraint ( live_local_ty , location ) ;
70
+ }
71
+ } ) ;
64
72
73
+ self . liveness
74
+ . drop
75
+ . simulate_block ( self . mir , bb, |location, live_locals| {
65
76
for live_local in live_locals. iter ( ) {
66
77
let live_local_ty = self . mir . local_decls [ live_local] . ty ;
67
- tcx. for_each_free_region ( & live_local_ty, |live_region| {
68
- let vid = live_region. to_region_index ( ) ;
69
- self . regioncx . add_live_point ( vid, location) ;
70
- } )
78
+ self . add_drop_live_constraint ( live_local_ty, location) ;
71
79
}
72
80
} ) ;
73
81
}
74
82
}
83
+
84
+ /// Some variable with type `live_ty` is "regular live" at
85
+ /// `location` -- i.e., it may be used later. This means that all
86
+ /// regions appearing in the type `live_ty` must be live at
87
+ /// `location`.
88
+ fn add_regular_live_constraint < T > ( & mut self , live_ty : T , location : Location )
89
+ where
90
+ T : TypeFoldable < ' tcx > ,
91
+ {
92
+ debug ! (
93
+ "add_regular_live_constraint(live_ty={:?}, location={:?})" ,
94
+ live_ty,
95
+ location
96
+ ) ;
97
+
98
+ self . infcx
99
+ . tcx
100
+ . for_each_free_region ( & live_ty, |live_region| {
101
+ let vid = live_region. to_region_index ( ) ;
102
+ self . regioncx . add_live_point ( vid, location) ;
103
+ } ) ;
104
+ }
105
+
106
+ /// Some variable with type `live_ty` is "drop live" at `location`
107
+ /// -- i.e., it may be dropped later. This means that *some* of
108
+ /// the regions in its type must be live at `location`. The
109
+ /// precise set will depend on the dropck constraints, and in
110
+ /// particular this takes `#[may_dangle]` into account.
111
+ fn add_drop_live_constraint ( & mut self , dropped_ty : Ty < ' tcx > , location : Location ) {
112
+ debug ! (
113
+ "add_drop_live_constraint(dropped_ty={:?}, location={:?})" ,
114
+ dropped_ty,
115
+ location
116
+ ) ;
117
+
118
+ let tcx = self . infcx . tcx ;
119
+ let mut types = vec ! [ ( dropped_ty, 0 ) ] ;
120
+ let mut known = FxHashSet ( ) ;
121
+ while let Some ( ( ty, depth) ) = types. pop ( ) {
122
+ let span = DUMMY_SP ; // FIXME
123
+ let result = match tcx. dtorck_constraint_for_ty ( span, dropped_ty, depth, ty) {
124
+ Ok ( result) => result,
125
+ Err ( ErrorReported ) => {
126
+ continue ;
127
+ }
128
+ } ;
129
+
130
+ let ty:: DtorckConstraint {
131
+ outlives,
132
+ dtorck_types,
133
+ } = result;
134
+
135
+ // All things in the `outlives` array may be touched by
136
+ // the destructor and must be live at this point.
137
+ for outlive in outlives {
138
+ if let Some ( ty) = outlive. as_type ( ) {
139
+ self . add_regular_live_constraint ( ty, location) ;
140
+ } else if let Some ( r) = outlive. as_region ( ) {
141
+ self . add_regular_live_constraint ( r, location) ;
142
+ } else {
143
+ bug ! ( )
144
+ }
145
+ }
146
+
147
+ // However, there may also be some types that
148
+ // `dtorck_constraint_for_ty` could not resolve (e.g.,
149
+ // associated types and parameters). We need to normalize
150
+ // associated types here and possibly recursively process.
151
+ let def_id = tcx. hir . local_def_id ( self . mir_source . item_id ( ) ) ;
152
+ let param_env = self . infcx . tcx . param_env ( def_id) ;
153
+ for ty in dtorck_types {
154
+ // FIXME -- I think that this may disregard some region obligations
155
+ // or something. Do we care? -nmatsakis
156
+ let cause = ObligationCause :: dummy ( ) ;
157
+ match traits:: fully_normalize ( self . infcx , cause, param_env, & ty) {
158
+ Ok ( ty) => match ty. sty {
159
+ ty:: TyParam ( ..) | ty:: TyProjection ( ..) | ty:: TyAnon ( ..) => {
160
+ self . add_regular_live_constraint ( ty, location) ;
161
+ }
162
+
163
+ _ => if known. insert ( ty) {
164
+ types. push ( ( ty, depth + 1 ) ) ;
165
+ } ,
166
+ } ,
167
+
168
+ Err ( errors) => {
169
+ self . infcx . report_fulfillment_errors ( & errors, None ) ;
170
+ }
171
+ }
172
+ }
173
+ }
174
+ }
75
175
}
0 commit comments