Skip to content

Commit

Permalink
Make trivial dropck outlives a query
Browse files Browse the repository at this point in the history
This allows caching some recursive types and getting to an error much
more quickly.
  • Loading branch information
Mark-Simulacrum committed Oct 12, 2019
1 parent 026447b commit 62fba55
Show file tree
Hide file tree
Showing 5 changed files with 24 additions and 6 deletions.
6 changes: 6 additions & 0 deletions src/librustc/query/mod.rs
Expand Up @@ -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> {}
Expand Down
16 changes: 12 additions & 4 deletions src/librustc/traits/query/dropck_outlives.rs
Expand Up @@ -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
Expand Down Expand Up @@ -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![],
Expand Down Expand Up @@ -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() {
Expand Down Expand Up @@ -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
};
}
3 changes: 1 addition & 2 deletions 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};
Expand All @@ -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
Expand Down
1 change: 1 addition & 0 deletions src/librustc/ty/mod.rs
Expand Up @@ -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,
Expand Down
4 changes: 4 additions & 0 deletions src/librustc_traits/dropck_outlives.rs
Expand Up @@ -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
Expand Down

0 comments on commit 62fba55

Please sign in to comment.