Skip to content

Commit

Permalink
transition various normalization functions to the new methods
Browse files Browse the repository at this point in the history
In particular:

- `fully_normalize_monormophic_ty` => `normalize_erasing_regions`
- `normalize_associated_type_in_env` => `normalize_erasing_regions`
- `fully_normalize_associated_types_in` => `normalize_erasing_regions`
- `erase_late_bound_regions_and_normalize` => `normalize_erasing_late_bound_regions`
  • Loading branch information
nikomatsakis committed Mar 13, 2018
1 parent 211d9ad commit e4728e4
Show file tree
Hide file tree
Showing 28 changed files with 91 additions and 283 deletions.
1 change: 0 additions & 1 deletion src/librustc/dep_graph/dep_node.rs
Expand Up @@ -635,7 +635,6 @@ define_dep_nodes!( <'tcx>
[] CodegenUnit(InternedString),
[] CompileCodegenUnit(InternedString),
[input] OutputFilenames,
[anon] NormalizeTy,
[] NormalizeProjectionTy(CanonicalProjectionGoal<'tcx>),
[] NormalizeTyAfterErasingRegions(ParamEnvAnd<'tcx, Ty<'tcx>>),
[] DropckOutlives(CanonicalTyGoal<'tcx>),
Expand Down
136 changes: 1 addition & 135 deletions src/librustc/infer/mod.rs
Expand Up @@ -21,7 +21,6 @@ use hir::def_id::DefId;
use middle::free_region::RegionRelations;
use middle::region;
use middle::lang_items;
use mir::tcx::PlaceTy;
use ty::subst::Substs;
use ty::{TyVid, IntVid, FloatVid};
use ty::{self, Ty, TyCtxt};
Expand All @@ -35,7 +34,7 @@ use std::collections::BTreeMap;
use std::fmt;
use syntax::ast;
use errors::DiagnosticBuilder;
use syntax_pos::{self, Span, DUMMY_SP};
use syntax_pos::{self, Span};
use util::nodemap::FxHashMap;
use arena::DroplessArena;

Expand Down Expand Up @@ -493,140 +492,7 @@ pub struct CombinedSnapshot<'a, 'tcx:'a> {
_in_progress_tables: Option<Ref<'a, ty::TypeckTables<'tcx>>>,
}

/// Helper trait for shortening the lifetimes inside a
/// value for post-type-checking normalization.
///
/// This trait offers a normalization method where the inputs and
/// outputs both have the `'gcx` lifetime; the implementations
/// internally create inference contexts and/or lift as needed.
pub trait TransNormalize<'gcx>: TypeFoldable<'gcx> {
fn trans_normalize<'a, 'tcx>(&self,
infcx: &InferCtxt<'a, 'gcx, 'tcx>,
param_env: ty::ParamEnv<'tcx>)
-> Self;
}

macro_rules! items { ($($item:item)+) => ($($item)+) }
macro_rules! impl_trans_normalize {
($lt_gcx:tt, $($ty:ty),+) => {
items!($(impl<$lt_gcx> TransNormalize<$lt_gcx> for $ty {
fn trans_normalize<'a, 'tcx>(&self,
infcx: &InferCtxt<'a, $lt_gcx, 'tcx>,
param_env: ty::ParamEnv<'tcx>)
-> Self {
infcx.normalize_projections_in(param_env, self)
}
})+);
}
}

impl_trans_normalize!('gcx,
Ty<'gcx>,
&'gcx ty::Const<'gcx>,
&'gcx Substs<'gcx>,
ty::FnSig<'gcx>,
ty::PolyFnSig<'gcx>,
ty::ClosureSubsts<'gcx>,
ty::PolyTraitRef<'gcx>,
ty::ExistentialTraitRef<'gcx>
);

impl<'gcx> TransNormalize<'gcx> for PlaceTy<'gcx> {
fn trans_normalize<'a, 'tcx>(&self,
infcx: &InferCtxt<'a, 'gcx, 'tcx>,
param_env: ty::ParamEnv<'tcx>)
-> Self {
match *self {
PlaceTy::Ty { ty } => PlaceTy::Ty { ty: ty.trans_normalize(infcx, param_env) },
PlaceTy::Downcast { adt_def, substs, variant_index } => {
PlaceTy::Downcast {
adt_def,
substs: substs.trans_normalize(infcx, param_env),
variant_index,
}
}
}
}
}

// NOTE: Callable from trans only!
impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
/// Currently, higher-ranked type bounds inhibit normalization. Therefore,
/// each time we erase them in translation, we need to normalize
/// the contents.
pub fn erase_late_bound_regions_and_normalize<T>(self, value: &ty::Binder<T>)
-> T
where T: TransNormalize<'tcx>
{
assert!(!value.needs_subst());
let value = self.erase_late_bound_regions(value);
self.fully_normalize_associated_types_in(&value)
}

/// Fully normalizes any associated types in `value`, using an
/// empty environment and `Reveal::All` mode (therefore, suitable
/// only for monomorphized code during trans, basically).
pub fn fully_normalize_associated_types_in<T>(self, value: &T) -> T
where T: TransNormalize<'tcx>
{
debug!("fully_normalize_associated_types_in(t={:?})", value);

let param_env = ty::ParamEnv::reveal_all();
let value = self.erase_regions(value);

if !value.has_projections() {
return value;
}

self.infer_ctxt().enter(|infcx| {
value.trans_normalize(&infcx, param_env)
})
}

/// Does a best-effort to normalize any associated types in
/// `value`; this includes revealing specializable types, so this
/// should be not be used during type-checking, but only during
/// optimization and code generation.
pub fn normalize_associated_type_in_env<T>(
self, value: &T, env: ty::ParamEnv<'tcx>
) -> T
where T: TransNormalize<'tcx>
{
debug!("normalize_associated_type_in_env(t={:?})", value);

let value = self.erase_regions(value);

if !value.has_projections() {
return value;
}

self.infer_ctxt().enter(|infcx| {
value.trans_normalize(&infcx, env.with_reveal_all())
})
}
}

impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
fn normalize_projections_in<T>(&self, param_env: ty::ParamEnv<'tcx>, value: &T) -> T::Lifted
where T: TypeFoldable<'tcx> + ty::Lift<'gcx>
{
let mut selcx = traits::SelectionContext::new(self);
let cause = traits::ObligationCause::dummy();
let traits::Normalized { value: result, obligations } =
traits::normalize(&mut selcx, param_env, cause, value);

debug!("normalize_projections_in: result={:?} obligations={:?}",
result, obligations);

let mut fulfill_cx = traits::FulfillmentContext::new();

for obligation in obligations {
fulfill_cx.register_predicate_obligation(self, obligation);
}

self.drain_fulfillment_cx_or_panic(DUMMY_SP, &mut fulfill_cx, &result)
}

/// Finishes processes any obligations that remain in the
/// fulfillment context, and then returns the result with all type
/// variables removed and regions erased. Because this is intended
Expand Down
5 changes: 4 additions & 1 deletion src/librustc/traits/mod.rs
Expand Up @@ -770,7 +770,10 @@ fn vtable_methods<'a, 'tcx>(
// the trait type may have higher-ranked lifetimes in it;
// so erase them if they appear, so that we get the type
// at some particular call site
let substs = tcx.erase_late_bound_regions_and_normalize(&ty::Binder(substs));
let substs = tcx.normalize_erasing_late_bound_regions(
ty::ParamEnv::reveal_all(),
&ty::Binder(substs),
);

// It's possible that the method relies on where clauses that
// do not hold for this particular set of type parameters.
Expand Down
80 changes: 5 additions & 75 deletions src/librustc/traits/trans/mod.rs
Expand Up @@ -14,14 +14,13 @@
// general routines.

use dep_graph::{DepKind, DepTrackingMapConfig};
use infer::TransNormalize;
use std::marker::PhantomData;
use syntax_pos::DUMMY_SP;
use hir::def_id::DefId;
use traits::{FulfillmentContext, Obligation, ObligationCause, SelectionContext, Vtable};
use ty::{self, Ty, TyCtxt};
use ty::subst::{Subst, Substs};
use ty::fold::{TypeFoldable, TypeFolder};
use ty::fold::TypeFoldable;

/// Attempts to resolve an obligation to a vtable.. The result is
/// a shallow vtable resolution -- meaning that we do not
Expand Down Expand Up @@ -93,12 +92,11 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
param_substs: &Substs<'tcx>,
value: &T)
-> T
where T: TransNormalize<'tcx>
where T: TypeFoldable<'tcx>
{
debug!("apply_param_substs(param_substs={:?}, value={:?})", param_substs, value);
let substituted = value.subst(self, param_substs);
let substituted = self.erase_regions(&substituted);
AssociatedTypeNormalizer::new(self).fold(&substituted)
self.normalize_erasing_regions(ty::ParamEnv::reveal_all(), substituted)
}

pub fn trans_apply_param_substs_env<T>(
Expand All @@ -108,7 +106,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
value: &T,
) -> T
where
T: TransNormalize<'tcx>,
T: TypeFoldable<'tcx>,
{
debug!(
"apply_param_substs_env(param_substs={:?}, value={:?}, param_env={:?})",
Expand All @@ -117,8 +115,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
param_env,
);
let substituted = value.subst(self, param_substs);
let substituted = self.erase_regions(&substituted);
AssociatedTypeNormalizerEnv::new(self, param_env).fold(&substituted)
self.normalize_erasing_regions(param_env, substituted)
}

pub fn trans_impl_self_ty(&self, def_id: DefId, substs: &'tcx Substs<'tcx>)
Expand All @@ -128,73 +125,6 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
}
}

struct AssociatedTypeNormalizer<'a, 'gcx: 'a> {
tcx: TyCtxt<'a, 'gcx, 'gcx>,
}

impl<'a, 'gcx> AssociatedTypeNormalizer<'a, 'gcx> {
fn new(tcx: TyCtxt<'a, 'gcx, 'gcx>) -> Self {
AssociatedTypeNormalizer { tcx }
}

fn fold<T:TypeFoldable<'gcx>>(&mut self, value: &T) -> T {
if !value.has_projections() {
value.clone()
} else {
value.fold_with(self)
}
}
}

impl<'a, 'gcx> TypeFolder<'gcx, 'gcx> for AssociatedTypeNormalizer<'a, 'gcx> {
fn tcx<'c>(&'c self) -> TyCtxt<'c, 'gcx, 'gcx> {
self.tcx
}

fn fold_ty(&mut self, ty: Ty<'gcx>) -> Ty<'gcx> {
if !ty.has_projections() {
ty
} else {
debug!("AssociatedTypeNormalizer: ty={:?}", ty);
self.tcx.fully_normalize_monormophic_ty(ty)
}
}
}

struct AssociatedTypeNormalizerEnv<'a, 'gcx: 'a> {
tcx: TyCtxt<'a, 'gcx, 'gcx>,
param_env: ty::ParamEnv<'gcx>,
}

impl<'a, 'gcx> AssociatedTypeNormalizerEnv<'a, 'gcx> {
fn new(tcx: TyCtxt<'a, 'gcx, 'gcx>, param_env: ty::ParamEnv<'gcx>) -> Self {
Self { tcx, param_env }
}

fn fold<T: TypeFoldable<'gcx>>(&mut self, value: &T) -> T {
if !value.has_projections() {
value.clone()
} else {
value.fold_with(self)
}
}
}

impl<'a, 'gcx> TypeFolder<'gcx, 'gcx> for AssociatedTypeNormalizerEnv<'a, 'gcx> {
fn tcx<'c>(&'c self) -> TyCtxt<'c, 'gcx, 'gcx> {
self.tcx
}

fn fold_ty(&mut self, ty: Ty<'gcx>) -> Ty<'gcx> {
if !ty.has_projections() {
ty
} else {
debug!("AssociatedTypeNormalizerEnv: ty={:?}", ty);
self.tcx.normalize_associated_type_in_env(&ty, self.param_env)
}
}
}

// Implement DepTrackingMapConfig for `trait_cache`
pub struct TraitSelectionCache<'tcx> {
data: PhantomData<&'tcx ()>
Expand Down
3 changes: 0 additions & 3 deletions src/librustc/ty/context.rs
Expand Up @@ -2537,9 +2537,6 @@ pub fn provide(providers: &mut ty::maps::Providers) {
assert_eq!(cnum, LOCAL_CRATE);
tcx.features().clone_closures
};
providers.fully_normalize_monormophic_ty = |tcx, ty| {
tcx.fully_normalize_associated_types_in(&ty)
};
providers.features_query = |tcx, cnum| {
assert_eq!(cnum, LOCAL_CRATE);
Lrc::new(tcx.sess.features_untracked().clone())
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/ty/instance.rs
Expand Up @@ -352,7 +352,7 @@ fn fn_once_adapter_instance<'a, 'tcx>(
closure_did, substs);

let sig = substs.closure_sig(closure_did, tcx);
let sig = tcx.erase_late_bound_regions_and_normalize(&sig);
let sig = tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig);
assert_eq!(sig.inputs().len(), 1);
let substs = tcx.mk_substs([Kind::from(self_ty), sig.inputs()[0].into()].iter().cloned());

Expand Down
12 changes: 6 additions & 6 deletions src/librustc/ty/layout.rs
Expand Up @@ -1213,7 +1213,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
data_ptr.valid_range.start = 1;
}

let pointee = tcx.normalize_associated_type_in_env(&pointee, param_env);
let pointee = tcx.normalize_erasing_regions(param_env, pointee);
if pointee.is_sized(tcx.at(DUMMY_SP), param_env) {
return Ok(tcx.intern_layout(LayoutDetails::scalar(self, data_ptr)));
}
Expand Down Expand Up @@ -1241,7 +1241,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
// Arrays and slices.
ty::TyArray(element, mut count) => {
if count.has_projections() {
count = tcx.normalize_associated_type_in_env(&count, param_env);
count = tcx.normalize_erasing_regions(param_env, count);
if count.has_projections() {
return Err(LayoutError::Unknown(ty));
}
Expand Down Expand Up @@ -1686,7 +1686,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {

// Types with no meaningful known layout.
ty::TyProjection(_) | ty::TyAnon(..) => {
let normalized = tcx.normalize_associated_type_in_env(&ty, param_env);
let normalized = tcx.normalize_erasing_regions(param_env, ty);
if ty == normalized {
return Err(LayoutError::Unknown(ty));
}
Expand Down Expand Up @@ -1953,7 +1953,7 @@ impl<'a, 'tcx> SizeSkeleton<'tcx> {
}

ty::TyProjection(_) | ty::TyAnon(..) => {
let normalized = tcx.normalize_associated_type_in_env(&ty, param_env);
let normalized = tcx.normalize_erasing_regions(param_env, ty);
if ty == normalized {
Err(err)
} else {
Expand Down Expand Up @@ -2059,7 +2059,7 @@ impl<'a, 'tcx> LayoutOf<Ty<'tcx>> for LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
/// executes in "reveal all" mode.
fn layout_of(self, ty: Ty<'tcx>) -> Self::TyLayout {
let param_env = self.param_env.with_reveal_all();
let ty = self.tcx.normalize_associated_type_in_env(&ty, param_env);
let ty = self.tcx.normalize_erasing_regions(param_env, ty);
let details = self.tcx.layout_raw(param_env.and(ty))?;
let layout = TyLayout {
ty,
Expand All @@ -2085,7 +2085,7 @@ impl<'a, 'tcx> LayoutOf<Ty<'tcx>> for LayoutCx<'tcx, ty::maps::TyCtxtAt<'a, 'tcx
/// executes in "reveal all" mode.
fn layout_of(self, ty: Ty<'tcx>) -> Self::TyLayout {
let param_env = self.param_env.with_reveal_all();
let ty = self.tcx.normalize_associated_type_in_env(&ty, param_env);
let ty = self.tcx.normalize_erasing_regions(param_env, ty);
let details = self.tcx.layout_raw(param_env.and(ty))?;
let layout = TyLayout {
ty,
Expand Down
6 changes: 0 additions & 6 deletions src/librustc/ty/maps/config.rs
Expand Up @@ -610,12 +610,6 @@ impl<'tcx> QueryDescription<'tcx> for queries::has_copy_closures<'tcx> {
}
}

impl<'tcx> QueryDescription<'tcx> for queries::fully_normalize_monormophic_ty<'tcx> {
fn describe(_tcx: TyCtxt, _: Ty) -> String {
format!("normalizing types")
}
}

impl<'tcx> QueryDescription<'tcx> for queries::features_query<'tcx> {
fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
format!("looking up enabled feature gates")
Expand Down

0 comments on commit e4728e4

Please sign in to comment.