@@ -38,11 +38,16 @@ impl<'cx, 'gcx, 'tcx> At<'cx, 'gcx, 'tcx> {
3838 pub fn dropck_outlives ( & self , ty : Ty < ' tcx > ) -> InferOk < ' tcx , Vec < Kind < ' tcx > > > {
3939 debug ! (
4040 "dropck_outlives(ty={:?}, param_env={:?})" ,
41- ty,
42- self . param_env,
41+ ty, self . param_env,
4342 ) ;
4443
44+ // Quick check: there are a number of cases that we know do not require
45+ // any destructor.
4546 let tcx = self . infcx . tcx ;
47+ if trivial_dropck_outlives ( tcx, ty) {
48+ return InferOk { value : vec ! [ ] , obligations : vec ! [ ] } ;
49+ }
50+
4651 let gcx = tcx. global_tcx ( ) ;
4752 let ( c_ty, orig_values) = self . infcx . canonicalize_query ( & self . param_env . and ( ty) ) ;
4853 let span = self . cause . span ;
@@ -192,3 +197,68 @@ impl_stable_hash_for!(struct DtorckConstraint<'tcx> {
192197 dtorck_types,
193198 overflows
194199} ) ;
200+
201+ /// This returns true if the type `ty` is "trivial" for
202+ /// dropck-outlives -- that is, if it doesn't require any types to
203+ /// outlive. This is similar but not *quite* the same as the
204+ /// `needs_drop` test in the compiler already -- that is, for every
205+ /// type T for which this function return true, needs-drop would
206+ /// return false. But the reverse does not hold: in particular,
207+ /// `needs_drop` returns false for `PhantomData`, but it is not
208+ /// trivial for dropck-outlives.
209+ ///
210+ /// Note also that `needs_drop` requires a "global" type (i.e., one
211+ /// with erased regions), but this funtcion does not.
212+ fn trivial_dropck_outlives < ' cx , ' tcx > ( tcx : TyCtxt < ' cx , ' _ , ' tcx > , ty : Ty < ' tcx > ) -> bool {
213+ match ty. sty {
214+ // None of these types have a destructor and hence they do not
215+ // require anything in particular to outlive the dtor's
216+ // execution.
217+ ty:: TyInfer ( ty:: FreshIntTy ( _) )
218+ | ty:: TyInfer ( ty:: FreshFloatTy ( _) )
219+ | ty:: TyBool
220+ | ty:: TyInt ( _)
221+ | ty:: TyUint ( _)
222+ | ty:: TyFloat ( _)
223+ | ty:: TyNever
224+ | ty:: TyFnDef ( ..)
225+ | ty:: TyFnPtr ( _)
226+ | ty:: TyChar
227+ | ty:: TyGeneratorWitness ( ..)
228+ | ty:: TyRawPtr ( _)
229+ | ty:: TyRef ( ..)
230+ | ty:: TyStr
231+ | ty:: TyForeign ( ..)
232+ | ty:: TyError => true ,
233+
234+ // [T; N] and [T] have same properties as T.
235+ ty:: TyArray ( ty, _) | ty:: TySlice ( ty) => trivial_dropck_outlives ( tcx, ty) ,
236+
237+ // (T1..Tn) and closures have same properties as T1..Tn --
238+ // check if *any* of those are trivial.
239+ ty:: TyTuple ( ref tys, _) => tys. iter ( ) . cloned ( ) . all ( |t| trivial_dropck_outlives ( tcx, t) ) ,
240+ ty:: TyClosure ( def_id, ref substs) => substs
241+ . upvar_tys ( def_id, tcx)
242+ . all ( |t| trivial_dropck_outlives ( tcx, t) ) ,
243+
244+ ty:: TyAdt ( def, _) => {
245+ if def. is_union ( ) {
246+ // Unions never run have a dtor.
247+ true
248+ } else {
249+ // Other types might. Moreover, PhantomData doesn't
250+ // have a dtor, but it is considered to own its
251+ // content, so it is non-trivial.
252+ false
253+ }
254+ }
255+
256+ // The following *might* require a destructor: it would deeper inspection to tell.
257+ ty:: TyDynamic ( ..)
258+ | ty:: TyProjection ( ..)
259+ | ty:: TyParam ( _)
260+ | ty:: TyAnon ( ..)
261+ | ty:: TyInfer ( _)
262+ | ty:: TyGenerator ( ..) => false ,
263+ }
264+ }
0 commit comments