Make trivial dropck outlives a query

This allows caching some recursive types and getting to an error much
more quickly.
This commit is contained in:
Mark Rousskov 2019-09-18 19:33:31 -04:00
parent 026447b9b0
commit 62fba55670
5 changed files with 24 additions and 6 deletions

View file

@ -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<DtorckConstraint<'tcx>, NoSolution> {}

View file

@ -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
};
}

View file

@ -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<Self::QueryResponse> {
if trivial_dropck_outlives(tcx, key.value.dropped_ty) {
if tcx.trivial_dropck_outlives(key.value.dropped_ty) {
Some(DropckOutlivesResult::default())
} else {
None

View file

@ -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,

View file

@ -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