introduce tcx.normalize_erasing_regions(..) operaton [VIC]
This commit is contained in:
parent
ca87d24467
commit
211d9ad7db
8 changed files with 143 additions and 3 deletions
|
|
@ -179,6 +179,8 @@ pub struct PerfStats {
|
|||
/// result had already been canonicalized.
|
||||
pub canonicalized_values_allocated: Cell<usize>,
|
||||
/// Number of times this query is invoked.
|
||||
pub normalize_ty_after_erasing_regions: Cell<usize>,
|
||||
/// Number of times this query is invoked.
|
||||
pub normalize_projection_ty: Cell<usize>,
|
||||
}
|
||||
|
||||
|
|
@ -869,6 +871,8 @@ impl Session {
|
|||
self.perf_stats.queries_canonicalized.get());
|
||||
println!("Total canonical values interned: {}",
|
||||
self.perf_stats.canonicalized_values_allocated.get());
|
||||
println!("normalize_ty_after_erasing_regions: {}",
|
||||
self.perf_stats.normalize_ty_after_erasing_regions.get());
|
||||
println!("normalize_projection_ty: {}",
|
||||
self.perf_stats.normalize_projection_ty.get());
|
||||
}
|
||||
|
|
@ -1159,6 +1163,7 @@ pub fn build_session_(
|
|||
decode_def_path_tables_time: Cell::new(Duration::from_secs(0)),
|
||||
queries_canonicalized: Cell::new(0),
|
||||
canonicalized_values_allocated: Cell::new(0),
|
||||
normalize_ty_after_erasing_regions: Cell::new(0),
|
||||
normalize_projection_ty: Cell::new(0),
|
||||
},
|
||||
code_stats: RefCell::new(CodeStats::new()),
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ use ty::{self, Ty};
|
|||
|
||||
pub mod dropck_outlives;
|
||||
pub mod normalize;
|
||||
pub mod normalize_erasing_regions;
|
||||
|
||||
pub type CanonicalProjectionGoal<'tcx> =
|
||||
Canonical<'tcx, ty::ParamEnvAnd<'tcx, ty::ProjectionTy<'tcx>>>;
|
||||
|
|
|
|||
81
src/librustc/traits/query/normalize_erasing_regions.rs
Normal file
81
src/librustc/traits/query/normalize_erasing_regions.rs
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! Methods for normalizing when you don't care about regions (and
|
||||
//! aren't doing type inference). If either of those things don't
|
||||
//! apply to you, use `infcx.normalize(...)`.
|
||||
//!
|
||||
//! The methods in this file use a `TypeFolder` to recursively process
|
||||
//! contents, invoking the underlying
|
||||
//! `normalize_ty_after_erasing_regions` query for each type found
|
||||
//! within. (This underlying query is what is cached.)
|
||||
|
||||
use ty::{self, Ty, TyCtxt};
|
||||
use ty::fold::{TypeFoldable, TypeFolder};
|
||||
|
||||
impl<'cx, 'tcx> TyCtxt<'cx, 'tcx, 'tcx> {
|
||||
/// Erase the regions in `value` and then fully normalize all the
|
||||
/// types found within. The result will also have regions erased.
|
||||
///
|
||||
/// This is appropriate to use only after type-check: it assumes
|
||||
/// that normalization will succeed, for example.
|
||||
pub fn normalize_erasing_regions<T>(self, param_env: ty::ParamEnv<'tcx>, value: T) -> T
|
||||
where
|
||||
T: TypeFoldable<'tcx>,
|
||||
{
|
||||
// Erase first before we do the real query -- this keeps the
|
||||
// cache from being too polluted.
|
||||
let value = self.erase_regions(&value);
|
||||
if !value.has_projections() {
|
||||
value
|
||||
} else {
|
||||
value.fold_with(&mut NormalizeAfterErasingRegionsFolder {
|
||||
tcx: self,
|
||||
param_env: param_env,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// If you have a `Binder<T>`, you can do this to strip out the
|
||||
/// late-bound regions and then normalize the result, yielding up
|
||||
/// a `T` (with regions erased). This is appropriate when the
|
||||
/// binder is being instantiated at the call site.
|
||||
///
|
||||
/// NB. Currently, higher-ranked type bounds inhibit
|
||||
/// normalization. Therefore, each time we erase them in
|
||||
/// translation, we need to normalize the contents.
|
||||
pub fn normalize_erasing_late_bound_regions<T>(
|
||||
self,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
value: &ty::Binder<T>,
|
||||
) -> T
|
||||
where
|
||||
T: TypeFoldable<'tcx>,
|
||||
{
|
||||
assert!(!value.needs_subst());
|
||||
let value = self.erase_late_bound_regions(value);
|
||||
self.normalize_erasing_regions(param_env, value)
|
||||
}
|
||||
}
|
||||
|
||||
struct NormalizeAfterErasingRegionsFolder<'cx, 'tcx: 'cx> {
|
||||
tcx: TyCtxt<'cx, 'tcx, 'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
}
|
||||
|
||||
impl<'cx, 'tcx> TypeFolder<'tcx, 'tcx> for NormalizeAfterErasingRegionsFolder<'cx, 'tcx> {
|
||||
fn tcx<'a>(&'a self) -> TyCtxt<'a, 'tcx, 'tcx> {
|
||||
self.tcx
|
||||
}
|
||||
|
||||
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
|
||||
self.tcx.normalize_ty_after_erasing_regions(self.param_env.and(ty))
|
||||
}
|
||||
}
|
||||
|
|
@ -12,7 +12,7 @@ use dep_graph::SerializedDepNodeIndex;
|
|||
use hir::def_id::{CrateNum, DefId, DefIndex};
|
||||
use mir::interpret::{GlobalId};
|
||||
use traits::query::{CanonicalProjectionGoal, CanonicalTyGoal};
|
||||
use ty::{self, Ty, TyCtxt};
|
||||
use ty::{self, ParamEnvAnd, Ty, TyCtxt};
|
||||
use ty::subst::Substs;
|
||||
use ty::maps::queries;
|
||||
|
||||
|
|
@ -67,6 +67,12 @@ impl<'tcx> QueryDescription<'tcx> for queries::dropck_outlives<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::normalize_ty_after_erasing_regions<'tcx> {
|
||||
fn describe(_tcx: TyCtxt, goal: ParamEnvAnd<'tcx, Ty<'tcx>>) -> String {
|
||||
format!("normalizing `{:?}`", goal)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::is_copy_raw<'tcx> {
|
||||
fn describe(_tcx: TyCtxt, env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> String {
|
||||
format!("computing whether `{}` is `Copy`", env.value)
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ use traits::query::{CanonicalProjectionGoal, CanonicalTyGoal, NoSolution};
|
|||
use traits::query::dropck_outlives::{DtorckConstraint, DropckOutlivesResult};
|
||||
use traits::query::normalize::NormalizationResult;
|
||||
use traits::specialization_graph;
|
||||
use ty::{self, CrateInherentImpls, Ty, TyCtxt};
|
||||
use ty::{self, CrateInherentImpls, ParamEnvAnd, Ty, TyCtxt};
|
||||
use ty::steal::Steal;
|
||||
use ty::subst::Substs;
|
||||
use util::nodemap::{DefIdSet, DefIdMap, ItemLocalSet};
|
||||
|
|
@ -394,6 +394,11 @@ define_maps! { <'tcx>
|
|||
NoSolution,
|
||||
>,
|
||||
|
||||
/// Do not call this query directly: invoke `normalize_erasing_regions` instead.
|
||||
[] fn normalize_ty_after_erasing_regions: NormalizeTyAfterErasingRegions(
|
||||
ParamEnvAnd<'tcx, Ty<'tcx>>
|
||||
) -> Ty<'tcx>,
|
||||
|
||||
/// Do not call this query directly: invoke `infcx.at().dropck_outlives()` instead.
|
||||
[] fn dropck_outlives: DropckOutlives(
|
||||
CanonicalTyGoal<'tcx>
|
||||
|
|
|
|||
|
|
@ -772,8 +772,9 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>,
|
|||
DepKind::FulfillObligation |
|
||||
DepKind::VtableMethods |
|
||||
DepKind::EraseRegionsTy |
|
||||
DepKind::NormalizeTy |
|
||||
DepKind::NormalizeProjectionTy |
|
||||
DepKind::NormalizeTyAfterErasingRegions |
|
||||
DepKind::NormalizeTy |
|
||||
DepKind::DropckOutlives |
|
||||
DepKind::SubstituteNormalizeAndTestPredicates |
|
||||
DepKind::InstanceDefSizeEstimate |
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
#[macro_use]
|
||||
extern crate rustc;
|
||||
extern crate rustc_data_structures;
|
||||
extern crate syntax;
|
||||
|
|
@ -26,6 +27,7 @@ extern crate syntax_pos;
|
|||
|
||||
mod dropck_outlives;
|
||||
mod normalize_projection_ty;
|
||||
mod normalize_erasing_regions;
|
||||
mod util;
|
||||
|
||||
use rustc::ty::maps::Providers;
|
||||
|
|
@ -35,6 +37,8 @@ pub fn provide(p: &mut Providers) {
|
|||
dropck_outlives: dropck_outlives::dropck_outlives,
|
||||
adt_dtorck_constraint: dropck_outlives::adt_dtorck_constraint,
|
||||
normalize_projection_ty: normalize_projection_ty::normalize_projection_ty,
|
||||
normalize_ty_after_erasing_regions:
|
||||
normalize_erasing_regions::normalize_ty_after_erasing_regions,
|
||||
..*p
|
||||
};
|
||||
}
|
||||
|
|
|
|||
37
src/librustc_traits/normalize_erasing_regions.rs
Normal file
37
src/librustc_traits/normalize_erasing_regions.rs
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use rustc::traits::{Normalized, ObligationCause};
|
||||
use rustc::traits::query::NoSolution;
|
||||
use rustc::ty::{ParamEnvAnd, Ty, TyCtxt};
|
||||
use rustc::util::common::CellUsizeExt;
|
||||
|
||||
crate fn normalize_ty_after_erasing_regions<'tcx>(
|
||||
tcx: TyCtxt<'_, 'tcx, 'tcx>,
|
||||
goal: ParamEnvAnd<'tcx, Ty<'tcx>>,
|
||||
) -> Ty<'tcx> {
|
||||
let ParamEnvAnd { param_env, value } = goal;
|
||||
tcx.sess.perf_stats.normalize_ty_after_erasing_regions.increment();
|
||||
tcx.infer_ctxt().enter(|infcx| {
|
||||
let cause = ObligationCause::dummy();
|
||||
match infcx.at(&cause, param_env).normalize(&value) {
|
||||
Ok(Normalized { value: normalized_value, obligations: _ }) => {
|
||||
// ^^^^^^^^^^^
|
||||
// We don't care about the `obligations`,
|
||||
// they are always only region relations,
|
||||
// and we are about to erase those anyway.
|
||||
let normalized_value = infcx.resolve_type_vars_if_possible(&normalized_value);
|
||||
let normalized_value = infcx.tcx.erase_regions(&normalized_value);
|
||||
tcx.lift_to_global(&normalized_value).unwrap()
|
||||
}
|
||||
Err(NoSolution) => bug!("could not fully normalize `{:?}`", value),
|
||||
}
|
||||
})
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue