]> git.lizzy.rs Git - rust.git/commitdiff
centralize the caching for is-copy, is-sized, and is-freeze
authorNiko Matsakis <niko@alum.mit.edu>
Wed, 10 May 2017 14:28:06 +0000 (10:28 -0400)
committerNiko Matsakis <niko@alum.mit.edu>
Mon, 22 May 2017 18:55:03 +0000 (14:55 -0400)
Use the trait-environment+type as the key. Note that these
are only invoked on types that live for the entire compilation
(no inference artifacts). We no longer need the various special-case
bits and caches that were in place before.

22 files changed:
src/librustc/dep_graph/dep_node.rs
src/librustc/infer/mod.rs
src/librustc/traits/mod.rs
src/librustc/traits/select.rs
src/librustc/ty/layout.rs
src/librustc/ty/maps.rs
src/librustc/ty/mod.rs
src/librustc/ty/util.rs
src/librustc/util/ppaux.rs
src/librustc_borrowck/borrowck/mir/elaborate_drops.rs
src/librustc_borrowck/borrowck/mir/gather_moves.rs
src/librustc_borrowck/borrowck/mir/mod.rs
src/librustc_const_eval/check_match.rs
src/librustc_lint/builtin.rs
src/librustc_mir/hair/cx/mod.rs
src/librustc_mir/shim.rs
src/librustc_mir/transform/inline.rs
src/librustc_mir/transform/qualify_consts.rs
src/librustc_mir/util/elaborate_drops.rs
src/librustc_passes/consts.rs
src/librustc_trans/context.rs
src/librustc_typeck/check/compare_method.rs

index 15c4469b74694c98d3108c0002a9840329f6b53f..d268c8787cceef59a88726247cab5af6a17a6bf9 100644 (file)
@@ -108,6 +108,9 @@ pub enum DepNode<D: Clone + Debug> {
     SymbolName(D),
     SpecializationGraph(D),
     ObjectSafety(D),
+    IsCopy(D),
+    IsSized(D),
+    IsFreeze(D),
 
     // The set of impls for a given trait. Ultimately, it would be
     // nice to get more fine-grained here (e.g., to include a
@@ -233,6 +236,9 @@ pub fn map_def<E, OP>(&self, mut op: OP) -> Option<DepNode<E>>
             // they are always absolute.
             WorkProduct(ref id) => Some(WorkProduct(id.clone())),
 
+            IsCopy(ref d) => op(d).map(IsCopy),
+            IsSized(ref d) => op(d).map(IsSized),
+            IsFreeze(ref d) => op(d).map(IsFreeze),
             Hir(ref d) => op(d).map(Hir),
             HirBody(ref d) => op(d).map(HirBody),
             MetaData(ref d) => op(d).map(MetaData),
index 1ecc277c7ca4d27dd407cfc9ff39b1f910c5ecdb..7dcad0122e8a66d393b2a50f9a795a466e22460e 100644 (file)
@@ -28,7 +28,7 @@
 use mir::tcx::LvalueTy;
 use ty::subst::{Kind, Subst, Substs};
 use ty::{TyVid, IntVid, FloatVid};
-use ty::{self, Ty, TyCtxt};
+use ty::{self, ParameterEnvironment, Ty, TyCtxt};
 use ty::error::{ExpectedFound, TypeError, UnconstrainedNumeric};
 use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
 use ty::relate::{Relate, RelateResult, TypeRelation};
@@ -526,9 +526,7 @@ pub fn enter<F, R>(&'tcx mut self, f: F) -> R
         let tables = tables.map(InferTables::Interned).unwrap_or_else(|| {
             fresh_tables.as_ref().map_or(InferTables::Missing, InferTables::InProgress)
         });
-        let param_env = param_env.take().unwrap_or_else(|| {
-            global_tcx.empty_parameter_environment()
-        });
+        let param_env = param_env.take().unwrap_or_else(|| ParameterEnvironment::empty());
         global_tcx.enter_local(arena, |tcx| f(InferCtxt {
             tcx: tcx,
             tables: tables,
@@ -650,7 +648,7 @@ pub fn normalize_associated_type<T>(self, value: &T) -> T
     }
 
     pub fn normalize_associated_type_in_env<T>(
-        self, value: &T, env: &'a ty::ParameterEnvironment<'tcx>
+        self, value: &T, env: ty::ParameterEnvironment<'tcx>
     ) -> T
         where T: TransNormalize<'tcx>
     {
@@ -662,7 +660,7 @@ pub fn normalize_associated_type_in_env<T>(
             return value;
         }
 
-        self.infer_ctxt(env.clone(), Reveal::All).enter(|infcx| {
+        self.infer_ctxt(env, Reveal::All).enter(|infcx| {
             value.trans_normalize(&infcx)
        })
     }
@@ -1674,8 +1672,8 @@ pub fn upvar_capture(&self, upvar_id: ty::UpvarId) -> Option<ty::UpvarCapture<'t
         self.tables.borrow().upvar_capture_map.get(&upvar_id).cloned()
     }
 
-    pub fn param_env(&self) -> &ty::ParameterEnvironment<'gcx> {
-        &self.parameter_environment
+    pub fn param_env(&self) -> ty::ParameterEnvironment<'gcx> {
+        self.parameter_environment
     }
 
     pub fn closure_kind(&self,
index 1823373348badfb8ef177602d852f4ed29ff0217..9e3381d8450d38b3f629e7e74b2009fd8794d0c3 100644 (file)
@@ -477,7 +477,7 @@ pub fn normalize_param_env_or_error<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     debug!("normalize_param_env_or_error: elaborated-predicates={:?}",
            predicates);
 
-    let elaborated_env = unnormalized_env.with_caller_bounds(tcx.intern_predicates(&predicates));
+    let elaborated_env = ty::ParameterEnvironment::new(tcx.intern_predicates(&predicates));
 
     tcx.infer_ctxt(elaborated_env, Reveal::UserFacing).enter(|infcx| {
         let predicates = match fully_normalize(
@@ -528,7 +528,7 @@ pub fn normalize_param_env_or_error<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         debug!("normalize_param_env_or_error: resolved predicates={:?}",
             predicates);
 
-        infcx.parameter_environment.with_caller_bounds(tcx.intern_predicates(&predicates))
+        ty::ParameterEnvironment::new(tcx.intern_predicates(&predicates))
     })
 }
 
index cccc20e5b296bd692fdd23ec52144512fd942582..5be07e712b69553cb407c2a1926fd6a13f317d70 100644 (file)
@@ -315,7 +315,7 @@ pub fn tcx(&self) -> TyCtxt<'cx, 'gcx, 'tcx> {
         self.infcx.tcx
     }
 
-    pub fn param_env(&self) -> &'cx ty::ParameterEnvironment<'gcx> {
+    pub fn param_env(&self) -> ty::ParameterEnvironment<'gcx> {
         self.infcx.param_env()
     }
 
index bd38a6c3fd39a6edad843f3053b95fe8b4325ea4..66935dd3a3bb8cfb609ac9400086e0853ba07948 100644 (file)
@@ -1079,7 +1079,7 @@ pub fn compute_uncached(ty: Ty<'gcx>,
         let ptr_layout = |pointee: Ty<'gcx>| {
             let non_zero = !ty.is_unsafe_ptr();
             let pointee = infcx.normalize_projections(pointee);
-            if pointee.is_sized(tcx, &infcx.parameter_environment, DUMMY_SP) {
+            if pointee.is_sized(tcx, infcx.parameter_environment, DUMMY_SP) {
                 Ok(Scalar { value: Pointer, non_zero: non_zero })
             } else {
                 let unsized_part = tcx.struct_tail(pointee);
@@ -1272,7 +1272,7 @@ pub fn compute_uncached(ty: Ty<'gcx>,
                         let fields = &def.variants[0].fields;
                         let last_field = &fields[fields.len()-1];
                         let always_sized = tcx.type_of(last_field.did)
-                          .is_sized(tcx, &param_env, DUMMY_SP);
+                          .is_sized(tcx, param_env, DUMMY_SP);
                         if !always_sized { StructKind::MaybeUnsizedUnivariant }
                         else { StructKind::AlwaysSizedUnivariant }
                     };
index 85462bd9b1273ca2a40946ace10c0355abcb9212..b0868ac389b463d865b58c07708a111b40c62152 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 use dep_graph::{DepGraph, DepNode, DepTrackingMap, DepTrackingMapConfig};
-use hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
+use hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId, LOCAL_CRATE};
 use hir::def::Def;
 use hir;
 use middle::const_val;
@@ -136,6 +136,15 @@ fn default_span(&self, tcx: TyCtxt) -> Span {
     }
 }
 
+impl<'tcx, T: Clone + Hash + Eq + Debug> Key for ty::ParameterEnvironmentAnd<'tcx, T> {
+    fn map_crate(&self) -> CrateNum {
+        LOCAL_CRATE
+    }
+    fn default_span(&self, _: TyCtxt) -> Span {
+        DUMMY_SP
+    }
+}
+
 trait Value<'tcx>: Sized {
     fn from_cycle_error<'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Self;
 }
@@ -244,6 +253,24 @@ impl<M: DepTrackingMapConfig<Key=DefId>> QueryDescription for M {
     }
 }
 
+impl<'tcx> QueryDescription for queries::is_copy_raw<'tcx> {
+    fn describe(_tcx: TyCtxt, env: ty::ParameterEnvironmentAnd<'tcx, Ty<'tcx>>) -> String {
+        format!("computing whether `{}` is `Copy`", env.value)
+    }
+}
+
+impl<'tcx> QueryDescription for queries::is_sized_raw<'tcx> {
+    fn describe(_tcx: TyCtxt, env: ty::ParameterEnvironmentAnd<'tcx, Ty<'tcx>>) -> String {
+        format!("computing whether `{}` is `Sized`", env.value)
+    }
+}
+
+impl<'tcx> QueryDescription for queries::is_freeze_raw<'tcx> {
+    fn describe(_tcx: TyCtxt, env: ty::ParameterEnvironmentAnd<'tcx, Ty<'tcx>>) -> String {
+        format!("computing whether `{}` is freeze", env.value)
+    }
+}
+
 impl<'tcx> QueryDescription for queries::super_predicates_of<'tcx> {
     fn describe(tcx: TyCtxt, def_id: DefId) -> String {
         format!("computing the supertraits of `{}`",
@@ -856,6 +883,12 @@ fn default() -> Self {
         -> ty::trait_def::TraitImpls,
     [] specialization_graph_of: SpecializationGraph(DefId) -> Rc<specialization_graph::Graph>,
     [] is_object_safe: ObjectSafety(DefId) -> bool,
+
+    // Trait selection queries. These are best used by invoking `ty.moves_by_default()`,
+    // `ty.is_copy()`, etc, since that will prune the environment where possible.
+    [] is_copy_raw: is_copy_dep_node(ty::ParameterEnvironmentAnd<'tcx, Ty<'tcx>>) -> bool,
+    [] is_sized_raw: is_sized_dep_node(ty::ParameterEnvironmentAnd<'tcx, Ty<'tcx>>) -> bool,
+    [] is_freeze_raw: is_freeze_dep_node(ty::ParameterEnvironmentAnd<'tcx, Ty<'tcx>>) -> bool,
 }
 
 fn coherent_trait_dep_node((_, def_id): (CrateNum, DefId)) -> DepNode<DefId> {
@@ -899,3 +932,18 @@ fn crate_variances(_: CrateNum) -> DepNode<DefId> {
 fn relevant_trait_impls_for((def_id, _): (DefId, SimplifiedType)) -> DepNode<DefId> {
     DepNode::TraitImpls(def_id)
 }
+
+fn is_copy_dep_node<'tcx>(_: ty::ParameterEnvironmentAnd<'tcx, Ty<'tcx>>) -> DepNode<DefId> {
+    let krate_def_id = DefId::local(CRATE_DEF_INDEX);
+    DepNode::IsCopy(krate_def_id)
+}
+
+fn is_sized_dep_node<'tcx>(_: ty::ParameterEnvironmentAnd<'tcx, Ty<'tcx>>) -> DepNode<DefId> {
+    let krate_def_id = DefId::local(CRATE_DEF_INDEX);
+    DepNode::IsSized(krate_def_id)
+}
+
+fn is_freeze_dep_node<'tcx>(_: ty::ParameterEnvironmentAnd<'tcx, Ty<'tcx>>) -> DepNode<DefId> {
+    let krate_def_id = DefId::local(CRATE_DEF_INDEX);
+    DepNode::IsSized(krate_def_id)
+}
index 359722ce96ec9786f0131c197805fac38806bfe7..9036db9e3d543154073438a00d4f268096432b70 100644 (file)
@@ -35,7 +35,7 @@
 use util::nodemap::{NodeSet, DefIdMap, FxHashMap, FxHashSet};
 
 use serialize::{self, Encodable, Encoder};
-use std::cell::{Cell, RefCell};
+use std::cell::Cell;
 use std::collections::BTreeMap;
 use std::cmp;
 use std::fmt;
@@ -507,8 +507,6 @@ pub enum FragmentInfo {
         // Caches for type_is_sized, type_moves_by_default
         const SIZEDNESS_CACHED  = 1 << 16,
         const IS_SIZED          = 1 << 17,
-        const MOVENESS_CACHED   = 1 << 18,
-        const MOVES_BY_DEFAULT  = 1 << 19,
         const FREEZENESS_CACHED = 1 << 20,
         const IS_FREEZE         = 1 << 21,
         const NEEDS_DROP_CACHED = 1 << 22,
@@ -1250,45 +1248,34 @@ pub fn is_empty(&self) -> bool {
 }
 
 /// When type checking, we use the `ParameterEnvironment` to track
-/// details about the type/lifetime parameters that are in scope.
-/// It primarily stores the bounds information.
-///
-/// Note: This information might seem to be redundant with the data in
-/// `tcx.ty_param_defs`, but it is not. That table contains the
-/// parameter definitions from an "outside" perspective, but this
-/// struct will contain the bounds for a parameter as seen from inside
-/// the function body. Currently the only real distinction is that
-/// bound lifetime parameters are replaced with free ones, but in the
-/// future I hope to refine the representation of types so as to make
-/// more distinctions clearer.
-#[derive(Clone)]
+/// details about the set of where-clauses that are in scope at this
+/// particular point.
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
 pub struct ParameterEnvironment<'tcx> {
     /// Obligations that the caller must satisfy. This is basically
     /// the set of bounds on the in-scope type parameters, translated
     /// into Obligations, and elaborated and normalized.
-    pub caller_bounds: &'tcx [ty::Predicate<'tcx>],
-
-    /// A cache for `moves_by_default`.
-    pub is_copy_cache: RefCell<FxHashMap<Ty<'tcx>, bool>>,
+    pub caller_bounds: &'tcx Slice<ty::Predicate<'tcx>>,
+}
 
-    /// A cache for `type_is_sized`
-    pub is_sized_cache: RefCell<FxHashMap<Ty<'tcx>, bool>>,
+impl<'tcx> ParameterEnvironment<'tcx> {
+    pub fn and<T>(self, value: T) -> ParameterEnvironmentAnd<'tcx, T> {
+        ParameterEnvironmentAnd {
+            param_env: self,
+            value: value,
+        }
+    }
+}
 
-    /// A cache for `type_is_freeze`
-    pub is_freeze_cache: RefCell<FxHashMap<Ty<'tcx>, bool>>,
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
+pub struct ParameterEnvironmentAnd<'tcx, T> {
+    pub param_env: ParameterEnvironment<'tcx>,
+    pub value: T,
 }
 
-impl<'a, 'tcx> ParameterEnvironment<'tcx> {
-    pub fn with_caller_bounds(&self,
-                              caller_bounds: &'tcx [ty::Predicate<'tcx>])
-                              -> ParameterEnvironment<'tcx>
-    {
-        ParameterEnvironment {
-            caller_bounds: caller_bounds,
-            is_copy_cache: RefCell::new(FxHashMap()),
-            is_sized_cache: RefCell::new(FxHashMap()),
-            is_freeze_cache: RefCell::new(FxHashMap()),
-        }
+impl<'tcx, T> ParameterEnvironmentAnd<'tcx, T> {
+    pub fn into_parts(self) -> (ParameterEnvironment<'tcx>, T) {
+        (self.param_env, self.value)
     }
 }
 
@@ -2357,17 +2344,6 @@ pub fn impl_of_method(self, def_id: DefId) -> Option<DefId> {
         }
     }
 
-    /// Construct a parameter environment suitable for static contexts or other contexts where there
-    /// are no free type/lifetime parameters in scope.
-    pub fn empty_parameter_environment(self) -> ParameterEnvironment<'tcx> {
-        ty::ParameterEnvironment {
-            caller_bounds: Slice::empty(),
-            is_copy_cache: RefCell::new(FxHashMap()),
-            is_sized_cache: RefCell::new(FxHashMap()),
-            is_freeze_cache: RefCell::new(FxHashMap()),
-        }
-    }
-
     /// See `ParameterEnvironment` struct def'n for details.
     pub fn parameter_environment(self, def_id: DefId) -> ParameterEnvironment<'gcx> {
         //
@@ -2391,12 +2367,7 @@ pub fn parameter_environment(self, def_id: DefId) -> ParameterEnvironment<'gcx>
         // sure that this will succeed without errors anyway.
         //
 
-        let unnormalized_env = ty::ParameterEnvironment {
-            caller_bounds: tcx.intern_predicates(&predicates),
-            is_copy_cache: RefCell::new(FxHashMap()),
-            is_sized_cache: RefCell::new(FxHashMap()),
-            is_freeze_cache: RefCell::new(FxHashMap()),
-        };
+        let unnormalized_env = ty::ParameterEnvironment::new(tcx.intern_predicates(&predicates));
 
         let body_id = self.hir.as_local_node_id(def_id).map_or(DUMMY_NODE_ID, |id| {
             self.hir.maybe_body_owned_by(id).map_or(id, |body| body.node_id)
@@ -2566,6 +2537,7 @@ fn trait_of_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Option
 
 
 pub fn provide(providers: &mut ty::maps::Providers) {
+    util::provide(providers);
     *providers = ty::maps::Providers {
         associated_item,
         associated_item_def_ids,
index c6c6a0e47003dbb40777d056b2ade638c6259eb7..b9276281a54e666c9a136c8a3028e5356d50a56b 100644 (file)
 use infer::InferCtxt;
 use ich::{StableHashingContext, NodeIdHashingMode};
 use traits::{self, Reveal};
-use ty::{self, Ty, TyCtxt, TypeAndMut, TypeFlags, TypeFoldable};
+use ty::{self, Ty, TyCtxt, TypeFlags, TypeFoldable};
 use ty::ParameterEnvironment;
 use ty::fold::TypeVisitor;
 use ty::layout::{Layout, LayoutError};
 use ty::subst::{Subst, Kind};
 use ty::TypeVariants::*;
 use util::common::ErrorReported;
-use util::nodemap::{FxHashMap, FxHashSet};
+use util::nodemap::FxHashSet;
 use middle::lang_items;
 
 use rustc_const_math::{ConstInt, ConstIsize, ConstUsize};
 use rustc_data_structures::stable_hasher::{StableHasher, StableHasherResult,
                                            HashStable};
-use std::cell::RefCell;
 use std::cmp;
 use std::hash::Hash;
 use std::intrinsics;
@@ -36,8 +35,6 @@
 use syntax::attr::{self, SignedInt, UnsignedInt};
 use syntax_pos::{Span, DUMMY_SP};
 
-use hir;
-
 type Disr = ConstInt;
 
 pub trait IntTypeExt {
@@ -153,6 +150,17 @@ pub enum Representability {
 }
 
 impl<'tcx> ParameterEnvironment<'tcx> {
+    /// Construct a trait environment suitable for contexts where
+    /// there are no where clauses in scope.
+    pub fn empty() -> Self {
+        Self::new(ty::Slice::empty())
+    }
+
+    /// Construct a trait environment with the given set of predicates.
+    pub fn new(caller_bounds: &'tcx ty::Slice<ty::Predicate<'tcx>>) -> Self {
+        ty::ParameterEnvironment { caller_bounds }
+    }
+
     pub fn can_type_implement_copy<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                        self_type: Ty<'tcx>, span: Span)
                                        -> Result<(), CopyImplementationError> {
@@ -711,152 +719,40 @@ fn visit_binder<T: TypeFoldable<'tcx>>(&mut self, x: &ty::Binder<T>) -> bool {
 }
 
 impl<'a, 'tcx> ty::TyS<'tcx> {
-    fn impls_bound(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                   param_env: &ParameterEnvironment<'tcx>,
-                   def_id: DefId,
-                   cache: &RefCell<FxHashMap<Ty<'tcx>, bool>>,
-                   span: Span) -> bool
-    {
-        if self.has_param_types() || self.has_self_ty() {
-            if let Some(result) = cache.borrow().get(self) {
-                return *result;
-            }
-        }
-        let result =
-            tcx.infer_ctxt(param_env.clone(), Reveal::UserFacing)
-            .enter(|infcx| {
-                traits::type_known_to_meet_bound(&infcx, self, def_id, span)
-            });
+    pub fn moves_by_default(&'tcx self,
+                            tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                            param_env: ParameterEnvironment<'tcx>,
+                            span: Span)
+                            -> bool {
         if self.has_param_types() || self.has_self_ty() {
-            cache.borrow_mut().insert(self, result);
-        }
-        return result;
-    }
-
-    // FIXME (@jroesch): I made this public to use it, not sure if should be private
-    pub fn moves_by_default(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                            param_env: &ParameterEnvironment<'tcx>,
-                            span: Span) -> bool {
-        if self.flags.get().intersects(TypeFlags::MOVENESS_CACHED) {
-            return self.flags.get().intersects(TypeFlags::MOVES_BY_DEFAULT);
-        }
-
-        assert!(!self.needs_infer());
-
-        // Fast-path for primitive types
-        let result = match self.sty {
-            TyBool | TyChar | TyInt(..) | TyUint(..) | TyFloat(..) | TyNever |
-            TyRawPtr(..) | TyFnDef(..) | TyFnPtr(_) | TyRef(_, TypeAndMut {
-                mutbl: hir::MutImmutable, ..
-            }) => Some(false),
-
-            TyStr | TyRef(_, TypeAndMut {
-                mutbl: hir::MutMutable, ..
-            }) => Some(true),
-
-            TyArray(..) | TySlice(..) | TyDynamic(..) | TyTuple(..) |
-            TyClosure(..) | TyAdt(..) | TyAnon(..) |
-            TyProjection(..) | TyParam(..) | TyInfer(..) | TyError => None
-        }.unwrap_or_else(|| {
-            !self.impls_bound(tcx, param_env,
-                              tcx.require_lang_item(lang_items::CopyTraitLangItem),
-                              &param_env.is_copy_cache, span) });
-
-        if !self.has_param_types() && !self.has_self_ty() {
-            self.flags.set(self.flags.get() | if result {
-                TypeFlags::MOVENESS_CACHED | TypeFlags::MOVES_BY_DEFAULT
-            } else {
-                TypeFlags::MOVENESS_CACHED
-            });
+            !tcx.at(span).is_copy_raw(param_env.and(self))
+        } else {
+            !tcx.is_copy_raw(ParameterEnvironment::empty().and(self))
         }
-
-        result
     }
 
-    #[inline]
-    pub fn is_sized(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                    param_env: &ParameterEnvironment<'tcx>,
-                    span: Span) -> bool
+    pub fn is_sized(&'tcx self,
+                    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                    param_env: ParameterEnvironment<'tcx>,
+                    span: Span)-> bool
     {
-        if self.flags.get().intersects(TypeFlags::SIZEDNESS_CACHED) {
-            return self.flags.get().intersects(TypeFlags::IS_SIZED);
-        }
-
-        self.is_sized_uncached(tcx, param_env, span)
-    }
-
-    fn is_sized_uncached(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                         param_env: &ParameterEnvironment<'tcx>,
-                         span: Span) -> bool {
-        assert!(!self.needs_infer());
-
-        // Fast-path for primitive types
-        let result = match self.sty {
-            TyBool | TyChar | TyInt(..) | TyUint(..) | TyFloat(..) |
-            TyRawPtr(..) | TyRef(..) | TyFnDef(..) | TyFnPtr(_) |
-            TyArray(..) | TyTuple(..) | TyClosure(..) | TyNever => Some(true),
-
-            TyStr | TyDynamic(..) | TySlice(_) => Some(false),
-
-            TyAdt(..) | TyProjection(..) | TyParam(..) |
-            TyInfer(..) | TyAnon(..) | TyError => None
-        }.unwrap_or_else(|| {
-            self.impls_bound(tcx, param_env, tcx.require_lang_item(lang_items::SizedTraitLangItem),
-                              &param_env.is_sized_cache, span) });
-
-        if !self.has_param_types() && !self.has_self_ty() {
-            self.flags.set(self.flags.get() | if result {
-                TypeFlags::SIZEDNESS_CACHED | TypeFlags::IS_SIZED
-            } else {
-                TypeFlags::SIZEDNESS_CACHED
-            });
+        if self.has_param_types() || self.has_self_ty() {
+            tcx.at(span).is_sized_raw(param_env.and(self))
+        } else {
+            tcx.is_sized_raw(ParameterEnvironment::empty().and(self))
         }
-
-        result
     }
 
-    /// Returns `true` if and only if there are no `UnsafeCell`s
-    /// nested within the type (ignoring `PhantomData` or pointers).
-    #[inline]
-    pub fn is_freeze(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                     param_env: &ParameterEnvironment<'tcx>,
-                     span: Span) -> bool
+    pub fn is_freeze(&'tcx self,
+                     tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                     param_env: ParameterEnvironment<'tcx>,
+                     span: Span)-> bool
     {
-        if self.flags.get().intersects(TypeFlags::FREEZENESS_CACHED) {
-            return self.flags.get().intersects(TypeFlags::IS_FREEZE);
-        }
-
-        self.is_freeze_uncached(tcx, param_env, span)
-    }
-
-    fn is_freeze_uncached(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                          param_env: &ParameterEnvironment<'tcx>,
-                          span: Span) -> bool {
-        assert!(!self.needs_infer());
-
-        // Fast-path for primitive types
-        let result = match self.sty {
-            TyBool | TyChar | TyInt(..) | TyUint(..) | TyFloat(..) |
-            TyRawPtr(..) | TyRef(..) | TyFnDef(..) | TyFnPtr(_) |
-            TyStr | TyNever => Some(true),
-
-            TyArray(..) | TySlice(_) |
-            TyTuple(..) | TyClosure(..) | TyAdt(..) |
-            TyDynamic(..) | TyProjection(..) | TyParam(..) |
-            TyInfer(..) | TyAnon(..) | TyError => None
-        }.unwrap_or_else(|| {
-            self.impls_bound(tcx, param_env, tcx.require_lang_item(lang_items::FreezeTraitLangItem),
-                              &param_env.is_freeze_cache, span) });
-
-        if !self.has_param_types() && !self.has_self_ty() {
-            self.flags.set(self.flags.get() | if result {
-                TypeFlags::FREEZENESS_CACHED | TypeFlags::IS_FREEZE
-            } else {
-                TypeFlags::FREEZENESS_CACHED
-            });
+        if self.has_param_types() || self.has_self_ty() {
+            tcx.at(span).is_freeze_raw(param_env.and(self))
+        } else {
+            tcx.is_freeze_raw(ParameterEnvironment::empty().and(self))
         }
-
-        result
     }
 
     /// If `ty.needs_drop(...)` returns `true`, then `ty` is definitely
@@ -866,8 +762,10 @@ fn is_freeze_uncached(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
     /// (Note that this implies that if `ty` has a destructor attached,
     /// then `needs_drop` will definitely return `true` for `ty`.)
     #[inline]
-    pub fn needs_drop(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                    param_env: &ty::ParameterEnvironment<'tcx>) -> bool {
+    pub fn needs_drop(&'tcx self,
+                      tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                      param_env: ty::ParameterEnvironment<'tcx>)
+                      -> bool {
         if self.flags.get().intersects(TypeFlags::NEEDS_DROP_CACHED) {
             return self.flags.get().intersects(TypeFlags::NEEDS_DROP);
         }
@@ -877,7 +775,7 @@ pub fn needs_drop(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
     fn needs_drop_inner(&'tcx self,
                         tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                        param_env: &ty::ParameterEnvironment<'tcx>,
+                        param_env: ty::ParameterEnvironment<'tcx>,
                         stack: &mut FxHashSet<Ty<'tcx>>)
                         -> bool {
         if self.flags.get().intersects(TypeFlags::NEEDS_DROP_CACHED) {
@@ -902,7 +800,7 @@ fn needs_drop_inner(&'tcx self,
 
     fn needs_drop_uncached(&'tcx self,
                            tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                           param_env: &ty::ParameterEnvironment<'tcx>,
+                           param_env: ty::ParameterEnvironment<'tcx>,
                            stack: &mut FxHashSet<Ty<'tcx>>)
                            -> bool {
         assert!(!self.needs_infer());
@@ -1158,3 +1056,42 @@ fn is_type_structurally_recursive<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         r
     }
 }
+
+fn is_copy_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                         query: ty::ParameterEnvironmentAnd<'tcx, Ty<'tcx>>)
+                         -> bool
+{
+    let (param_env, ty) = query.into_parts();
+    let trait_def_id = tcx.require_lang_item(lang_items::CopyTraitLangItem);
+    tcx.infer_ctxt(param_env, Reveal::UserFacing)
+       .enter(|infcx| traits::type_known_to_meet_bound(&infcx, ty, trait_def_id, DUMMY_SP))
+}
+
+fn is_sized_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                          query: ty::ParameterEnvironmentAnd<'tcx, Ty<'tcx>>)
+                          -> bool
+{
+    let (param_env, ty) = query.into_parts();
+    let trait_def_id = tcx.require_lang_item(lang_items::SizedTraitLangItem);
+    tcx.infer_ctxt(param_env, Reveal::UserFacing)
+       .enter(|infcx| traits::type_known_to_meet_bound(&infcx, ty, trait_def_id, DUMMY_SP))
+}
+
+fn is_freeze_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                           query: ty::ParameterEnvironmentAnd<'tcx, Ty<'tcx>>)
+                           -> bool
+{
+    let (param_env, ty) = query.into_parts();
+    let trait_def_id = tcx.require_lang_item(lang_items::FreezeTraitLangItem);
+    tcx.infer_ctxt(param_env, Reveal::UserFacing)
+       .enter(|infcx| traits::type_known_to_meet_bound(&infcx, ty, trait_def_id, DUMMY_SP))
+}
+
+pub fn provide(providers: &mut ty::maps::Providers) {
+    *providers = ty::maps::Providers {
+        is_copy_raw,
+        is_sized_raw,
+        is_freeze_raw,
+        ..*providers
+    };
+}
index 8ca699339d36ecedca7a92a3e785b51fffb248bf..340e4f2cfccbcdba96cacd9f1e35f786fcfad6e3 100644 (file)
@@ -504,13 +504,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
     }
 }
 
-impl<'tcx> fmt::Debug for ty::ParameterEnvironment<'tcx> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "ParameterEnvironment({:?})", self.caller_bounds)
-    }
-}
-
-impl<'tcx> fmt::Display for ty::RegionKind {
+impl fmt::Display for ty::RegionKind {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         if verbose() {
             return write!(f, "{:?}", *self);
index 520a90d940b3912d292448891e569244063cefef..0178aa818d6a220db21214a789fbeb1af0cdde9c 100644 (file)
@@ -45,7 +45,7 @@ fn run_pass<'a, 'tcx>(&self,
         }
         let id = src.item_id();
         let param_env = tcx.parameter_environment(tcx.hir.local_def_id(id));
-        let move_data = MoveData::gather_moves(mir, tcx, &param_env);
+        let move_data = MoveData::gather_moves(mir, tcx, param_env);
         let elaborate_patch = {
             let mir = &*mir;
             let env = MoveDataParamEnv {
@@ -196,7 +196,7 @@ fn tcx(&self) -> ty::TyCtxt<'a, 'tcx, 'tcx> {
         self.ctxt.tcx
     }
 
-    fn param_env(&self) -> &'a ty::ParameterEnvironment<'tcx> {
+    fn param_env(&self) -> ty::ParameterEnvironment<'tcx> {
         self.ctxt.param_env()
     }
 
@@ -289,8 +289,9 @@ struct ElaborateDropsCtxt<'a, 'tcx: 'a> {
 
 impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
     fn move_data(&self) -> &'b MoveData<'tcx> { &self.env.move_data }
-    fn param_env(&self) -> &'b ty::ParameterEnvironment<'tcx> {
-        &self.env.param_env
+
+    fn param_env(&self) -> ty::ParameterEnvironment<'tcx> {
+        self.env.param_env
     }
 
     fn initialization_data_at(&self, loc: Location) -> InitializationData {
index ed5e539f245f10fb2280d4821e8bf39f38166796..ebaae1b30d7d1c82e32bd4d0d36fe0f86976c44d 100644 (file)
@@ -191,7 +191,7 @@ pub struct MovePathLookup<'tcx> {
 struct MoveDataBuilder<'a, 'tcx: 'a> {
     mir: &'a Mir<'tcx>,
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    param_env: &'a ParameterEnvironment<'tcx>,
+    param_env: ParameterEnvironment<'tcx>,
     data: MoveData<'tcx>,
 }
 
@@ -203,7 +203,7 @@ pub enum MovePathError {
 impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> {
     fn new(mir: &'a Mir<'tcx>,
            tcx: TyCtxt<'a, 'tcx, 'tcx>,
-           param_env: &'a ParameterEnvironment<'tcx>)
+           param_env: ParameterEnvironment<'tcx>)
            -> Self {
         let mut move_paths = IndexVec::new();
         let mut path_map = IndexVec::new();
@@ -370,7 +370,7 @@ pub fn find(&self, lval: &Lvalue<'tcx>) -> LookupResult {
 impl<'a, 'tcx> MoveData<'tcx> {
     pub fn gather_moves(mir: &Mir<'tcx>,
                         tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                        param_env: &ParameterEnvironment<'tcx>)
+                        param_env: ParameterEnvironment<'tcx>)
                         -> Self {
         gather_moves(mir, tcx, param_env)
     }
@@ -378,7 +378,7 @@ pub fn gather_moves(mir: &Mir<'tcx>,
 
 fn gather_moves<'a, 'tcx>(mir: &Mir<'tcx>,
                           tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                          param_env: &ParameterEnvironment<'tcx>)
+                          param_env: ParameterEnvironment<'tcx>)
                           -> MoveData<'tcx> {
     let mut builder = MoveDataBuilder::new(mir, tcx, param_env);
 
index fbaa60f84450b26f4596bb99728af967f47344ba..003fc2ae9c25c8f24134c04fbdc222078c63ea9a 100644 (file)
@@ -66,7 +66,7 @@ pub fn borrowck_mir(bcx: &mut BorrowckCtxt,
     let mir = &tcx.mir_validated(def_id).borrow();
 
     let param_env = tcx.parameter_environment(def_id);
-    let move_data = MoveData::gather_moves(mir, tcx, &param_env);
+    let move_data = MoveData::gather_moves(mir, tcx, param_env);
     let mdpe = MoveDataParamEnv { move_data: move_data, param_env: param_env };
     let dead_unwinds = IdxSetBuf::new_empty(mir.basic_blocks().len());
     let flow_inits =
@@ -325,7 +325,7 @@ fn on_all_drop_children_bits<'a, 'tcx, F>(
         let ty = lvalue.ty(mir, tcx).to_ty(tcx);
         debug!("on_all_drop_children_bits({:?}, {:?} : {:?})", path, lvalue, ty);
 
-        if ty.needs_drop(tcx, &ctxt.param_env) {
+        if ty.needs_drop(tcx, ctxt.param_env) {
             each_child(child);
         } else {
             debug!("on_all_drop_children_bits - skipping")
@@ -359,7 +359,7 @@ fn drop_flag_effects_for_location<'a, 'tcx, F>(
     where F: FnMut(MovePathIndex, DropFlagState)
 {
     let move_data = &ctxt.move_data;
-    let param_env = &ctxt.param_env;
+    let param_env = ctxt.param_env;
     debug!("drop_flag_effects_for_location({:?})", loc);
 
     // first, move out of the RHS
index a18f91a9ee391408f069981f119d09ead357e618..6e2a13a9a0d7eee6495c00e01ce1a22990bb3ca3 100644 (file)
@@ -52,7 +52,7 @@ fn visit_fn(&mut self, fk: FnKind<'tcx>, fd: &'tcx hir::FnDecl,
             tcx: self.tcx,
             tables: self.tcx.body_tables(b),
             region_maps: &self.tcx.region_maps(def_id),
-            param_env: &self.tcx.parameter_environment(def_id)
+            param_env: self.tcx.parameter_environment(def_id)
         }.visit_body(self.tcx.hir.body(b));
     }
 }
@@ -69,7 +69,7 @@ fn create_e0004<'a>(sess: &'a Session, sp: Span, error_message: String) -> Diagn
 struct MatchVisitor<'a, 'tcx: 'a> {
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     tables: &'a ty::TypeckTables<'tcx>,
-    param_env: &'a ty::ParameterEnvironment<'tcx>,
+    param_env: ty::ParameterEnvironment<'tcx>,
     region_maps: &'a RegionMaps,
 }
 
@@ -518,7 +518,7 @@ fn check_legality_of_move_bindings(cx: &MatchVisitor,
 ///
 /// FIXME: this should be done by borrowck.
 fn check_for_mutation_in_guard(cx: &MatchVisitor, guard: &hir::Expr) {
-    cx.tcx.infer_ctxt((cx.tables, cx.param_env.clone()), Reveal::UserFacing).enter(|infcx| {
+    cx.tcx.infer_ctxt((cx.tables, cx.param_env), Reveal::UserFacing).enter(|infcx| {
         let mut checker = MutationChecker {
             cx: cx,
         };
index 6423d65a4c23fc7175ee598ef365ae7ed90c3ce1..d67f7bc901fe1681a5287b5c1e41e2f767501fcc 100644 (file)
@@ -527,13 +527,11 @@ fn check_item(&mut self, cx: &LateContext, item: &hir::Item) {
         if def.has_dtor(cx.tcx) {
             return;
         }
-        let parameter_environment = cx.tcx.empty_parameter_environment();
-        // FIXME (@jroesch) should probably inver this so that the parameter env still impls this
-        // method
-        if !ty.moves_by_default(cx.tcx, &parameter_environment, item.span) {
+        let param_env = ty::ParameterEnvironment::empty();
+        if !ty.moves_by_default(cx.tcx, param_env, item.span) {
             return;
         }
-        if parameter_environment.can_type_implement_copy(cx.tcx, ty, item.span).is_ok() {
+        if param_env.can_type_implement_copy(cx.tcx, ty, item.span).is_ok() {
             cx.span_lint(MISSING_COPY_IMPLEMENTATIONS,
                          item.span,
                          "type could implement `Copy`; consider adding `impl \
@@ -1258,7 +1256,8 @@ fn get_lints(&self) -> LintArray {
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnionsWithDropFields {
     fn check_item(&mut self, ctx: &LateContext, item: &hir::Item) {
         if let hir::ItemUnion(ref vdata, _) = item.node {
-            let param_env = &ctx.tcx.parameter_environment(ctx.tcx.hir.local_def_id(item.id));
+            let item_def_id = ctx.tcx.hir.local_def_id(item.id);
+            let param_env = ctx.tcx.parameter_environment(item_def_id);
             for field in vdata.fields() {
                 let field_ty = ctx.tcx.type_of(ctx.tcx.hir.local_def_id(field.id));
                 if field_ty.needs_drop(ctx.tcx, param_env) {
index 9ffce18fe150e0c8b52ac54df9164910d5631345..d14d4d6c5310c2de9cec44b990f900135b5f754e 100644 (file)
@@ -168,7 +168,7 @@ pub fn needs_drop(&mut self, ty: Ty<'tcx>) -> bool {
                   type with inference types/regions",
                  ty);
         });
-        ty.needs_drop(self.tcx.global_tcx(), &self.infcx.parameter_environment)
+        ty.needs_drop(self.tcx.global_tcx(), self.infcx.parameter_environment)
     }
 
     pub fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> {
index 6f4480bf6dd16d525bdb54dc8ba02a9f66b2ffa7..e80764b7af2dabb6f0502f5d537f67d2895953ae 100644 (file)
@@ -40,8 +40,6 @@ fn make_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
                        -> &'tcx Mir<'tcx>
 {
     debug!("make_shim({:?})", instance);
-    let did = instance.def_id();
-    let param_env = tcx.parameter_environment(did);
 
     let mut result = match instance {
         ty::InstanceDef::Item(..) =>
@@ -98,7 +96,7 @@ fn make_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
             )
         }
         ty::InstanceDef::DropGlue(def_id, ty) => {
-            build_drop_shim(tcx, &param_env, def_id, ty)
+            build_drop_shim(tcx, def_id, ty)
         }
         ty::InstanceDef::Intrinsic(_) => {
             bug!("creating shims from intrinsics ({:?}) is unsupported", instance)
@@ -144,7 +142,6 @@ fn local_decls_for_sig<'tcx>(sig: &ty::FnSig<'tcx>, span: Span)
 }
 
 fn build_drop_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
-                             param_env: &ty::ParameterEnvironment<'tcx>,
                              def_id: DefId,
                              ty: Option<Ty<'tcx>>)
                              -> Mir<'tcx>
@@ -189,10 +186,12 @@ fn build_drop_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
 
     if let Some(..) = ty {
         let patch = {
+            let param_env = tcx.parameter_environment(def_id);
             let mut elaborator = DropShimElaborator {
                 mir: &mir,
                 patch: MirPatch::new(&mir),
-                tcx, param_env
+                tcx,
+                param_env
             };
             let dropee = Lvalue::Local(Local::new(1+0)).deref();
             let resume_block = elaborator.patch.resume_block();
@@ -218,7 +217,7 @@ pub struct DropShimElaborator<'a, 'tcx: 'a> {
     mir: &'a Mir<'tcx>,
     patch: MirPatch<'tcx>,
     tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
-    param_env: &'a ty::ParameterEnvironment<'tcx>,
+    param_env: ty::ParameterEnvironment<'tcx>,
 }
 
 impl<'a, 'tcx> fmt::Debug for DropShimElaborator<'a, 'tcx> {
@@ -233,7 +232,7 @@ impl<'a, 'tcx> DropElaborator<'a, 'tcx> for DropShimElaborator<'a, 'tcx> {
     fn patch(&mut self) -> &mut MirPatch<'tcx> { &mut self.patch }
     fn mir(&self) -> &'a Mir<'tcx> { self.mir }
     fn tcx(&self) -> ty::TyCtxt<'a, 'tcx, 'tcx> { self.tcx }
-    fn param_env(&self) -> &'a ty::ParameterEnvironment<'tcx> { self.param_env }
+    fn param_env(&self) -> ty::ParameterEnvironment<'tcx> { self.param_env }
 
     fn drop_style(&self, _path: Self::Path, mode: DropFlagMode) -> DropStyle {
         if let DropFlagMode::Shallow = mode {
index e6d62dc6460726365dc560edb3492f74964f5f44..e2c10c1a547d913462374248a08e8a04703d3b0d 100644 (file)
@@ -253,7 +253,7 @@ fn should_inline(&self,
                     // a regular goto.
                     let ty = location.ty(&callee_mir, tcx).subst(tcx, callsite.substs);
                     let ty = ty.to_ty(tcx);
-                    if ty.needs_drop(tcx, &param_env) {
+                    if ty.needs_drop(tcx, param_env) {
                         cost += CALL_PENALTY;
                         if let Some(unwind) = unwind {
                             work_list.push(unwind);
index 72edf68f4034c47121332cf54b57d7647115ed56..9737c6039879536059cfb9f00edc06462adeca28 100644 (file)
@@ -78,7 +78,7 @@ impl<'a, 'tcx> Qualif {
     /// Remove flags which are impossible for the given type.
     fn restrict(&mut self, ty: Ty<'tcx>,
                 tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                param_env: &ty::ParameterEnvironment<'tcx>) {
+                param_env: ty::ParameterEnvironment<'tcx>) {
         if ty.is_freeze(tcx, param_env, DUMMY_SP) {
             *self = *self - Qualif::MUTABLE_INTERIOR;
         }
@@ -193,7 +193,7 @@ fn add(&mut self, qualif: Qualif) {
     /// Add the given type's qualification to self.qualif.
     fn add_type(&mut self, ty: Ty<'tcx>) {
         self.add(Qualif::MUTABLE_INTERIOR | Qualif::NEEDS_DROP);
-        self.qualif.restrict(ty, self.tcx, &self.param_env);
+        self.qualif.restrict(ty, self.tcx, self.param_env);
     }
 
     /// Within the provided closure, self.qualif will start
@@ -544,7 +544,7 @@ fn visit_lvalue(&mut self,
                                            static, use a constant instead");
                             }
                             let ty = lvalue.ty(this.mir, this.tcx).to_ty(this.tcx);
-                            this.qualif.restrict(ty, this.tcx, &this.param_env);
+                            this.qualif.restrict(ty, this.tcx, this.param_env);
                         }
 
                         ProjectionElem::ConstantIndex {..} |
index 9d7c7ec63cfc57afbc32eccfa5dfb5cee46185c2..0573a4e2ee1534065d4d090c9dd557f228af7e8a 100644 (file)
@@ -56,7 +56,7 @@ pub trait DropElaborator<'a, 'tcx: 'a> : fmt::Debug {
     fn patch(&mut self) -> &mut MirPatch<'tcx>;
     fn mir(&self) -> &'a Mir<'tcx>;
     fn tcx(&self) -> ty::TyCtxt<'a, 'tcx, 'tcx>;
-    fn param_env(&self) -> &'a ty::ParameterEnvironment<'tcx>;
+    fn param_env(&self) -> ty::ParameterEnvironment<'tcx>;
 
     fn drop_style(&self, path: Self::Path, mode: DropFlagMode) -> DropStyle;
     fn get_drop_flag(&mut self, path: Self::Path) -> Option<Operand<'tcx>>;
index a0998b1bd1bfb3fd7cd3a54da70b140d3987da0a..9a8ea52a6654b2673ec61a3b2db2713c2a31b4fd 100644 (file)
@@ -38,7 +38,7 @@
 use rustc::middle::mem_categorization as mc;
 use rustc::middle::mem_categorization::Categorization;
 use rustc::mir::transform::MirSource;
-use rustc::ty::{self, Ty, TyCtxt};
+use rustc::ty::{self, ParameterEnvironment, Ty, TyCtxt};
 use rustc::traits::Reveal;
 use rustc::util::common::ErrorReported;
 use rustc::util::nodemap::NodeSet;
@@ -85,11 +85,11 @@ fn check_const_eval(&self, expr: &'gcx hir::Expr) {
 
     // Adds the worst effect out of all the values of one type.
     fn add_type(&mut self, ty: Ty<'gcx>) {
-        if !ty.is_freeze(self.tcx, &self.param_env, DUMMY_SP) {
+        if !ty.is_freeze(self.tcx, self.param_env, DUMMY_SP) {
             self.promotable = false;
         }
 
-        if ty.needs_drop(self.tcx, &self.param_env) {
+        if ty.needs_drop(self.tcx, self.param_env) {
             self.promotable = false;
         }
     }
@@ -466,7 +466,7 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
         in_fn: false,
         promotable: false,
         mut_rvalue_borrows: NodeSet(),
-        param_env: tcx.empty_parameter_environment(),
+        param_env: ParameterEnvironment::empty(),
     }.as_deep_visitor());
     tcx.sess.abort_if_errors();
 }
index c2f2c63790a4c64d04ec9e9ca93ffb175364fc24..7baaf25cf25284efd18829f1e229b528cf57cbbb 100644 (file)
@@ -24,7 +24,7 @@
 use type_::Type;
 use rustc_data_structures::base_n;
 use rustc::ty::subst::Substs;
-use rustc::ty::{self, Ty, TyCtxt};
+use rustc::ty::{self, ParameterEnvironment, Ty, TyCtxt};
 use rustc::ty::layout::{LayoutTyper, TyLayout};
 use session::config::NoDebugInfo;
 use session::Session;
@@ -79,7 +79,6 @@ pub fn extend(&mut self, stats: Stats) {
 pub struct SharedCrateContext<'a, 'tcx: 'a> {
     exported_symbols: NodeSet,
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    empty_param_env: ty::ParameterEnvironment<'tcx>,
     check_overflow: bool,
 
     use_dll_storage_attrs: bool,
@@ -315,7 +314,6 @@ pub fn new(tcx: TyCtxt<'b, 'tcx, 'tcx>,
 
         SharedCrateContext {
             exported_symbols: exported_symbols,
-            empty_param_env: tcx.empty_parameter_environment(),
             tcx: tcx,
             check_overflow: check_overflow,
             use_dll_storage_attrs: use_dll_storage_attrs,
@@ -323,15 +321,15 @@ pub fn new(tcx: TyCtxt<'b, 'tcx, 'tcx>,
     }
 
     pub fn type_needs_drop(&self, ty: Ty<'tcx>) -> bool {
-        ty.needs_drop(self.tcx, &self.empty_param_env)
+        ty.needs_drop(self.tcx, ParameterEnvironment::empty())
     }
 
     pub fn type_is_sized(&self, ty: Ty<'tcx>) -> bool {
-        ty.is_sized(self.tcx, &self.empty_param_env, DUMMY_SP)
+        ty.is_sized(self.tcx, ParameterEnvironment::empty(), DUMMY_SP)
     }
 
     pub fn type_is_freeze(&self, ty: Ty<'tcx>) -> bool {
-        ty.is_freeze(self.tcx, &self.empty_param_env, DUMMY_SP)
+        ty.is_freeze(self.tcx, ParameterEnvironment::empty(), DUMMY_SP)
     }
 
     pub fn exported_symbols<'a>(&'a self) -> &'a NodeSet {
index d9f77e8f04f1ccbfa595b19195f286a8a942b34a..320884b82f4c36ee45126e5919e98060bdadb49b 100644 (file)
@@ -165,10 +165,6 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     // Finally we register each of these predicates as an obligation in
     // a fresh FulfillmentCtxt, and invoke select_all_or_error.
 
-    // Create a parameter environment that represents the implementation's
-    // method.
-    let impl_param_env = tcx.parameter_environment(impl_m.def_id);
-
     // Create mapping from impl to skolemized.
     let impl_to_skol_substs = Substs::identity_for_item(tcx, impl_m.def_id);
 
@@ -216,14 +212,13 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     // The key step here is to update the caller_bounds's predicates to be
     // the new hybrid bounds we computed.
     let normalize_cause = traits::ObligationCause::misc(impl_m_span, impl_m_node_id);
-    let trait_param_env = impl_param_env.with_caller_bounds(
-        tcx.intern_predicates(&hybrid_preds.predicates));
-    let trait_param_env = traits::normalize_param_env_or_error(tcx,
-                                                               impl_m.def_id,
-                                                               trait_param_env,
-                                                               normalize_cause.clone());
-
-    tcx.infer_ctxt(trait_param_env, Reveal::UserFacing).enter(|infcx| {
+    let param_env = ty::ParameterEnvironment::new(tcx.intern_predicates(&hybrid_preds.predicates));
+    let param_env = traits::normalize_param_env_or_error(tcx,
+                                                         impl_m.def_id,
+                                                         param_env,
+                                                         normalize_cause.clone());
+
+    tcx.infer_ctxt(param_env, Reveal::UserFacing).enter(|infcx| {
         let inh = Inherited::new(infcx, impl_m.def_id);
         let infcx = &inh.infcx;