@@ -34,117 +34,121 @@ fn dropck_outlives<'tcx>(
3434) -> Result < Lrc < Canonical < ' tcx , QueryResponse < ' tcx , DropckOutlivesResult < ' tcx > > > > , NoSolution > {
3535 debug ! ( "dropck_outlives(goal={:#?})" , canonical_goal) ;
3636
37- tcx. infer_ctxt ( ) . enter_with_canonical ( DUMMY_SP , & canonical_goal, |ref infcx, goal, canonical_inference_vars| {
38- let tcx = infcx. tcx ;
39- let ParamEnvAnd {
40- param_env,
41- value : for_ty,
42- } = goal;
43-
44- let mut result = DropckOutlivesResult {
45- kinds : vec ! [ ] ,
46- overflows : vec ! [ ] ,
47- } ;
37+ tcx. infer_ctxt ( ) . enter_with_canonical (
38+ DUMMY_SP ,
39+ & canonical_goal,
40+ |ref infcx, goal, canonical_inference_vars| {
41+ let tcx = infcx. tcx ;
42+ let ParamEnvAnd {
43+ param_env,
44+ value : for_ty,
45+ } = goal;
46+
47+ let mut result = DropckOutlivesResult {
48+ kinds : vec ! [ ] ,
49+ overflows : vec ! [ ] ,
50+ } ;
4851
49- // A stack of types left to process. Each round, we pop
50- // something from the stack and invoke
51- // `dtorck_constraint_for_ty`. This may produce new types that
52- // have to be pushed on the stack. This continues until we have explored
53- // all the reachable types from the type `for_ty`.
54- //
55- // Example: Imagine that we have the following code:
56- //
57- // ```rust
58- // struct A {
59- // value: B,
60- // children: Vec<A>,
61- // }
62- //
63- // struct B {
64- // value: u32
65- // }
66- //
67- // fn f() {
68- // let a: A = ...;
69- // ..
70- // } // here, `a` is dropped
71- // ```
72- //
73- // at the point where `a` is dropped, we need to figure out
74- // which types inside of `a` contain region data that may be
75- // accessed by any destructors in `a`. We begin by pushing `A`
76- // onto the stack, as that is the type of `a`. We will then
77- // invoke `dtorck_constraint_for_ty` which will expand `A`
78- // into the types of its fields `(B, Vec<A>)`. These will get
79- // pushed onto the stack. Eventually, expanding `Vec<A>` will
80- // lead to us trying to push `A` a second time -- to prevent
81- // infinite recursion, we notice that `A` was already pushed
82- // once and stop.
83- let mut ty_stack = vec ! [ ( for_ty, 0 ) ] ;
84-
85- // Set used to detect infinite recursion.
86- let mut ty_set = FxHashSet ( ) ;
87-
88- let fulfill_cx = & mut FulfillmentContext :: new ( ) ;
89-
90- let cause = ObligationCause :: dummy ( ) ;
91- while let Some ( ( ty, depth) ) = ty_stack. pop ( ) {
92- let DtorckConstraint {
93- dtorck_types,
94- outlives,
95- overflows,
96- } = dtorck_constraint_for_ty ( tcx, DUMMY_SP , for_ty, depth, ty) ?;
97-
98- // "outlives" represent types/regions that may be touched
99- // by a destructor.
100- result. kinds . extend ( outlives) ;
101- result. overflows . extend ( overflows) ;
102-
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 dtorck_types {
107- match infcx. at ( & cause, param_env) . normalize ( & ty) {
108- Ok ( Normalized {
109- value : ty,
110- obligations,
111- } ) => {
112- fulfill_cx. register_predicate_obligations ( infcx, obligations) ;
113-
114- debug ! ( "dropck_outlives: ty from dtorck_types = {:?}" , ty) ;
115-
116- match ty. sty {
117- // All parameters live for the duration of the
118- // function.
119- ty:: Param ( ..) => { }
120-
121- // A projection that we couldn't resolve - it
122- // might have a destructor.
123- ty:: Projection ( ..) | ty:: Opaque ( ..) => {
124- result. kinds . push ( ty. into ( ) ) ;
125- }
52+ // A stack of types left to process. Each round, we pop
53+ // something from the stack and invoke
54+ // `dtorck_constraint_for_ty`. This may produce new types that
55+ // have to be pushed on the stack. This continues until we have explored
56+ // all the reachable types from the type `for_ty`.
57+ //
58+ // Example: Imagine that we have the following code:
59+ //
60+ // ```rust
61+ // struct A {
62+ // value: B,
63+ // children: Vec<A>,
64+ // }
65+ //
66+ // struct B {
67+ // value: u32
68+ // }
69+ //
70+ // fn f() {
71+ // let a: A = ...;
72+ // ..
73+ // } // here, `a` is dropped
74+ // ```
75+ //
76+ // at the point where `a` is dropped, we need to figure out
77+ // which types inside of `a` contain region data that may be
78+ // accessed by any destructors in `a`. We begin by pushing `A`
79+ // onto the stack, as that is the type of `a`. We will then
80+ // invoke `dtorck_constraint_for_ty` which will expand `A`
81+ // into the types of its fields `(B, Vec<A>)`. These will get
82+ // pushed onto the stack. Eventually, expanding `Vec<A>` will
83+ // lead to us trying to push `A` a second time -- to prevent
84+ // infinite recursion, we notice that `A` was already pushed
85+ // once and stop.
86+ let mut ty_stack = vec ! [ ( for_ty, 0 ) ] ;
87+
88+ // Set used to detect infinite recursion.
89+ let mut ty_set = FxHashSet ( ) ;
90+
91+ let fulfill_cx = & mut FulfillmentContext :: new ( ) ;
92+
93+ let cause = ObligationCause :: dummy ( ) ;
94+ while let Some ( ( ty, depth) ) = ty_stack. pop ( ) {
95+ let DtorckConstraint {
96+ dtorck_types,
97+ outlives,
98+ overflows,
99+ } = dtorck_constraint_for_ty ( tcx, DUMMY_SP , for_ty, depth, ty) ?;
100+
101+ // "outlives" represent types/regions that may be touched
102+ // by a destructor.
103+ result. kinds . extend ( outlives) ;
104+ result. overflows . extend ( overflows) ;
105+
106+ // dtorck types are "types that will get dropped but which
107+ // do not themselves define a destructor", more or less. We have
108+ // to push them onto the stack to be expanded.
109+ for ty in dtorck_types {
110+ match infcx. at ( & cause, param_env) . normalize ( & ty) {
111+ Ok ( Normalized {
112+ value : ty,
113+ obligations,
114+ } ) => {
115+ fulfill_cx. register_predicate_obligations ( infcx, obligations) ;
116+
117+ debug ! ( "dropck_outlives: ty from dtorck_types = {:?}" , ty) ;
118+
119+ match ty. sty {
120+ // All parameters live for the duration of the
121+ // function.
122+ ty:: Param ( ..) => { }
123+
124+ // A projection that we couldn't resolve - it
125+ // might have a destructor.
126+ ty:: Projection ( ..) | ty:: Opaque ( ..) => {
127+ result. kinds . push ( ty. into ( ) ) ;
128+ }
126129
127- _ => {
128- if ty_set. insert ( ty) {
129- ty_stack. push ( ( ty, depth + 1 ) ) ;
130+ _ => {
131+ if ty_set. insert ( ty) {
132+ ty_stack. push ( ( ty, depth + 1 ) ) ;
133+ }
130134 }
131135 }
132136 }
133- }
134137
135- // We don't actually expect to fail to normalize.
136- // That implies a WF error somewhere else.
137- Err ( NoSolution ) => {
138- return Err ( NoSolution ) ;
138+ // We don't actually expect to fail to normalize.
139+ // That implies a WF error somewhere else.
140+ Err ( NoSolution ) => {
141+ return Err ( NoSolution ) ;
142+ }
139143 }
140144 }
141145 }
142- }
143146
144- debug ! ( "dropck_outlives: result = {:#?}" , result) ;
147+ debug ! ( "dropck_outlives: result = {:#?}" , result) ;
145148
146- infcx. make_canonicalized_query_response ( canonical_inference_vars, result, fulfill_cx)
147- } )
149+ infcx. make_canonicalized_query_response ( canonical_inference_vars, result, fulfill_cx)
150+ } ,
151+ )
148152}
149153
150154/// Return a set of constraints that needs to be satisfied in
@@ -192,8 +196,7 @@ fn dtorck_constraint_for_ty<'a, 'gcx, 'tcx>(
192196 dtorck_constraint_for_ty ( tcx, span, for_ty, depth + 1 , ety)
193197 }
194198
195- ty:: Tuple ( tys) => tys
196- . iter ( )
199+ ty:: Tuple ( tys) => tys. iter ( )
197200 . map ( |ty| dtorck_constraint_for_ty ( tcx, span, for_ty, depth + 1 , ty) )
198201 . collect ( ) ,
199202
@@ -305,8 +308,7 @@ crate fn adt_dtorck_constraint<'a, 'tcx>(
305308 return Ok ( result) ;
306309 }
307310
308- let mut result = def
309- . all_fields ( )
311+ let mut result = def. all_fields ( )
310312 . map ( |field| tcx. type_of ( field. did ) )
311313 . map ( |fty| dtorck_constraint_for_ty ( tcx, span, fty, 0 , fty) )
312314 . collect :: < Result < DtorckConstraint , NoSolution > > ( ) ?;
0 commit comments