diff --git a/src/librustc/infer/combine.rs b/src/librustc/infer/combine.rs index e20b53455f49c..4a9b68f24371d 100644 --- a/src/librustc/infer/combine.rs +++ b/src/librustc/infer/combine.rs @@ -340,6 +340,7 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> { ambient_variance, needs_wf: false, root_ty: ty, + param_env: self.param_env, }; let ty = match generalize.relate(&ty, &ty) { @@ -379,6 +380,8 @@ struct Generalizer<'cx, 'tcx> { /// The root type that we are generalizing. Used when reporting cycles. root_ty: Ty<'tcx>, + + param_env: ty::ParamEnv<'tcx>, } /// Result from a generalization operation. This includes @@ -419,6 +422,7 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> { fn tcx(&self) -> TyCtxt<'tcx> { self.infcx.tcx } + fn param_env(&self) -> ty::ParamEnv<'tcx> { self.param_env } fn tag(&self) -> &'static str { "Generalizer" diff --git a/src/librustc/infer/equate.rs b/src/librustc/infer/equate.rs index 5eebe9e78d353..5dfa0d29daf1b 100644 --- a/src/librustc/infer/equate.rs +++ b/src/librustc/infer/equate.rs @@ -30,6 +30,8 @@ impl TypeRelation<'tcx> for Equate<'combine, 'infcx, 'tcx> { fn tcx(&self) -> TyCtxt<'tcx> { self.fields.tcx() } + fn param_env(&self) -> ty::ParamEnv<'tcx> { self.fields.param_env } + fn a_is_expected(&self) -> bool { self.a_is_expected } fn relate_item_substs(&mut self, diff --git a/src/librustc/infer/glb.rs b/src/librustc/infer/glb.rs index 550213167470d..2cef521176269 100644 --- a/src/librustc/infer/glb.rs +++ b/src/librustc/infer/glb.rs @@ -27,6 +27,8 @@ impl TypeRelation<'tcx> for Glb<'combine, 'infcx, 'tcx> { fn tcx(&self) -> TyCtxt<'tcx> { self.fields.tcx() } + fn param_env(&self) -> ty::ParamEnv<'tcx> { self.fields.param_env } + fn a_is_expected(&self) -> bool { self.a_is_expected } fn relate_with_variance>(&mut self, diff --git a/src/librustc/infer/lub.rs b/src/librustc/infer/lub.rs index 156288b9e6afd..e20372f151371 100644 --- a/src/librustc/infer/lub.rs +++ b/src/librustc/infer/lub.rs @@ -27,6 +27,8 @@ impl TypeRelation<'tcx> for Lub<'combine, 'infcx, 'tcx> { fn tcx(&self) -> TyCtxt<'tcx> { self.fields.tcx() } + fn param_env(&self) -> ty::ParamEnv<'tcx> { self.fields.param_env } + fn a_is_expected(&self) -> bool { self.a_is_expected } fn relate_with_variance>(&mut self, diff --git a/src/librustc/infer/nll_relate/mod.rs b/src/librustc/infer/nll_relate/mod.rs index a0621af053783..5d521def65b0b 100644 --- a/src/librustc/infer/nll_relate/mod.rs +++ b/src/librustc/infer/nll_relate/mod.rs @@ -502,6 +502,9 @@ where self.infcx.tcx } + // FIXME(oli-obk): not sure how to get the correct ParamEnv + fn param_env(&self) -> ty::ParamEnv<'tcx> { ty::ParamEnv::empty() } + fn tag(&self) -> &'static str { "nll::subtype" } @@ -831,6 +834,9 @@ where self.infcx.tcx } + // FIXME(oli-obk): not sure how to get the correct ParamEnv + fn param_env(&self) -> ty::ParamEnv<'tcx> { ty::ParamEnv::empty() } + fn tag(&self) -> &'static str { "nll::generalizer" } diff --git a/src/librustc/infer/outlives/env.rs b/src/librustc/infer/outlives/env.rs index d555886128598..e6155454d46f1 100644 --- a/src/librustc/infer/outlives/env.rs +++ b/src/librustc/infer/outlives/env.rs @@ -27,7 +27,7 @@ use crate::ty::{self, Ty}; /// interested in the `OutlivesEnvironment`. -nmatsakis #[derive(Clone)] pub struct OutlivesEnvironment<'tcx> { - param_env: ty::ParamEnv<'tcx>, + pub param_env: ty::ParamEnv<'tcx>, free_region_map: FreeRegionMap<'tcx>, // Contains, for each body B that we are checking (that is, the fn diff --git a/src/librustc/infer/sub.rs b/src/librustc/infer/sub.rs index 1452a6dee5bc1..cd1d206b5fca1 100644 --- a/src/librustc/infer/sub.rs +++ b/src/librustc/infer/sub.rs @@ -35,6 +35,9 @@ impl<'combine, 'infcx, 'tcx> Sub<'combine, 'infcx, 'tcx> { impl TypeRelation<'tcx> for Sub<'combine, 'infcx, 'tcx> { fn tag(&self) -> &'static str { "Sub" } fn tcx(&self) -> TyCtxt<'tcx> { self.fields.infcx.tcx } + + fn param_env(&self) -> ty::ParamEnv<'tcx> { self.fields.param_env } + fn a_is_expected(&self) -> bool { self.a_is_expected } fn with_cause(&mut self, cause: Cause, f: F) -> R diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index 2448db032b965..a274d7bbee5f7 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -277,6 +277,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { ) -> Self { ExprUseVisitor { mc: mc::MemCategorizationContext::new(tcx, + param_env, body_owner, region_scope_tree, tables, @@ -299,6 +300,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { ExprUseVisitor { mc: mc::MemCategorizationContext::with_infer( infcx, + param_env, body_owner, region_scope_tree, tables, diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 524d5ddf92900..77d6f3932445b 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -214,6 +214,7 @@ impl HirNode for hir::Pat { #[derive(Clone)] pub struct MemCategorizationContext<'a, 'tcx> { pub tcx: TyCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, pub body_owner: DefId, pub upvars: Option<&'tcx FxIndexMap>, pub region_scope_tree: &'a region::ScopeTree, @@ -330,6 +331,7 @@ impl MutabilityCategory { impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { pub fn new( tcx: TyCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, body_owner: DefId, region_scope_tree: &'a region::ScopeTree, tables: &'a ty::TypeckTables<'tcx>, @@ -342,7 +344,8 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { region_scope_tree, tables, rvalue_promotable_map, - infcx: None + infcx: None, + param_env, } } } @@ -359,6 +362,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { /// known, the results around upvar accesses may be incorrect. pub fn with_infer( infcx: &'a InferCtxt<'a, 'tcx>, + param_env: ty::ParamEnv<'tcx>, body_owner: DefId, region_scope_tree: &'a region::ScopeTree, tables: &'a ty::TypeckTables<'tcx>, @@ -379,6 +383,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { tables, rvalue_promotable_map, infcx: Some(infcx), + param_env, } } @@ -896,7 +901,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { // Always promote `[T; 0]` (even when e.g., borrowed mutably). let promotable = match expr_ty.sty { - ty::Array(_, len) if len.assert_usize(self.tcx) == Some(0) => true, + ty::Array(_, len) if len.try_eval_usize(self.tcx, self.param_env) == Some(0) => true, _ => promotable, }; diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs index e2f5d192281a7..f8889380b2abf 100644 --- a/src/librustc/mir/tcx.rs +++ b/src/librustc/mir/tcx.rs @@ -57,7 +57,7 @@ impl<'tcx> PlaceTy<'tcx> { /// `PlaceElem`, where we can just use the `Ty` that is already /// stored inline on field projection elems. pub fn projection_ty(self, tcx: TyCtxt<'tcx>, elem: &PlaceElem<'tcx>) -> PlaceTy<'tcx> { - self.projection_ty_core(tcx, elem, |_, _, ty| ty) + self.projection_ty_core(tcx, ty::ParamEnv::empty(), elem, |_, _, ty| ty) } /// `place_ty.projection_ty_core(tcx, elem, |...| { ... })` @@ -68,6 +68,7 @@ impl<'tcx> PlaceTy<'tcx> { pub fn projection_ty_core( self, tcx: TyCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, elem: &ProjectionElem, mut handle_field: impl FnMut(&Self, &Field, &T) -> Ty<'tcx>, ) -> PlaceTy<'tcx> @@ -90,7 +91,7 @@ impl<'tcx> PlaceTy<'tcx> { ProjectionElem::Subslice { from, to } => { PlaceTy::from_ty(match self.ty.sty { ty::Array(inner, size) => { - let size = size.unwrap_usize(tcx); + let size = size.eval_usize(tcx, param_env); let len = size - (from as u64) - (to as u64); tcx.mk_array(inner, len) } diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 14a288f5af1a0..83bd5c56040e1 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -417,7 +417,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { Some(format!("[{}]", self.tcx.type_of(def.did).to_string())), )); let tcx = self.tcx; - if let Some(len) = len.assert_usize(tcx) { + if let Some(len) = len.try_eval_usize(tcx, ty::ParamEnv::empty()) { flags.push(( sym::_Self, Some(format!("[{}; {}]", self.tcx.type_of(def.did).to_string(), len)), diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 2486f29ab0f22..da582c015e4ea 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -1082,7 +1082,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } if unbound_input_types && stack.iter().skip(1).any(|prev| { stack.obligation.param_env == prev.obligation.param_env - && self.match_fresh_trait_refs(&stack.fresh_trait_ref, &prev.fresh_trait_ref) + && self.match_fresh_trait_refs( + &stack.fresh_trait_ref, &prev.fresh_trait_ref, prev.obligation.param_env) }) { debug!( "evaluate_stack({:?}) --> unbound argument, recursive --> giving up", @@ -3798,8 +3799,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &self, previous: &ty::PolyTraitRef<'tcx>, current: &ty::PolyTraitRef<'tcx>, + param_env: ty::ParamEnv<'tcx>, ) -> bool { - let mut matcher = ty::_match::Match::new(self.tcx()); + let mut matcher = ty::_match::Match::new(self.tcx(), param_env); matcher.relate(previous, current).is_ok() } diff --git a/src/librustc/ty/_match.rs b/src/librustc/ty/_match.rs index 6e10dc03a2869..f800a70e0becf 100644 --- a/src/librustc/ty/_match.rs +++ b/src/librustc/ty/_match.rs @@ -21,17 +21,19 @@ use crate::mir::interpret::ConstValue; /// affects any type variables or unification state. pub struct Match<'tcx> { tcx: TyCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, } impl Match<'tcx> { - pub fn new(tcx: TyCtxt<'tcx>) -> Match<'tcx> { - Match { tcx } + pub fn new(tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Match<'tcx> { + Match { tcx, param_env } } } impl TypeRelation<'tcx> for Match<'tcx> { fn tag(&self) -> &'static str { "Match" } fn tcx(&self) -> TyCtxt<'tcx> { self.tcx } + fn param_env(&self) -> ty::ParamEnv<'tcx> { self.param_env } fn a_is_expected(&self) -> bool { true } // irrelevant fn relate_with_variance>(&mut self, diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs index b8bdde4a78738..4a72794b61a64 100644 --- a/src/librustc/ty/error.rs +++ b/src/librustc/ty/error.rs @@ -194,7 +194,7 @@ impl<'tcx> ty::TyS<'tcx> { ty::Foreign(def_id) => format!("extern type `{}`", tcx.def_path_str(def_id)).into(), ty::Array(_, n) => { let n = tcx.lift_to_global(&n).unwrap(); - match n.assert_usize(tcx) { + match n.try_eval_usize(tcx, ty::ParamEnv::empty()) { Some(n) => format!("array of {} elements", n).into(), None => "array".into(), } diff --git a/src/librustc/ty/inhabitedness/mod.rs b/src/librustc/ty/inhabitedness/mod.rs index 0d96e5ea625da..2b3291656653f 100644 --- a/src/librustc/ty/inhabitedness/mod.rs +++ b/src/librustc/ty/inhabitedness/mod.rs @@ -3,6 +3,7 @@ use crate::ty::{AdtDef, VariantDef, FieldDef, Ty, TyS}; use crate::ty::{DefId, SubstsRef}; use crate::ty::{AdtKind, Visibility}; use crate::ty::TyKind::*; +use crate::ty; pub use self::def_id_forest::DefIdForest; @@ -190,7 +191,7 @@ impl<'tcx> TyS<'tcx> { })) } - Array(ty, len) => match len.assert_usize(tcx) { + Array(ty, len) => match len.try_eval_usize(tcx, ty::ParamEnv::empty()) { // If the array is definitely non-empty, it's uninhabited if // the type of its elements is uninhabited. Some(n) if n != 0 => ty.uninhabited_from(tcx), diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index e0e70f41abe6a..a66a4ac66f3f5 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -594,7 +594,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { } } - let count = count.assert_usize(tcx).ok_or(LayoutError::Unknown(ty))?; + let count = count.try_eval_usize(tcx, param_env).ok_or(LayoutError::Unknown(ty))?; let element = self.layout_of(element)?; let size = element.size.checked_mul(count, dl) .ok_or(LayoutError::SizeOverflow(ty))?; diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 8e170578227c0..5fec95e2a3b34 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -2357,7 +2357,7 @@ impl<'tcx> AdtDef { #[inline] pub fn eval_explicit_discr(&self, tcx: TyCtxt<'tcx>, expr_did: DefId) -> Option> { - let param_env = ParamEnv::empty(); + let param_env = tcx.param_env(expr_did); let repr_type = self.repr.discr_type(); let substs = InternalSubsts::identity_for_item(tcx.global_tcx(), expr_did); let instance = ty::Instance::new(expr_did, substs); @@ -2368,7 +2368,7 @@ impl<'tcx> AdtDef { match tcx.const_eval(param_env.and(cid)) { Ok(val) => { // FIXME: Find the right type and use it instead of `val.ty` here - if let Some(b) = val.assert_bits(tcx.global_tcx(), param_env.and(val.ty)) { + if let Some(b) = val.try_eval_bits(tcx.global_tcx(), param_env, val.ty) { trace!("discriminants: {} ({:?})", b, repr_type); Some(Discr { val: b, diff --git a/src/librustc/ty/print/obsolete.rs b/src/librustc/ty/print/obsolete.rs index c12402a57cc3c..b68e6a744872f 100644 --- a/src/librustc/ty/print/obsolete.rs +++ b/src/librustc/ty/print/obsolete.rs @@ -89,7 +89,8 @@ impl DefPathBasedNames<'tcx> { ty::Array(inner_type, len) => { output.push('['); self.push_type_name(inner_type, output, debug); - write!(output, "; {}", len.unwrap_usize(self.tcx)).unwrap(); + let len = len.eval_usize(self.tcx, ty::ParamEnv::reveal_all()); + write!(output, "; {}", len).unwrap(); output.push(']'); } ty::Slice(inner_type) => { diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index e889f2edef2bb..017f67463c31b 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -696,7 +696,12 @@ pub trait PrettyPrinter<'tcx>: }, ty::Array(ty, sz) => { p!(write("["), print(ty), write("; ")); - if let Some(n) = sz.assert_usize(self.tcx()) { + if let ConstValue::Unevaluated(..) = sz.val { + // do not try to evalute unevaluated constants. If we are const evaluating an + // array length anon const, rustc will (with debug assertions) print the + // constant's path. Which will end up here again. + p!(write("_")); + } else if let Some(n) = sz.try_eval_usize(self.tcx(), ty::ParamEnv::empty()) { p!(write("{}", n)); } else { p!(write("_")); @@ -915,7 +920,7 @@ pub trait PrettyPrinter<'tcx>: if let ty::Ref(_, ref_ty, _) = ct.ty.sty { let byte_str = match (ct.val, &ref_ty.sty) { (ConstValue::Scalar(Scalar::Ptr(ptr)), ty::Array(t, n)) if *t == u8 => { - let n = n.unwrap_usize(self.tcx()); + let n = n.eval_usize(self.tcx(), ty::ParamEnv::empty()); Some(self.tcx() .alloc_map.lock() .unwrap_memory(ptr.alloc_id) diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs index ca54f63b83afe..945e3e158eafb 100644 --- a/src/librustc/ty/relate.rs +++ b/src/librustc/ty/relate.rs @@ -25,6 +25,8 @@ pub enum Cause { pub trait TypeRelation<'tcx>: Sized { fn tcx(&self) -> TyCtxt<'tcx>; + fn param_env(&self) -> ty::ParamEnv<'tcx>; + /// Returns a static string we can use for printouts. fn tag(&self) -> &'static str; @@ -466,7 +468,9 @@ pub fn super_relate_tys>( Err(err) => { // Check whether the lengths are both concrete/known values, // but are unequal, for better diagnostics. - match (sz_a.assert_usize(tcx), sz_b.assert_usize(tcx)) { + let sz_a = sz_a.try_eval_usize(tcx, relation.param_env()); + let sz_b = sz_b.try_eval_usize(tcx, relation.param_env()); + match (sz_a, sz_b) { (Some(sz_a_val), Some(sz_b_val)) => { Err(TypeError::FixedArraySize( expected_found(relation, &sz_a_val, &sz_b_val) diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 2b14558de6916..769b6592b6fa8 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -15,7 +15,7 @@ use crate::ty::{self, AdtDef, Discr, DefIdTree, TypeFlags, Ty, TyCtxt, TypeFolda use crate::ty::{List, TyS, ParamEnvAnd, ParamEnv}; use crate::ty::layout::VariantIdx; use crate::util::captures::Captures; -use crate::mir::interpret::{Scalar, Pointer}; +use crate::mir::interpret::{Scalar, GlobalId}; use smallvec::SmallVec; use std::borrow::Cow; @@ -1726,7 +1726,7 @@ impl<'tcx> TyS<'tcx> { ty.expect_ty().conservative_is_privately_uninhabited(tcx) }), ty::Array(ty, len) => { - match len.assert_usize(tcx) { + match len.try_eval_usize(tcx, ParamEnv::empty()) { // If the array is definitely non-empty, it's uninhabited if // the type of its elements is uninhabited. Some(n) if n != 0 => ty.conservative_is_privately_uninhabited(tcx), @@ -2291,29 +2291,38 @@ impl<'tcx> Const<'tcx> { } #[inline] - pub fn to_bits(&self, tcx: TyCtxt<'tcx>, ty: ParamEnvAnd<'tcx, Ty<'tcx>>) -> Option { - if self.ty != ty.value { - return None; + pub fn try_eval_bits( + &self, + tcx: TyCtxt<'tcx>, + param_env: ParamEnv<'tcx>, + ty: Ty<'tcx>, + ) -> Option { + assert_eq!(self.ty, ty); + // if `ty` does not depend on generic parameters, use an empty param_env + let size = tcx.layout_of(param_env.with_reveal_all().and(ty)).ok()?.size; + match self.val { + // FIXME(const_generics): this doesn't work right now, + // because it tries to relate an `Infer` to a `Param`. + ConstValue::Unevaluated(did, substs) => { + // if `substs` has no unresolved components, use and empty param_env + let (param_env, substs) = param_env.with_reveal_all().and(substs).into_parts(); + // try to resolve e.g. associated constants to their definition on an impl + let instance = ty::Instance::resolve(tcx, param_env, did, substs)?; + let gid = GlobalId { + instance, + promoted: None, + }; + let evaluated = tcx.const_eval(param_env.and(gid)).ok()?; + evaluated.val.try_to_bits(size) + }, + // otherwise just extract a `ConstValue`'s bits if possible + _ => self.val.try_to_bits(size), } - let size = tcx.layout_of(ty).ok()?.size; - self.val.try_to_bits(size) - } - - #[inline] - pub fn to_ptr(&self) -> Option { - self.val.try_to_ptr() - } - - #[inline] - pub fn assert_bits(&self, tcx: TyCtxt<'tcx>, ty: ParamEnvAnd<'tcx, Ty<'tcx>>) -> Option { - assert_eq!(self.ty, ty.value); - let size = tcx.layout_of(ty).ok()?.size; - self.val.try_to_bits(size) } #[inline] - pub fn assert_bool(&self, tcx: TyCtxt<'tcx>) -> Option { - self.assert_bits(tcx, ParamEnv::empty().and(tcx.types.bool)).and_then(|v| match v { + pub fn try_eval_bool(&self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Option { + self.try_eval_bits(tcx, param_env, tcx.types.bool).and_then(|v| match v { 0 => Some(false), 1 => Some(true), _ => None, @@ -2321,20 +2330,19 @@ impl<'tcx> Const<'tcx> { } #[inline] - pub fn assert_usize(&self, tcx: TyCtxt<'tcx>) -> Option { - self.assert_bits(tcx, ParamEnv::empty().and(tcx.types.usize)).map(|v| v as u64) + pub fn try_eval_usize(&self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Option { + self.try_eval_bits(tcx, param_env, tcx.types.usize).map(|v| v as u64) } #[inline] - pub fn unwrap_bits(&self, tcx: TyCtxt<'tcx>, ty: ParamEnvAnd<'tcx, Ty<'tcx>>) -> u128 { - self.assert_bits(tcx, ty).unwrap_or_else(|| - bug!("expected bits of {}, got {:#?}", ty.value, self)) + pub fn eval_bits(&self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ty: Ty<'tcx>) -> u128 { + self.try_eval_bits(tcx, param_env, ty).unwrap_or_else(|| + bug!("expected bits of {:#?}, got {:#?}", ty, self)) } #[inline] - pub fn unwrap_usize(&self, tcx: TyCtxt<'tcx>) -> u64 { - self.assert_usize(tcx).unwrap_or_else(|| - bug!("expected constant usize, got {:#?}", self)) + pub fn eval_usize(&self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> u64 { + self.eval_bits(tcx, param_env, tcx.types.usize) as u64 } } diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs index f0bdb0018efe7..3b7aee84862ce 100644 --- a/src/librustc_codegen_llvm/debuginfo/metadata.rs +++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs @@ -341,7 +341,7 @@ fn fixed_vec_metadata( let (size, align) = cx.size_and_align_of(array_or_slice_type); let upper_bound = match array_or_slice_type.sty { - ty::Array(_, len) => len.unwrap_usize(cx.tcx) as c_longlong, + ty::Array(_, len) => len.eval_usize(cx.tcx, ty::ParamEnv::reveal_all()) as c_longlong, _ => -1 }; diff --git a/src/librustc_codegen_ssa/base.rs b/src/librustc_codegen_ssa/base.rs index fc04976f511b3..cdc54bb179ebf 100644 --- a/src/librustc_codegen_ssa/base.rs +++ b/src/librustc_codegen_ssa/base.rs @@ -132,7 +132,7 @@ pub fn unsized_info<'tcx, Cx: CodegenMethods<'tcx>>( cx.tcx().struct_lockstep_tails_erasing_lifetimes(source, target, cx.param_env()); match (&source.sty, &target.sty) { (&ty::Array(_, len), &ty::Slice(_)) => { - cx.const_usize(len.unwrap_usize(cx.tcx())) + cx.const_usize(len.eval_usize(cx.tcx(), ty::ParamEnv::reveal_all())) } (&ty::Dynamic(..), &ty::Dynamic(..)) => { // For now, upcasts are limited to changes in marker diff --git a/src/librustc_codegen_ssa/debuginfo/type_names.rs b/src/librustc_codegen_ssa/debuginfo/type_names.rs index 8f0bb6ee19837..ea39913d4b91b 100644 --- a/src/librustc_codegen_ssa/debuginfo/type_names.rs +++ b/src/librustc_codegen_ssa/debuginfo/type_names.rs @@ -89,7 +89,7 @@ pub fn push_debuginfo_type_name<'tcx>( ty::Array(inner_type, len) => { output.push('['); push_debuginfo_type_name(tcx, inner_type, true, output, visited); - output.push_str(&format!("; {}", len.unwrap_usize(tcx))); + output.push_str(&format!("; {}", len.eval_usize(tcx, ty::ParamEnv::reveal_all()))); output.push(']'); }, ty::Slice(inner_type) => { diff --git a/src/librustc_codegen_ssa/mir/constant.rs b/src/librustc_codegen_ssa/mir/constant.rs index d6951b923bf7d..216e5a4645a46 100644 --- a/src/librustc_codegen_ssa/mir/constant.rs +++ b/src/librustc_codegen_ssa/mir/constant.rs @@ -41,7 +41,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { .map(|c| { let field_ty = c.ty.builtin_index().unwrap(); let fields = match c.ty.sty { - ty::Array(_, n) => n.unwrap_usize(bx.tcx()), + ty::Array(_, n) => n.eval_usize(bx.tcx(), ty::ParamEnv::reveal_all()), _ => bug!("invalid simd shuffle type: {}", c.ty), }; let values: Vec<_> = (0..fields).map(|field| { diff --git a/src/librustc_codegen_ssa/mir/rvalue.rs b/src/librustc_codegen_ssa/mir/rvalue.rs index 202cf147f1fcb..21cedb7a9b394 100644 --- a/src/librustc_codegen_ssa/mir/rvalue.rs +++ b/src/librustc_codegen_ssa/mir/rvalue.rs @@ -521,7 +521,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } = *place { if let LocalRef::Operand(Some(op)) = self.locals[index] { if let ty::Array(_, n) = op.layout.ty.sty { - let n = n.unwrap_usize(bx.cx().tcx()); + let n = n.eval_usize(bx.cx().tcx(), ty::ParamEnv::reveal_all()); return bx.cx().const_usize(n); } } diff --git a/src/librustc_codegen_utils/symbol_names/v0.rs b/src/librustc_codegen_utils/symbol_names/v0.rs index 8a54fb6bbc4ca..47601da8b7b23 100644 --- a/src/librustc_codegen_utils/symbol_names/v0.rs +++ b/src/librustc_codegen_utils/symbol_names/v0.rs @@ -512,7 +512,7 @@ impl Printer<'tcx> for SymbolMangler<'tcx> { } self = ct.ty.print(self)?; - if let Some(bits) = ct.assert_bits(self.tcx, ty::ParamEnv::empty().and(ct.ty)) { + if let Some(bits) = ct.try_eval_bits(self.tcx, ty::ParamEnv::reveal_all(), ct.ty) { let _ = write!(self.out, "{:x}_", bits); } else { // NOTE(eddyb) despite having the path, we need to diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index 4cccaa942b742..23b5889202874 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -208,7 +208,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults { } has_emitted } - ty::Array(ty, len) => match len.assert_usize(cx.tcx) { + ty::Array(ty, len) => match len.try_eval_usize(cx.tcx, cx.param_env) { // If the array is definitely non-empty, we can do `#[must_use]` checking. Some(n) if n != 0 => { let descr_pre = &format!( diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 9f22d7c51df6e..340ca5747d843 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -206,7 +206,7 @@ fn do_mir_borrowck<'a, 'tcx>( def_id, &attributes, &dead_unwinds, - Borrows::new(tcx, body, regioncx.clone(), &borrow_set), + Borrows::new(tcx, body, param_env, regioncx.clone(), &borrow_set), |rs, i| DebugFormatted::new(&rs.location(i)), )); let flow_uninits = FlowAtLocation::new(do_dataflow( @@ -242,6 +242,7 @@ fn do_mir_borrowck<'a, 'tcx>( infcx, body, mir_def_id: def_id, + param_env, move_data: &mdpe.move_data, location_table, movable_generator, @@ -424,6 +425,7 @@ crate struct MirBorrowckCtxt<'cx, 'tcx> { crate infcx: &'cx InferCtxt<'cx, 'tcx>, body: &'cx Body<'tcx>, mir_def_id: DefId, + param_env: ty::ParamEnv<'tcx>, move_data: &'cx MoveData<'tcx>, /// Map from MIR `Location` to `LocationIndex`; created @@ -1004,11 +1006,13 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let mut error_reported = false; let tcx = self.infcx.tcx; let body = self.body; + let param_env = self.param_env; let location_table = self.location_table.start_index(location); let borrow_set = self.borrow_set.clone(); each_borrow_involving_path( self, tcx, + param_env, body, location, (sd, place_span.0), @@ -1480,6 +1484,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { if places_conflict::borrow_conflicts_with_place( self.infcx.tcx, + self.param_env, self.body, place, borrow.kind, diff --git a/src/librustc_mir/borrow_check/nll/constraint_generation.rs b/src/librustc_mir/borrow_check/nll/constraint_generation.rs index 95c3299693b68..5c230913a0da3 100644 --- a/src/librustc_mir/borrow_check/nll/constraint_generation.rs +++ b/src/librustc_mir/borrow_check/nll/constraint_generation.rs @@ -18,6 +18,7 @@ use rustc::ty::subst::SubstsRef; pub(super) fn generate_constraints<'cx, 'tcx>( infcx: &InferCtxt<'cx, 'tcx>, + param_env: ty::ParamEnv<'tcx>, liveness_constraints: &mut LivenessValues, all_facts: &mut Option, location_table: &LocationTable, @@ -31,6 +32,7 @@ pub(super) fn generate_constraints<'cx, 'tcx>( location_table, all_facts, body, + param_env, }; for (bb, data) in body.basic_blocks().iter_enumerated() { @@ -41,6 +43,7 @@ pub(super) fn generate_constraints<'cx, 'tcx>( /// 'cg = the duration of the constraint generation process itself. struct ConstraintGeneration<'cg, 'cx, 'tcx> { infcx: &'cg InferCtxt<'cx, 'tcx>, + param_env: ty::ParamEnv<'tcx>, all_facts: &'cg mut Option, location_table: &'cg LocationTable, liveness_constraints: &'cg mut LivenessValues, @@ -271,6 +274,7 @@ impl<'cx, 'cg, 'tcx> ConstraintGeneration<'cx, 'cg, 'tcx> { for &borrow_index in borrow_indices { let places_conflict = places_conflict::places_conflict( self.infcx.tcx, + self.param_env, self.body, &self.borrow_set.borrows[borrow_index].borrowed_place, place, diff --git a/src/librustc_mir/borrow_check/nll/invalidation.rs b/src/librustc_mir/borrow_check/nll/invalidation.rs index 631a81421131c..71106af767064 100644 --- a/src/librustc_mir/borrow_check/nll/invalidation.rs +++ b/src/librustc_mir/borrow_check/nll/invalidation.rs @@ -9,7 +9,7 @@ use crate::borrow_check::{ReadKind, WriteKind}; use crate::borrow_check::nll::facts::AllFacts; use crate::borrow_check::path_utils::*; use crate::dataflow::indexes::BorrowIndex; -use rustc::ty::TyCtxt; +use rustc::ty::{self, TyCtxt}; use rustc::mir::visit::Visitor; use rustc::mir::{BasicBlock, Location, Body, Place, Rvalue}; use rustc::mir::{Statement, StatementKind}; @@ -19,6 +19,7 @@ use rustc_data_structures::graph::dominators::Dominators; pub(super) fn generate_invalidates<'tcx>( tcx: TyCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, all_facts: &mut Option, location_table: &LocationTable, body: &Body<'tcx>, @@ -34,6 +35,7 @@ pub(super) fn generate_invalidates<'tcx>( let mut ig = InvalidationGenerator { all_facts, borrow_set, + param_env, tcx, location_table, body, @@ -45,6 +47,7 @@ pub(super) fn generate_invalidates<'tcx>( struct InvalidationGenerator<'cx, 'tcx> { tcx: TyCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, all_facts: &'cx mut AllFacts, location_table: &'cx LocationTable, body: &'cx Body<'tcx>, @@ -401,11 +404,13 @@ impl<'cx, 'tcx> InvalidationGenerator<'cx, 'tcx> { ); let tcx = self.tcx; let body = self.body; + let param_env = self.param_env; let borrow_set = self.borrow_set.clone(); let indices = self.borrow_set.borrows.indices(); each_borrow_involving_path( self, tcx, + param_env, body, location, (sd, place), diff --git a/src/librustc_mir/borrow_check/nll/mod.rs b/src/librustc_mir/borrow_check/nll/mod.rs index a2c5ad202e8c9..d65cdde303ca0 100644 --- a/src/librustc_mir/borrow_check/nll/mod.rs +++ b/src/librustc_mir/borrow_check/nll/mod.rs @@ -138,6 +138,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>( constraint_generation::generate_constraints( infcx, + param_env, &mut liveness_constraints, &mut all_facts, location_table, @@ -162,6 +163,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>( // Generate various additional constraints. invalidation::generate_invalidates( infcx.tcx, + param_env, &mut all_facts, location_table, &body, diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index b27be43dda296..70d6c15d8e2a7 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -669,7 +669,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { ProjectionElem::Subslice { from, to } => PlaceTy::from_ty( match base_ty.sty { ty::Array(inner, size) => { - let size = size.unwrap_usize(tcx); + let size = size.eval_usize(tcx, self.cx.param_env); let min_size = (from as u64) + (to as u64); if let Some(rest_size) = size.checked_sub(min_size) { tcx.mk_array(inner, rest_size) @@ -1214,10 +1214,15 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { let tcx = self.infcx.tcx; for proj in &user_ty.projs { - let projected_ty = curr_projected_ty.projection_ty_core(tcx, proj, |this, field, &()| { - let ty = this.field_ty(tcx, field); - self.normalize(ty, locations) - }); + let projected_ty = curr_projected_ty.projection_ty_core( + tcx, + self.param_env, + proj, + |this, field, &()| { + let ty = this.field_ty(tcx, field); + self.normalize(ty, locations) + }, + ); curr_projected_ty = projected_ty; } debug!("user_ty base: {:?} freshened: {:?} projs: {:?} yields: {:?}", diff --git a/src/librustc_mir/borrow_check/path_utils.rs b/src/librustc_mir/borrow_check/path_utils.rs index da3f165482655..43a012e1494f8 100644 --- a/src/librustc_mir/borrow_check/path_utils.rs +++ b/src/librustc_mir/borrow_check/path_utils.rs @@ -4,7 +4,7 @@ use crate::borrow_check::AccessDepth; use crate::dataflow::indexes::BorrowIndex; use rustc::mir::{BasicBlock, Location, Body, Place, PlaceBase}; use rustc::mir::{ProjectionElem, BorrowKind}; -use rustc::ty::TyCtxt; +use rustc::ty::{self, TyCtxt}; use rustc_data_structures::graph::dominators::Dominators; /// Returns `true` if the borrow represented by `kind` is @@ -25,6 +25,7 @@ pub(super) enum Control { pub(super) fn each_borrow_involving_path<'tcx, F, I, S>( s: &mut S, tcx: TyCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, body: &Body<'tcx>, _location: Location, access_place: (AccessDepth, &Place<'tcx>), @@ -47,6 +48,7 @@ pub(super) fn each_borrow_involving_path<'tcx, F, I, S>( if places_conflict::borrow_conflicts_with_place( tcx, + param_env, body, &borrowed.borrowed_place, borrowed.kind, diff --git a/src/librustc_mir/borrow_check/places_conflict.rs b/src/librustc_mir/borrow_check/places_conflict.rs index b2a03147ecf80..4dd2794f11301 100644 --- a/src/librustc_mir/borrow_check/places_conflict.rs +++ b/src/librustc_mir/borrow_check/places_conflict.rs @@ -26,6 +26,7 @@ crate enum PlaceConflictBias { /// dataflow). crate fn places_conflict<'tcx>( tcx: TyCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, body: &Body<'tcx>, borrow_place: &Place<'tcx>, access_place: &Place<'tcx>, @@ -33,6 +34,7 @@ crate fn places_conflict<'tcx>( ) -> bool { borrow_conflicts_with_place( tcx, + param_env, body, borrow_place, BorrowKind::Mut { allow_two_phase_borrow: true }, @@ -48,6 +50,7 @@ crate fn places_conflict<'tcx>( /// order to make the conservative choice and preserve soundness. pub(super) fn borrow_conflicts_with_place<'tcx>( tcx: TyCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, body: &Body<'tcx>, borrow_place: &Place<'tcx>, borrow_kind: BorrowKind, @@ -78,6 +81,7 @@ pub(super) fn borrow_conflicts_with_place<'tcx>( access_place.iterate(|access_base, access_projections| { place_components_conflict( tcx, + param_env, body, (borrow_base, borrow_projections), borrow_kind, @@ -91,6 +95,7 @@ pub(super) fn borrow_conflicts_with_place<'tcx>( fn place_components_conflict<'tcx>( tcx: TyCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, body: &Body<'tcx>, borrow_projections: (&PlaceBase<'tcx>, ProjectionsIter<'_, 'tcx>), borrow_kind: BorrowKind, @@ -143,7 +148,7 @@ fn place_components_conflict<'tcx>( let borrow_base = borrow_projections.0; let access_base = access_projections.0; - match place_base_conflict(tcx, borrow_base, access_base) { + match place_base_conflict(tcx, param_env, borrow_base, access_base) { Overlap::Arbitrary => { bug!("Two base can't return Arbitrary"); } @@ -306,6 +311,7 @@ fn place_components_conflict<'tcx>( // between `elem1` and `elem2`. fn place_base_conflict<'tcx>( tcx: TyCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, elem1: &PlaceBase<'tcx>, elem2: &PlaceBase<'tcx>, ) -> Overlap { @@ -339,7 +345,7 @@ fn place_base_conflict<'tcx>( (StaticKind::Promoted(promoted_1), StaticKind::Promoted(promoted_2)) => { if promoted_1 == promoted_2 { if let ty::Array(_, len) = s1.ty.sty { - if let Some(0) = len.assert_usize(tcx) { + if let Some(0) = len.try_eval_usize(tcx, param_env) { // Ignore conflicts with promoted [T; 0]. debug!("place_element_conflict: IGNORE-LEN-0-PROMOTED"); return Overlap::Disjoint; diff --git a/src/librustc_mir/build/matches/test.rs b/src/librustc_mir/build/matches/test.rs index 528dfbef6946a..1c93abd40ded2 100644 --- a/src/librustc_mir/build/matches/test.rs +++ b/src/librustc_mir/build/matches/test.rs @@ -109,10 +109,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { match *match_pair.pattern.kind { PatternKind::Constant { value } => { - let switch_ty = ty::ParamEnv::empty().and(switch_ty); indices.entry(value) .or_insert_with(|| { - options.push(value.unwrap_bits(self.hir.tcx(), switch_ty)); + options.push(value.eval_bits( + self.hir.tcx(), self.hir.param_env, switch_ty, + )); options.len() - 1 }); true @@ -653,11 +654,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { use std::cmp::Ordering::*; use rustc::hir::RangeEnd::*; - let param_env = ty::ParamEnv::empty().and(test.ty); let tcx = self.hir.tcx(); - let lo = compare_const_vals(tcx, test.lo, pat.hi, param_env)?; - let hi = compare_const_vals(tcx, test.hi, pat.lo, param_env)?; + let lo = compare_const_vals(tcx, test.lo, pat.hi, self.hir.param_env, test.ty)?; + let hi = compare_const_vals(tcx, test.hi, pat.lo, self.hir.param_env, test.ty)?; match (test.end, pat.end, lo, hi) { // pat < test @@ -772,11 +772,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ) -> Option { use std::cmp::Ordering::*; - let param_env = ty::ParamEnv::empty().and(range.ty); let tcx = self.hir.tcx(); - let a = compare_const_vals(tcx, range.lo, value, param_env)?; - let b = compare_const_vals(tcx, value, range.hi, param_env)?; + let a = compare_const_vals(tcx, range.lo, value, self.hir.param_env, range.ty)?; + let b = compare_const_vals(tcx, value, range.hi, self.hir.param_env, range.ty)?; match (b, range.end) { (Less, _) | diff --git a/src/librustc_mir/dataflow/impls/borrows.rs b/src/librustc_mir/dataflow/impls/borrows.rs index 10c3e52b5255a..018fd2e97b264 100644 --- a/src/librustc_mir/dataflow/impls/borrows.rs +++ b/src/librustc_mir/dataflow/impls/borrows.rs @@ -2,7 +2,7 @@ use crate::borrow_check::borrow_set::{BorrowSet, BorrowData}; use crate::borrow_check::place_ext::PlaceExt; use rustc::mir::{self, Location, Place, PlaceBase, Body}; -use rustc::ty::TyCtxt; +use rustc::ty::{self, TyCtxt}; use rustc::ty::RegionVid; use rustc_data_structures::bit_set::BitSet; @@ -32,6 +32,7 @@ newtype_index! { pub struct Borrows<'a, 'tcx> { tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, + param_env: ty::ParamEnv<'tcx>, borrow_set: Rc>, borrows_out_of_scope_at_location: FxHashMap>, @@ -137,6 +138,7 @@ impl<'a, 'tcx> Borrows<'a, 'tcx> { crate fn new( tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, + param_env: ty::ParamEnv<'tcx>, nonlexical_regioncx: Rc>, borrow_set: &Rc>, ) -> Self { @@ -153,6 +155,7 @@ impl<'a, 'tcx> Borrows<'a, 'tcx> { Borrows { tcx: tcx, body: body, + param_env, borrow_set: borrow_set.clone(), borrows_out_of_scope_at_location, _nonlexical_regioncx: nonlexical_regioncx, @@ -218,6 +221,7 @@ impl<'a, 'tcx> Borrows<'a, 'tcx> { .filter(|&&i| { places_conflict::places_conflict( self.tcx, + self.param_env, self.body, &self.borrow_set.borrows[i].borrowed_place, place, diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index 242afcf5abb2e..1c6a743155ee4 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -556,7 +556,7 @@ fn make_mirror_unadjusted<'a, 'tcx>( }; let span = cx.tcx.def_span(def_id); let count = match cx.tcx.at(span).const_eval(cx.param_env.and(global_id)) { - Ok(cv) => cv.unwrap_usize(cx.tcx), + Ok(cv) => cv.eval_usize(cx.tcx, cx.param_env), Err(ErrorHandled::Reported) => 0, Err(ErrorHandled::TooGeneric) => { cx.tcx.sess.span_err(span, "array lengths can't depend on generic parameters"); diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs index b1a317ee65f6f..8a3d904e77579 100644 --- a/src/librustc_mir/hair/pattern/_match.rs +++ b/src/librustc_mir/hair/pattern/_match.rs @@ -228,7 +228,7 @@ impl LiteralExpander<'tcx> { ConstValue::Slice { data: self.tcx.alloc_map.lock().unwrap_memory(p.alloc_id), start: p.offset.bytes().try_into().unwrap(), - end: n.unwrap_usize(self.tcx).try_into().unwrap(), + end: n.eval_usize(self.tcx, ty::ParamEnv::empty()).try_into().unwrap(), } }, // fat pointers stay the same @@ -646,8 +646,8 @@ fn all_constructors<'a, 'tcx>( ConstantValue(ty::Const::from_bool(cx.tcx, b)) }).collect() } - ty::Array(ref sub_ty, len) if len.assert_usize(cx.tcx).is_some() => { - let len = len.unwrap_usize(cx.tcx); + ty::Array(ref sub_ty, len) if len.try_eval_usize(cx.tcx, cx.param_env).is_some() => { + let len = len.eval_usize(cx.tcx, cx.param_env); if len != 0 && cx.is_uninhabited(sub_ty) { vec![] } else { @@ -789,7 +789,7 @@ where match (value.val, &value.ty.sty) { (_, ty::Array(_, n)) => max_fixed_len = cmp::max( max_fixed_len, - n.unwrap_usize(cx.tcx), + n.eval_usize(cx.tcx, cx.param_env), ), (ConstValue::Slice{ start, end, .. }, ty::Slice(_)) => max_fixed_len = cmp::max( max_fixed_len, @@ -830,7 +830,11 @@ struct IntRange<'tcx> { } impl<'tcx> IntRange<'tcx> { - fn from_ctor(tcx: TyCtxt<'tcx>, ctor: &Constructor<'tcx>) -> Option> { + fn from_ctor( + tcx: TyCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, + ctor: &Constructor<'tcx>, + ) -> Option> { // Floating-point ranges are permitted and we don't want // to consider them when constructing integer ranges. fn is_integral(ty: Ty<'_>) -> bool { @@ -856,7 +860,7 @@ impl<'tcx> IntRange<'tcx> { } ConstantValue(val) if is_integral(val.ty) => { let ty = val.ty; - if let Some(val) = val.assert_bits(tcx, ty::ParamEnv::empty().and(ty)) { + if let Some(val) = val.try_eval_bits(tcx, param_env, ty) { let bias = IntRange::signed_bias(tcx, ty); let val = val ^ bias; Some(IntRange { range: val..=val, ty }) @@ -868,13 +872,17 @@ impl<'tcx> IntRange<'tcx> { } } - fn from_pat(tcx: TyCtxt<'tcx>, mut pat: &Pattern<'tcx>) -> Option> { + fn from_pat( + tcx: TyCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, + mut pat: &Pattern<'tcx>, + ) -> Option> { let range = loop { match pat.kind { box PatternKind::Constant { value } => break ConstantValue(value), box PatternKind::Range(PatternRange { lo, hi, ty, end }) => break ConstantRange( - lo.to_bits(tcx, ty::ParamEnv::empty().and(ty)).unwrap(), - hi.to_bits(tcx, ty::ParamEnv::empty().and(ty)).unwrap(), + lo.eval_bits(tcx, param_env, ty), + hi.eval_bits(tcx, param_env, ty), ty, end, ), @@ -884,7 +892,7 @@ impl<'tcx> IntRange<'tcx> { _ => return None, } }; - Self::from_ctor(tcx, &range) + Self::from_ctor(tcx, param_env, &range) } // The return value of `signed_bias` should be XORed with an endpoint to encode/decode it. @@ -919,10 +927,11 @@ impl<'tcx> IntRange<'tcx> { fn subtract_from( self, tcx: TyCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, ranges: Vec>, ) -> Vec> { let ranges = ranges.into_iter().filter_map(|r| { - IntRange::from_ctor(tcx, &r).map(|i| i.range) + IntRange::from_ctor(tcx, param_env, &r).map(|i| i.range) }); let mut remaining_ranges = vec![]; let ty = self.ty; @@ -989,6 +998,7 @@ enum MissingCtors<'tcx> { fn compute_missing_ctors<'tcx>( info: MissingCtorsInfo, tcx: TyCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, all_ctors: &Vec>, used_ctors: &Vec>, ) -> MissingCtors<'tcx> { @@ -1001,10 +1011,10 @@ fn compute_missing_ctors<'tcx>( // If a constructor appears in a `match` arm, we can // eliminate it straight away. refined_ctors = vec![] - } else if let Some(interval) = IntRange::from_ctor(tcx, used_ctor) { + } else if let Some(interval) = IntRange::from_ctor(tcx, param_env, used_ctor) { // Refine the required constructors for the type by subtracting // the range defined by the current constructor pattern. - refined_ctors = interval.subtract_from(tcx, refined_ctors); + refined_ctors = interval.subtract_from(tcx, param_env, refined_ctors); } // If the constructor patterns that have been considered so far @@ -1119,7 +1129,9 @@ pub fn is_useful<'p, 'a, 'tcx>( if is_declared_nonexhaustive { Useful } else { - split_grouped_constructors(cx.tcx, constructors, matrix, pcx.ty).into_iter().map(|c| + split_grouped_constructors( + cx.tcx, cx.param_env, constructors, matrix, pcx.ty, + ).into_iter().map(|c| is_useful_specialized(cx, matrix, v, c, pcx.ty, witness) ).find(|result| result.is_useful()).unwrap_or(NotUseful) } @@ -1158,8 +1170,9 @@ pub fn is_useful<'p, 'a, 'tcx>( // non-wildcard patterns in the current column. We always determine if // the set is empty, but we only fully construct them on-demand, // because they're rarely used and can be big. - let cheap_missing_ctors = - compute_missing_ctors(MissingCtorsInfo::Emptiness, cx.tcx, &all_ctors, &used_ctors); + let cheap_missing_ctors = compute_missing_ctors( + MissingCtorsInfo::Emptiness, cx.tcx, cx.param_env, &all_ctors, &used_ctors, + ); let is_privately_empty = all_ctors.is_empty() && !cx.is_uninhabited(pcx.ty); let is_declared_nonexhaustive = cx.is_non_exhaustive_enum(pcx.ty) && !cx.is_local(pcx.ty); @@ -1172,9 +1185,10 @@ pub fn is_useful<'p, 'a, 'tcx>( (pcx.ty.is_ptr_sized_integral() && !cx.tcx.features().precise_pointer_size_matching); if cheap_missing_ctors == MissingCtors::Empty && !is_non_exhaustive { - split_grouped_constructors(cx.tcx, all_ctors, matrix, pcx.ty).into_iter().map(|c| { - is_useful_specialized(cx, matrix, v, c, pcx.ty, witness) - }).find(|result| result.is_useful()).unwrap_or(NotUseful) + split_grouped_constructors(cx.tcx, cx.param_env, all_ctors, matrix, pcx.ty) + .into_iter().map(|c| is_useful_specialized(cx, matrix, v, c, pcx.ty, witness)) + .find(|result| result.is_useful()) + .unwrap_or(NotUseful) } else { let matrix = rows.iter().filter_map(|r| { if r[0].is_wildcard() { @@ -1242,9 +1256,9 @@ pub fn is_useful<'p, 'a, 'tcx>( witness }).collect() } else { - let expensive_missing_ctors = - compute_missing_ctors(MissingCtorsInfo::Ctors, cx.tcx, &all_ctors, - &used_ctors); + let expensive_missing_ctors = compute_missing_ctors( + MissingCtorsInfo::Ctors, cx.tcx, cx.param_env, &all_ctors, &used_ctors, + ); if let MissingCtors::Ctors(missing_ctors) = expensive_missing_ctors { pats.into_iter().flat_map(|witness| { missing_ctors.iter().map(move |ctor| { @@ -1327,14 +1341,14 @@ fn pat_constructors<'tcx>(cx: &mut MatchCheckCtxt<'_, 'tcx>, PatternKind::Constant { value } => Some(vec![ConstantValue(value)]), PatternKind::Range(PatternRange { lo, hi, ty, end }) => Some(vec![ConstantRange( - lo.to_bits(cx.tcx, ty::ParamEnv::empty().and(ty)).unwrap(), - hi.to_bits(cx.tcx, ty::ParamEnv::empty().and(ty)).unwrap(), + lo.eval_bits(cx.tcx, cx.param_env, ty), + hi.eval_bits(cx.tcx, cx.param_env, ty), ty, end, )]), PatternKind::Array { .. } => match pcx.ty.sty { ty::Array(_, length) => Some(vec![ - Slice(length.unwrap_usize(cx.tcx)) + Slice(length.eval_usize(cx.tcx, cx.param_env)) ]), _ => span_bug!(pat.span, "bad ty {:?} for array pattern", pcx.ty) }, @@ -1402,7 +1416,8 @@ fn constructor_sub_pattern_tys<'a, 'tcx>( match ty.sty { // If the field type returned is an array of an unknown // size return an TyErr. - ty::Array(_, len) if len.assert_usize(cx.tcx).is_none() => + ty::Array(_, len) + if len.try_eval_usize(cx.tcx, cx.param_env).is_none() => cx.tcx.types.err, _ => ty, } @@ -1432,11 +1447,12 @@ fn slice_pat_covered_by_const<'tcx>( prefix: &[Pattern<'tcx>], slice: &Option>, suffix: &[Pattern<'tcx>], + param_env: ty::ParamEnv<'tcx>, ) -> Result { let data: &[u8] = match (const_val.val, &const_val.ty.sty) { (ConstValue::ByRef { offset, alloc, .. }, ty::Array(t, n)) => { assert_eq!(*t, tcx.types.u8); - let n = n.assert_usize(tcx).unwrap(); + let n = n.eval_usize(tcx, param_env); let ptr = Pointer::new(AllocId(0), offset); alloc.get_bytes(&tcx, ptr, Size::from_bytes(n)).unwrap() }, @@ -1464,7 +1480,7 @@ fn slice_pat_covered_by_const<'tcx>( { match pat.kind { box PatternKind::Constant { value } => { - let b = value.unwrap_bits(tcx, ty::ParamEnv::empty().and(pat.ty)); + let b = value.eval_bits(tcx, param_env, pat.ty); assert_eq!(b as u8 as u128, b); if b as u8 != *ch { return Ok(false); @@ -1526,6 +1542,7 @@ fn should_treat_range_exhaustively(tcx: TyCtxt<'tcx>, ctor: &Constructor<'tcx>) /// merging operation depicted above.) fn split_grouped_constructors<'p, 'tcx>( tcx: TyCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, ctors: Vec>, &Matrix(ref m): &Matrix<'p, 'tcx>, ty: Ty<'tcx>, @@ -1540,7 +1557,7 @@ fn split_grouped_constructors<'p, 'tcx>( // We only care about finding all the subranges within the range of the constructor // range. Anything else is irrelevant, because it is guaranteed to result in // `NotUseful`, which is the default case anyway, and can be ignored. - let ctor_range = IntRange::from_ctor(tcx, &ctor).unwrap(); + let ctor_range = IntRange::from_ctor(tcx, param_env, &ctor).unwrap(); /// Represents a border between 2 integers. Because the intervals spanning borders /// must be able to cover every integer, we need to be able to represent @@ -1565,7 +1582,7 @@ fn split_grouped_constructors<'p, 'tcx>( // `borders` is the set of borders between equivalence classes: each equivalence // class lies between 2 borders. let row_borders = m.iter() - .flat_map(|row| IntRange::from_pat(tcx, row[0])) + .flat_map(|row| IntRange::from_pat(tcx, param_env, row[0])) .flat_map(|range| ctor_range.intersection(&range)) .flat_map(|range| range_borders(range)); let ctor_borders = range_borders(ctor_range.clone()); @@ -1604,11 +1621,12 @@ fn split_grouped_constructors<'p, 'tcx>( /// Checks whether there exists any shared value in either `ctor` or `pat` by intersecting them. fn constructor_intersects_pattern<'p, 'tcx>( tcx: TyCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, ctor: &Constructor<'tcx>, pat: &'p Pattern<'tcx>, ) -> Option; 2]>> { if should_treat_range_exhaustively(tcx, ctor) { - match (IntRange::from_ctor(tcx, ctor), IntRange::from_pat(tcx, pat)) { + match (IntRange::from_ctor(tcx, param_env, ctor), IntRange::from_pat(tcx, param_env, pat)) { (Some(ctor), Some(pat)) => { ctor.intersection(&pat).map(|_| { let (pat_lo, pat_hi) = pat.range.into_inner(); @@ -1623,7 +1641,7 @@ fn constructor_intersects_pattern<'p, 'tcx>( // Fallback for non-ranges and ranges that involve floating-point numbers, which are not // conveniently handled by `IntRange`. For these cases, the constructor may not be a range // so intersection actually devolves into being covered by the pattern. - match constructor_covered_by_range(tcx, ctor, pat) { + match constructor_covered_by_range(tcx, param_env, ctor, pat) { Ok(true) => Some(smallvec![]), Ok(false) | Err(ErrorReported) => None, } @@ -1632,6 +1650,7 @@ fn constructor_intersects_pattern<'p, 'tcx>( fn constructor_covered_by_range<'tcx>( tcx: TyCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, ctor: &Constructor<'tcx>, pat: &Pattern<'tcx>, ) -> Result { @@ -1641,9 +1660,9 @@ fn constructor_covered_by_range<'tcx>( _ => bug!("`constructor_covered_by_range` called with {:?}", pat), }; trace!("constructor_covered_by_range {:#?}, {:#?}, {:#?}, {}", ctor, from, to, ty); - let cmp_from = |c_from| compare_const_vals(tcx, c_from, from, ty::ParamEnv::empty().and(ty)) + let cmp_from = |c_from| compare_const_vals(tcx, c_from, from, param_env, ty) .map(|res| res != Ordering::Less); - let cmp_to = |c_to| compare_const_vals(tcx, c_to, to, ty::ParamEnv::empty().and(ty)); + let cmp_to = |c_to| compare_const_vals(tcx, c_to, to, param_env, ty); macro_rules! some_or_ok { ($e:expr) => { match $e { @@ -1760,7 +1779,7 @@ fn specialize<'p, 'a: 'p, 'tcx>( ConstValue::ByRef { offset, alloc, .. } => ( alloc, offset, - n.unwrap_usize(cx.tcx), + n.eval_usize(cx.tcx, cx.param_env), t, ), _ => span_bug!( @@ -1821,7 +1840,7 @@ fn specialize<'p, 'a: 'p, 'tcx>( // If the constructor is a: // Single value: add a row if the constructor equals the pattern. // Range: add a row if the constructor contains the pattern. - constructor_intersects_pattern(cx.tcx, constructor, pat) + constructor_intersects_pattern(cx.tcx, cx.param_env, constructor, pat) } } } @@ -1830,7 +1849,7 @@ fn specialize<'p, 'a: 'p, 'tcx>( // If the constructor is a: // Single value: add a row if the pattern contains the constructor. // Range: add a row if the constructor intersects the pattern. - constructor_intersects_pattern(cx.tcx, constructor, pat) + constructor_intersects_pattern(cx.tcx, cx.param_env, constructor, pat) } PatternKind::Array { ref prefix, ref slice, ref suffix } | @@ -1854,7 +1873,9 @@ fn specialize<'p, 'a: 'p, 'tcx>( } } ConstantValue(cv) => { - match slice_pat_covered_by_const(cx.tcx, pat.span, cv, prefix, slice, suffix) { + match slice_pat_covered_by_const( + cx.tcx, pat.span, cv, prefix, slice, suffix, cx.param_env, + ) { Ok(true) => Some(smallvec![]), Ok(false) => None, Err(ErrorReported) => None diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs index f759ec7f219d1..5ecfb84b63236 100644 --- a/src/librustc_mir/hair/pattern/mod.rs +++ b/src/librustc_mir/hair/pattern/mod.rs @@ -446,7 +446,8 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { self.tcx, lo, hi, - self.param_env.and(ty), + self.param_env, + ty, ); match (end, cmp) { (RangeEnd::Excluded, Some(Ordering::Less)) => @@ -728,7 +729,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { ty::Array(_, len) => { // fixed-length array - let len = len.unwrap_usize(self.tcx); + let len = len.eval_usize(self.tcx, self.param_env); assert!(len >= prefix.len() as u64 + suffix.len() as u64); PatternKind::Array { prefix: prefix, slice: slice, suffix: suffix } } @@ -1123,7 +1124,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { } ty::Array(_, n) => { PatternKind::Array { - prefix: (0..n.unwrap_usize(self.tcx)) + prefix: (0..n.eval_usize(self.tcx, self.param_env)) .map(|i| adt_subpattern(i as usize, None)) .collect(), slice: None, @@ -1206,7 +1207,8 @@ fn search_for_adt_without_structural_match<'tcx>(tcx: TyCtxt<'tcx>, // (But still tell caller to continue search.) return false; } - ty::Array(_, n) if n.assert_usize(self.tcx) == Some(0) => { + ty::Array(_, n) if n.try_eval_usize(self.tcx, ty::ParamEnv::reveal_all()) == Some(0) + => { // rust-lang/rust#62336: ignore type of contents // for empty array. return false; @@ -1451,7 +1453,8 @@ pub fn compare_const_vals<'tcx>( tcx: TyCtxt<'tcx>, a: &'tcx ty::Const<'tcx>, b: &'tcx ty::Const<'tcx>, - ty: ty::ParamEnvAnd<'tcx, Ty<'tcx>>, + param_env: ty::ParamEnv<'tcx>, + ty: Ty<'tcx>, ) -> Option { trace!("compare_const_vals: {:?}, {:?}", a, b); @@ -1466,15 +1469,16 @@ pub fn compare_const_vals<'tcx>( let fallback = || from_bool(a == b); // Use the fallback if any type differs - if a.ty != b.ty || a.ty != ty.value { + if a.ty != b.ty || a.ty != ty { return fallback(); } - // FIXME: This should use assert_bits(ty) instead of use_bits - // but triggers possibly bugs due to mismatching of arrays and slices - if let (Some(a), Some(b)) = (a.to_bits(tcx, ty), b.to_bits(tcx, ty)) { + let a_bits = a.try_eval_bits(tcx, param_env, ty); + let b_bits = b.try_eval_bits(tcx, param_env, ty); + + if let (Some(a), Some(b)) = (a_bits, b_bits) { use ::rustc_apfloat::Float; - return match ty.value.sty { + return match ty.sty { ty::Float(ast::FloatTy::F32) => { let l = ::rustc_apfloat::ieee::Single::from_bits(a); let r = ::rustc_apfloat::ieee::Single::from_bits(b); @@ -1497,7 +1501,7 @@ pub fn compare_const_vals<'tcx>( } } - if let ty::Str = ty.value.sty { + if let ty::Str = ty.sty { match (a.val, b.val) { ( ConstValue::Slice { data: alloc_a, start: offset_a, end: end_a }, diff --git a/src/librustc_mir/interpret/cast.rs b/src/librustc_mir/interpret/cast.rs index 8e3450656abfb..26cfbfe53a35c 100644 --- a/src/librustc_mir/interpret/cast.rs +++ b/src/librustc_mir/interpret/cast.rs @@ -253,7 +253,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // u64 cast is from usize to u64, which is always good let val = Immediate::new_slice( ptr, - length.unwrap_usize(self.tcx.tcx), + length.eval_usize(self.tcx.tcx, self.param_env), self, ); self.write_immediate(val, dest) diff --git a/src/librustc_mir/interpret/intern.rs b/src/librustc_mir/interpret/intern.rs index e9bba7889119a..1074ab941a761 100644 --- a/src/librustc_mir/interpret/intern.rs +++ b/src/librustc_mir/interpret/intern.rs @@ -176,7 +176,8 @@ for (InternMode::ConstBase, hir::Mutability::MutMutable) | (InternMode::Const, hir::Mutability::MutMutable) => { match referenced_ty.sty { - ty::Array(_, n) if n.unwrap_usize(self.ecx.tcx.tcx) == 0 => {} + ty::Array(_, n) + if n.eval_usize(self.ecx.tcx.tcx, self.param_env) == 0 => {} ty::Slice(_) if value.to_meta().unwrap().unwrap().to_usize(self.ecx)? == 0 => {} _ => bug!("const qualif failed to prevent mutable references"), diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index 32b964dbadfa9..42945c79ddf0e 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -304,8 +304,10 @@ impl<'a, 'tcx> DropElaborator<'a, 'tcx> for DropShimElaborator<'a, 'tcx> { fn build_clone_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'tcx>) -> Body<'tcx> { debug!("build_clone_shim(def_id={:?})", def_id); + let param_env = tcx.param_env(def_id); + let mut builder = CloneShimBuilder::new(tcx, def_id, self_ty); - let is_copy = self_ty.is_copy_modulo_regions(tcx, tcx.param_env(def_id), builder.span); + let is_copy = self_ty.is_copy_modulo_regions(tcx, param_env, builder.span); let dest = Place::RETURN_PLACE; let src = Place::from(Local::new(1+0)).deref(); @@ -313,7 +315,7 @@ fn build_clone_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'tcx>) - match self_ty.sty { _ if is_copy => builder.copy_shim(), ty::Array(ty, len) => { - let len = len.unwrap_usize(tcx); + let len = len.eval_usize(tcx, param_env); builder.array_shim(dest, src, ty, len) } ty::Closure(def_id, substs) => { diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index ffeaf4e19c22a..163d10b9bd5f3 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -367,7 +367,7 @@ impl Qualif for HasMutInterior { } else if let ty::Array(_, len) = ty.sty { // FIXME(eddyb) the `cx.mode == Mode::NonConstFn` condition // seems unnecessary, given that this is merely a ZST. - match len.assert_usize(cx.tcx) { + match len.try_eval_usize(cx.tcx, cx.param_env) { Some(0) if cx.mode == Mode::NonConstFn => {}, _ => return true, } diff --git a/src/librustc_mir/transform/simplify_branches.rs b/src/librustc_mir/transform/simplify_branches.rs index f39c71ef42d71..9ffa3db4c2eb0 100644 --- a/src/librustc_mir/transform/simplify_branches.rs +++ b/src/librustc_mir/transform/simplify_branches.rs @@ -1,6 +1,6 @@ //! A pass that simplifies branches when their condition is known. -use rustc::ty::{TyCtxt, ParamEnv}; +use rustc::ty::TyCtxt; use rustc::mir::*; use crate::transform::{MirPass, MirSource}; @@ -19,15 +19,15 @@ impl MirPass for SimplifyBranches { Cow::Borrowed(&self.label) } - fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body: &mut Body<'tcx>) { + fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) { + let param_env = tcx.param_env(src.def_id()); for block in body.basic_blocks_mut() { let terminator = block.terminator_mut(); terminator.kind = match terminator.kind { TerminatorKind::SwitchInt { discr: Operand::Constant(ref c), switch_ty, ref values, ref targets, .. } => { - let switch_ty = ParamEnv::empty().and(switch_ty); - let constant = c.literal.assert_bits(tcx, switch_ty); + let constant = c.literal.try_eval_bits(tcx, param_env, switch_ty); if let Some(constant) = constant { let (otherwise, targets) = targets.split_last().unwrap(); let mut ret = TerminatorKind::Goto { target: *otherwise }; @@ -44,7 +44,7 @@ impl MirPass for SimplifyBranches { }, TerminatorKind::Assert { target, cond: Operand::Constant(ref c), expected, .. - } if (c.literal.assert_bool(tcx) == Some(true)) == expected => + } if (c.literal.try_eval_bool(tcx, param_env) == Some(true)) == expected => TerminatorKind::Goto { target }, TerminatorKind::FalseEdges { real_target, .. } => { TerminatorKind::Goto { target: real_target } diff --git a/src/librustc_mir/transform/uniform_array_move_out.rs b/src/librustc_mir/transform/uniform_array_move_out.rs index 6aceeebaea161..60489e7fa3668 100644 --- a/src/librustc_mir/transform/uniform_array_move_out.rs +++ b/src/librustc_mir/transform/uniform_array_move_out.rs @@ -37,10 +37,11 @@ use crate::util::patch::MirPatch; pub struct UniformArrayMoveOut; impl MirPass for UniformArrayMoveOut { - fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body: &mut Body<'tcx>) { + fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) { let mut patch = MirPatch::new(body); + let param_env = tcx.param_env(src.def_id()); { - let mut visitor = UniformArrayMoveOutVisitor{body, patch: &mut patch, tcx}; + let mut visitor = UniformArrayMoveOutVisitor{body, patch: &mut patch, tcx, param_env}; visitor.visit_body(body); } patch.apply(body); @@ -51,6 +52,7 @@ struct UniformArrayMoveOutVisitor<'a, 'tcx> { body: &'a Body<'tcx>, patch: &'a mut MirPatch<'tcx>, tcx: TyCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, } impl<'a, 'tcx> Visitor<'tcx> for UniformArrayMoveOutVisitor<'a, 'tcx> { @@ -68,7 +70,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UniformArrayMoveOutVisitor<'a, 'tcx> { let place_ty = Place::ty_from(&src_place.base, &proj.base, self.body, self.tcx).ty; if let ty::Array(item_ty, const_size) = place_ty.sty { - if let Some(size) = const_size.assert_usize(self.tcx) { + if let Some(size) = const_size.try_eval_usize(self.tcx, self.param_env) { assert!(size <= u32::max_value() as u64, "uniform array move out doesn't supported for array bigger then u32"); @@ -183,8 +185,9 @@ impl<'a, 'tcx> UniformArrayMoveOutVisitor<'a, 'tcx> { pub struct RestoreSubsliceArrayMoveOut; impl MirPass for RestoreSubsliceArrayMoveOut { - fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body: &mut Body<'tcx>) { + fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) { let mut patch = MirPatch::new(body); + let param_env = tcx.param_env(src.def_id()); { let mut visitor = RestoreDataCollector { locals_use: IndexVec::from_elem(LocalUse::new(), &body.local_decls), @@ -219,7 +222,7 @@ impl MirPass for RestoreSubsliceArrayMoveOut { let src_ty = Place::ty_from(src_place.base, src_place.projection, body, tcx).ty; if let ty::Array(_, ref size_o) = src_ty.sty { - size_o.assert_usize(tcx) + size_o.try_eval_usize(tcx, param_env) } else { None } diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs index 61ad2ba8f5737..d17dcaafc04f5 100644 --- a/src/librustc_mir/util/elaborate_drops.rs +++ b/src/librustc_mir/util/elaborate_drops.rs @@ -821,7 +821,7 @@ where self.complete_drop(Some(DropFlagMode::Deep), succ, unwind) } ty::Array(ety, size) => { - let size = size.assert_usize(self.tcx()); + let size = size.try_eval_usize(self.tcx(), self.elaborator.param_env()); self.open_drop_for_array(ety, size) }, ty::Slice(ety) => self.open_drop_for_array(ety, None), diff --git a/src/librustc_traits/chalk_context/resolvent_ops.rs b/src/librustc_traits/chalk_context/resolvent_ops.rs index 59c01b8b1b7b1..c7aa6fe105e54 100644 --- a/src/librustc_traits/chalk_context/resolvent_ops.rs +++ b/src/librustc_traits/chalk_context/resolvent_ops.rs @@ -174,6 +174,11 @@ impl TypeRelation<'tcx> for AnswerSubstitutor<'cx, 'tcx> { self.infcx.tcx } + fn param_env(&self) -> ty::ParamEnv<'tcx> { + // FIXME(oli-obk): learn chalk and create param envs + ty::ParamEnv::empty() + } + fn tag(&self) -> &'static str { "chalk_context::answer_substitutor" } diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index e4dda20c822bf..3a43e764dd08e 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -423,7 +423,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let expected_ty = self.structurally_resolved_type(pat.span, expected); let (inner_ty, slice_ty) = match expected_ty.sty { ty::Array(inner_ty, size) => { - if let Some(size) = size.assert_usize(tcx) { + if let Some(size) = size.try_eval_usize(tcx, self.param_env) { let min_len = before.len() as u64 + after.len() as u64; if slice.is_none() { if min_len != size { diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs index 8d2160c0ec7aa..d825358beaade 100644 --- a/src/librustc_typeck/check/expr.rs +++ b/src/librustc_typeck/check/expr.rs @@ -1386,7 +1386,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } ty::Array(_, len) => { if let (Some(len), Ok(user_index)) = ( - len.assert_usize(self.tcx), + len.try_eval_usize(self.tcx, self.param_env), field.as_str().parse::() ) { let base = self.tcx.sess.source_map() diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index fe6d91b0a6eba..3f9e662c6f412 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -824,6 +824,7 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> { { f(mc::MemCategorizationContext::with_infer( &self.infcx, + self.outlives_environment.param_env, self.body_owner, &self.region_scope_tree, &self.tables.borrow(), diff --git a/src/test/ui/consts/self_normalization.rs b/src/test/ui/consts/self_normalization.rs new file mode 100644 index 0000000000000..b2a34f5877b19 --- /dev/null +++ b/src/test/ui/consts/self_normalization.rs @@ -0,0 +1,16 @@ +// check-pass + +fn testfn(_arr: &mut [(); 0]) {} + +trait TestTrait { + fn method(); +} + +impl TestTrait for [(); 0] { + fn method() { + let mut arr: Self = [(); 0]; + testfn(&mut arr); + } +} + +fn main() {} diff --git a/src/test/ui/consts/self_normalization2.rs b/src/test/ui/consts/self_normalization2.rs new file mode 100644 index 0000000000000..4fca38cba30bf --- /dev/null +++ b/src/test/ui/consts/self_normalization2.rs @@ -0,0 +1,21 @@ +// check-pass + +trait Gen { + fn gen(x: Self) -> T; +} + +struct A; + +impl Gen<[(); 0]> for A { + fn gen(x: Self) -> [(); 0] { + [] + } +} + +fn array() -> impl Gen<[(); 0]> { + A +} + +fn main() { + let [] = Gen::gen(array()); +}