From 62fba55670f3f54356cd757ac6d221be42745fad Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Wed, 18 Sep 2019 19:33:31 -0400 Subject: [PATCH] Make trivial dropck outlives a query This allows caching some recursive types and getting to an error much more quickly. --- src/librustc/query/mod.rs | 6 ++++++ src/librustc/traits/query/dropck_outlives.rs | 16 ++++++++++++---- src/librustc/traits/query/type_op/outlives.rs | 3 +-- src/librustc/ty/mod.rs | 1 + src/librustc_traits/dropck_outlives.rs | 4 ++++ 5 files changed, 24 insertions(+), 6 deletions(-) diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index c95652f274e3..2a012c527419 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -231,6 +231,12 @@ rustc_queries! { cycle_delay_bug } + query trivial_dropck_outlives(ty: Ty<'tcx>) -> bool { + anon + no_force + desc { "checking if `{:?}` has trivial dropck", ty } + } + query adt_dtorck_constraint( _: DefId ) -> Result, NoSolution> {} diff --git a/src/librustc/traits/query/dropck_outlives.rs b/src/librustc/traits/query/dropck_outlives.rs index eaf5971e4592..e84c91daf293 100644 --- a/src/librustc/traits/query/dropck_outlives.rs +++ b/src/librustc/traits/query/dropck_outlives.rs @@ -5,6 +5,7 @@ use std::iter::FromIterator; use syntax::source_map::Span; use crate::ty::subst::GenericArg; use crate::ty::{self, Ty, TyCtxt}; +use crate::ty::query::Providers; impl<'cx, 'tcx> At<'cx, 'tcx> { /// Given a type `ty` of some value being dropped, computes a set @@ -33,7 +34,7 @@ impl<'cx, 'tcx> At<'cx, 'tcx> { // Quick check: there are a number of cases that we know do not require // any destructor. let tcx = self.infcx.tcx; - if trivial_dropck_outlives(tcx, ty) { + if tcx.trivial_dropck_outlives(ty) { return InferOk { value: vec![], obligations: vec![], @@ -207,15 +208,15 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool { | ty::Error => true, // [T; N] and [T] have same properties as T. - ty::Array(ty, _) | ty::Slice(ty) => trivial_dropck_outlives(tcx, ty), + ty::Array(ty, _) | ty::Slice(ty) => tcx.trivial_dropck_outlives(ty), // (T1..Tn) and closures have same properties as T1..Tn -- // check if *any* of those are trivial. - ty::Tuple(ref tys) => tys.iter().all(|t| trivial_dropck_outlives(tcx, t.expect_ty())), + ty::Tuple(ref tys) => tys.iter().all(|t| tcx.trivial_dropck_outlives(t.expect_ty())), ty::Closure(def_id, ref substs) => substs .as_closure() .upvar_tys(def_id, tcx) - .all(|t| trivial_dropck_outlives(tcx, t)), + .all(|t| tcx.trivial_dropck_outlives(t)), ty::Adt(def, _) => { if Some(def.did) == tcx.lang_items().manually_drop() { @@ -243,3 +244,10 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool { ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"), } } + +crate fn provide(p: &mut Providers<'_>) { + *p = Providers { + trivial_dropck_outlives, + ..*p + }; +} diff --git a/src/librustc/traits/query/type_op/outlives.rs b/src/librustc/traits/query/type_op/outlives.rs index 9b956f3e5540..86a32d68fc09 100644 --- a/src/librustc/traits/query/type_op/outlives.rs +++ b/src/librustc/traits/query/type_op/outlives.rs @@ -1,5 +1,4 @@ use crate::infer::canonical::{Canonicalized, CanonicalizedQueryResponse}; -use crate::traits::query::dropck_outlives::trivial_dropck_outlives; use crate::traits::query::dropck_outlives::DropckOutlivesResult; use crate::traits::query::Fallible; use crate::ty::{ParamEnvAnd, Ty, TyCtxt}; @@ -22,7 +21,7 @@ impl super::QueryTypeOp<'tcx> for DropckOutlives<'tcx> { tcx: TyCtxt<'tcx>, key: &ParamEnvAnd<'tcx, Self>, ) -> Option { - if trivial_dropck_outlives(tcx, key.value.dropped_ty) { + if tcx.trivial_dropck_outlives(key.value.dropped_ty) { Some(DropckOutlivesResult::default()) } else { None diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index cfd859c33c2e..01b7cda6fe91 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -3394,6 +3394,7 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) { layout::provide(providers); util::provide(providers); constness::provide(providers); + crate::traits::query::dropck_outlives::provide(providers); *providers = ty::query::Providers { asyncness, associated_item, diff --git a/src/librustc_traits/dropck_outlives.rs b/src/librustc_traits/dropck_outlives.rs index 88e62db9a10d..e751c94f23d1 100644 --- a/src/librustc_traits/dropck_outlives.rs +++ b/src/librustc_traits/dropck_outlives.rs @@ -166,6 +166,10 @@ fn dtorck_constraint_for_ty<'tcx>( }); } + if tcx.trivial_dropck_outlives(ty) { + return Ok(DtorckConstraint::empty()); + } + let result = match ty.kind { ty::Bool | ty::Char