@@ -2,20 +2,18 @@ use rustc_data_structures::fx::FxHashSet;
22use rustc_hir:: def_id:: DefId ;
33use rustc_infer:: infer:: canonical:: { Canonical , QueryResponse } ;
44use rustc_infer:: infer:: TyCtxtInferExt ;
5- use rustc_infer:: traits:: TraitEngineExt as _;
65use rustc_middle:: ty:: query:: Providers ;
76use rustc_middle:: ty:: InternalSubsts ;
87use rustc_middle:: ty:: { self , EarlyBinder , ParamEnvAnd , Ty , TyCtxt } ;
98use rustc_span:: source_map:: { Span , DUMMY_SP } ;
9+ use rustc_trait_selection:: infer:: InferCtxtBuilderExt ;
1010use rustc_trait_selection:: traits:: query:: dropck_outlives:: trivial_dropck_outlives;
1111use rustc_trait_selection:: traits:: query:: dropck_outlives:: {
1212 DropckConstraint , DropckOutlivesResult ,
1313} ;
1414use rustc_trait_selection:: traits:: query:: normalize:: AtExt ;
1515use 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 } ;
1917
2018pub ( crate ) fn provide ( p : & mut Providers ) {
2119 * p = Providers { dropck_outlives, adt_dtorck_constraint, ..* p } ;
@@ -27,120 +25,109 @@ fn dropck_outlives<'tcx>(
2725) -> Result < & ' tcx Canonical < ' tcx , QueryResponse < ' tcx , DropckOutlivesResult < ' tcx > > > , NoSolution > {
2826 debug ! ( "dropck_outlives(goal={:#?})" , canonical_goal) ;
2927
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+ }
10297
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+ }
123118
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 ) ) ;
128122 }
129123 }
130124 }
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- }
137125 }
138126 }
139- }
140-
141- debug ! ( "dropck_outlives: result = {:#?}" , result) ;
142127
143- infcx. make_canonicalized_query_response ( canonical_inference_vars, result, & mut * fulfill_cx)
128+ debug ! ( "dropck_outlives: result = {:#?}" , result) ;
129+ Ok ( result)
130+ } )
144131}
145132
146133/// Returns a set of constraints that needs to be satisfied in
0 commit comments