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
// 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),
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};
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,
}
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>
{
return value;
}
- self.infer_ctxt(env.clone(), Reveal::All).enter(|infcx| {
+ self.infer_ctxt(env, Reveal::All).enter(|infcx| {
value.trans_normalize(&infcx)
})
}
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,
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(
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))
})
}
self.infcx.tcx
}
- pub fn param_env(&self) -> &'cx ty::ParameterEnvironment<'gcx> {
+ pub fn param_env(&self) -> ty::ParameterEnvironment<'gcx> {
self.infcx.param_env()
}
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);
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, ¶m_env, DUMMY_SP);
+ .is_sized(tcx, param_env, DUMMY_SP);
if !always_sized { StructKind::MaybeUnsizedUnivariant }
else { StructKind::AlwaysSizedUnivariant }
};
// 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;
}
}
+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;
}
}
}
+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 `{}`",
-> 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> {
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)
+}
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;
// 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,
}
/// 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)
}
}
}
}
- /// 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> {
//
// 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)
pub fn provide(providers: &mut ty::maps::Providers) {
+ util::provide(providers);
*providers = ty::maps::Providers {
associated_item,
associated_item_def_ids,
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;
use syntax::attr::{self, SignedInt, UnsignedInt};
use syntax_pos::{Span, DUMMY_SP};
-use hir;
-
type Disr = ConstInt;
pub trait IntTypeExt {
}
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> {
}
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),
- ¶m_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),
- ¶m_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),
- ¶m_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
/// (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);
}
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) {
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());
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
+ };
+}
}
}
-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);
}
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, ¶m_env);
+ let move_data = MoveData::gather_moves(mir, tcx, param_env);
let elaborate_patch = {
let mir = &*mir;
let env = MoveDataParamEnv {
self.ctxt.tcx
}
- fn param_env(&self) -> &'a ty::ParameterEnvironment<'tcx> {
+ fn param_env(&self) -> ty::ParameterEnvironment<'tcx> {
self.ctxt.param_env()
}
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 {
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>,
}
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();
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)
}
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);
let mir = &tcx.mir_validated(def_id).borrow();
let param_env = tcx.parameter_environment(def_id);
- let move_data = MoveData::gather_moves(mir, tcx, ¶m_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 =
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")
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
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));
}
}
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,
}
///
/// 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,
};
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, ¶meter_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 \
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) {
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> {
-> &'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(..) =>
)
}
ty::InstanceDef::DropGlue(def_id, ty) => {
- build_drop_shim(tcx, ¶m_env, def_id, ty)
+ build_drop_shim(tcx, def_id, ty)
}
ty::InstanceDef::Intrinsic(_) => {
bug!("creating shims from intrinsics ({:?}) is unsupported", instance)
}
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>
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();
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> {
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 {
// 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, ¶m_env) {
+ if ty.needs_drop(tcx, param_env) {
cost += CALL_PENALTY;
if let Some(unwind) = unwind {
work_list.push(unwind);
/// 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;
}
/// 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
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 {..} |
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>>;
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;
// 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;
}
}
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();
}
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;
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,
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,
}
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 {
// 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);
// 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;