From 437f017e2ed2e8c60b6f4af9dc71559ca87fd645 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Fri, 22 Mar 2019 17:30:15 +0100 Subject: [PATCH 01/10] Clean up the `ty::Const::assert*` methods --- src/librustc/ty/mod.rs | 2 +- src/librustc/ty/sty.rs | 34 ++++++------------- src/librustc_mir/build/matches/test.rs | 11 +++--- src/librustc_mir/hair/pattern/_match.rs | 16 ++++----- src/librustc_mir/hair/pattern/mod.rs | 14 ++++---- .../transform/simplify_branches.rs | 3 +- 6 files changed, 30 insertions(+), 50 deletions(-) diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 8e170578227..e71f8d94e7c 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -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.assert_bits(tcx.global_tcx(), val.ty) { trace!("discriminants: {} ({:?})", b, repr_type); Some(Discr { val: b, diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 2b14558de69..7849ae3d516 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; use smallvec::SmallVec; use std::borrow::Cow; @@ -2291,29 +2291,16 @@ 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; - } - 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; + pub fn assert_bits(&self, tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option { + assert_eq!(self.ty, ty); + let ty = tcx.lift_to_global(&ty).unwrap(); + let size = tcx.layout_of(ParamEnv::empty().and(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 { + self.assert_bits(tcx, tcx.types.bool).and_then(|v| match v { 0 => Some(false), 1 => Some(true), _ => None, @@ -2322,19 +2309,18 @@ 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) + self.assert_bits(tcx, tcx.types.usize).map(|v| v as u64) } #[inline] - pub fn unwrap_bits(&self, tcx: TyCtxt<'tcx>, ty: ParamEnvAnd<'tcx, Ty<'tcx>>) -> u128 { + pub fn unwrap_bits(&self, tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> u128 { self.assert_bits(tcx, ty).unwrap_or_else(|| - bug!("expected bits of {}, got {:#?}", ty.value, self)) + 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)) + self.unwrap_bits(tcx, tcx.types.usize) as u64 } } diff --git a/src/librustc_mir/build/matches/test.rs b/src/librustc_mir/build/matches/test.rs index 528dfbef694..45efbfe9b1a 100644 --- a/src/librustc_mir/build/matches/test.rs +++ b/src/librustc_mir/build/matches/test.rs @@ -109,7 +109,6 @@ 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)); @@ -653,11 +652,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, test.ty)?; + let hi = compare_const_vals(tcx, test.hi, pat.lo, test.ty)?; match (test.end, pat.end, lo, hi) { // pat < test @@ -772,11 +770,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, range.ty)?; + let b = compare_const_vals(tcx, value, range.hi, range.ty)?; match (b, range.end) { (Less, _) | diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs index b1a317ee65f..8baefc3162b 100644 --- a/src/librustc_mir/hair/pattern/_match.rs +++ b/src/librustc_mir/hair/pattern/_match.rs @@ -856,7 +856,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.assert_bits(tcx, ty) { let bias = IntRange::signed_bias(tcx, ty); let val = val ^ bias; Some(IntRange { range: val..=val, ty }) @@ -873,8 +873,8 @@ impl<'tcx> IntRange<'tcx> { 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.unwrap_bits(tcx, ty), + hi.unwrap_bits(tcx, ty), ty, end, ), @@ -1327,8 +1327,8 @@ 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.unwrap_bits(cx.tcx, ty), + hi.unwrap_bits(cx.tcx, ty), ty, end, )]), @@ -1464,7 +1464,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.unwrap_bits(tcx, pat.ty); assert_eq!(b as u8 as u128, b); if b as u8 != *ch { return Ok(false); @@ -1641,9 +1641,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, 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, ty); macro_rules! some_or_ok { ($e:expr) => { match $e { diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs index f759ec7f219..745266a6485 100644 --- a/src/librustc_mir/hair/pattern/mod.rs +++ b/src/librustc_mir/hair/pattern/mod.rs @@ -446,7 +446,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { self.tcx, lo, hi, - self.param_env.and(ty), + ty, ); match (end, cmp) { (RangeEnd::Excluded, Some(Ordering::Less)) => @@ -1451,7 +1451,7 @@ 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>>, + ty: Ty<'tcx>, ) -> Option { trace!("compare_const_vals: {:?}, {:?}", a, b); @@ -1466,15 +1466,13 @@ 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)) { + if let (Some(a), Some(b)) = (a.assert_bits(tcx, ty), b.assert_bits(tcx, ty)) { 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 +1495,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/transform/simplify_branches.rs b/src/librustc_mir/transform/simplify_branches.rs index f39c71ef42d..dd45595a4fe 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}; @@ -26,7 +26,6 @@ impl MirPass for SimplifyBranches { 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); if let Some(constant) = constant { let (otherwise, targets) = targets.split_last().unwrap(); From 9b87d22ea83a1b5955d5355f91125456c4dc4bab Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Fri, 22 Mar 2019 18:30:35 +0100 Subject: [PATCH 02/10] Don't abort on unevaluated constants without at least tryting to eval them --- src/librustc/middle/mem_categorization.rs | 2 +- src/librustc/mir/tcx.rs | 2 +- src/librustc/traits/error_reporting.rs | 2 +- src/librustc/ty/error.rs | 2 +- src/librustc/ty/inhabitedness/mod.rs | 2 +- src/librustc/ty/layout.rs | 2 +- src/librustc/ty/mod.rs | 2 +- src/librustc/ty/print/obsolete.rs | 2 +- src/librustc/ty/print/pretty.rs | 4 +- src/librustc/ty/relate.rs | 2 +- src/librustc/ty/sty.rs | 42 +++++++++++++------ .../debuginfo/metadata.rs | 2 +- src/librustc_codegen_ssa/base.rs | 2 +- .../debuginfo/type_names.rs | 2 +- src/librustc_codegen_ssa/mir/constant.rs | 2 +- src/librustc_codegen_ssa/mir/rvalue.rs | 2 +- src/librustc_codegen_utils/symbol_names/v0.rs | 2 +- src/librustc_lint/unused.rs | 2 +- .../borrow_check/nll/type_check/mod.rs | 2 +- .../borrow_check/places_conflict.rs | 2 +- src/librustc_mir/build/matches/test.rs | 2 +- src/librustc_mir/hair/cx/expr.rs | 2 +- src/librustc_mir/hair/pattern/_match.rs | 28 ++++++------- src/librustc_mir/hair/pattern/mod.rs | 8 ++-- src/librustc_mir/interpret/cast.rs | 2 +- src/librustc_mir/interpret/intern.rs | 2 +- src/librustc_mir/shim.rs | 2 +- src/librustc_mir/transform/qualify_consts.rs | 2 +- .../transform/simplify_branches.rs | 4 +- .../transform/uniform_array_move_out.rs | 4 +- src/librustc_mir/util/elaborate_drops.rs | 2 +- src/librustc_typeck/check/_match.rs | 2 +- src/librustc_typeck/check/expr.rs | 2 +- 33 files changed, 80 insertions(+), 64 deletions(-) diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 524d5ddf929..723a4f39055 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -896,7 +896,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) == Some(0) => true, _ => promotable, }; diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs index e2f5d192281..63f81aa97e7 100644 --- a/src/librustc/mir/tcx.rs +++ b/src/librustc/mir/tcx.rs @@ -90,7 +90,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); 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 14a288f5af1..04e3dad85ea 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) { flags.push(( sym::_Self, Some(format!("[{}; {}]", self.tcx.type_of(def.did).to_string(), len)), diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs index b8bdde4a787..46b6500e3cd 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) { 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 0d96e5ea625..3aeae11685c 100644 --- a/src/librustc/ty/inhabitedness/mod.rs +++ b/src/librustc/ty/inhabitedness/mod.rs @@ -190,7 +190,7 @@ impl<'tcx> TyS<'tcx> { })) } - Array(ty, len) => match len.assert_usize(tcx) { + Array(ty, len) => match len.try_eval_usize(tcx) { // 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 e0e70f41abe..7354ad241f9 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).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 e71f8d94e7c..e2834cd92ec 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -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(), val.ty) { + if let Some(b) = val.try_eval_bits(tcx.global_tcx(), 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 c12402a57cc..84c45898470 100644 --- a/src/librustc/ty/print/obsolete.rs +++ b/src/librustc/ty/print/obsolete.rs @@ -89,7 +89,7 @@ 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(); + write!(output, "; {}", len.eval_usize(self.tcx)).unwrap(); output.push(']'); } ty::Slice(inner_type) => { diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index e889f2edef2..41f85942faa 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -696,7 +696,7 @@ pub trait PrettyPrinter<'tcx>: }, ty::Array(ty, sz) => { p!(write("["), print(ty), write("; ")); - if let Some(n) = sz.assert_usize(self.tcx()) { + if let Some(n) = sz.try_eval_usize(self.tcx()) { p!(write("{}", n)); } else { p!(write("_")); @@ -915,7 +915,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()); 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 ca54f63b83a..25ff71cca86 100644 --- a/src/librustc/ty/relate.rs +++ b/src/librustc/ty/relate.rs @@ -466,7 +466,7 @@ 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)) { + match (sz_a.try_eval_usize(tcx), sz_b.try_eval_usize(tcx)) { (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 7849ae3d516..7bc903e8c4a 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; +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) { // 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,16 +2291,32 @@ impl<'tcx> Const<'tcx> { } #[inline] - pub fn assert_bits(&self, tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option { + pub fn try_eval_bits(&self, tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option { assert_eq!(self.ty, ty); - let ty = tcx.lift_to_global(&ty).unwrap(); + // FIXME(eddyb, oli-obk) get the right param_env. let size = tcx.layout_of(ParamEnv::empty().and(ty)).ok()?.size; - self.val.try_to_bits(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) => { + let substs = tcx.lift_to_global(&substs).unwrap(); + let instance = ty::Instance::resolve(tcx, ParamEnv::empty(), did, substs)?; + let gid = GlobalId { + instance, + promoted: None, + }; + let evaluated = tcx.const_eval(ParamEnv::empty().and(gid)).ok()?; + evaluated.val.try_to_bits(size) + }, + // FIXME(const_generics): try to evaluate generic consts with a given param env? + // E.g. when you have an associated constant whose value depends on a generic const + _ => self.val.try_to_bits(size), + } } #[inline] - pub fn assert_bool(&self, tcx: TyCtxt<'tcx>) -> Option { - self.assert_bits(tcx, tcx.types.bool).and_then(|v| match v { + pub fn try_eval_bool(&self, tcx: TyCtxt<'tcx>) -> Option { + self.try_eval_bits(tcx, tcx.types.bool).and_then(|v| match v { 0 => Some(false), 1 => Some(true), _ => None, @@ -2308,19 +2324,19 @@ impl<'tcx> Const<'tcx> { } #[inline] - pub fn assert_usize(&self, tcx: TyCtxt<'tcx>) -> Option { - self.assert_bits(tcx, tcx.types.usize).map(|v| v as u64) + pub fn try_eval_usize(&self, tcx: TyCtxt<'tcx>) -> Option { + self.try_eval_bits(tcx, tcx.types.usize).map(|v| v as u64) } #[inline] - pub fn unwrap_bits(&self, tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> u128 { - self.assert_bits(tcx, ty).unwrap_or_else(|| + pub fn eval_bits(&self, tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> u128 { + self.try_eval_bits(tcx, ty).unwrap_or_else(|| bug!("expected bits of {}, got {:#?}", ty, self)) } #[inline] - pub fn unwrap_usize(&self, tcx: TyCtxt<'tcx>) -> u64 { - self.unwrap_bits(tcx, tcx.types.usize) as u64 + pub fn eval_usize(&self, tcx: TyCtxt<'tcx>) -> u64 { + self.eval_bits(tcx, tcx.types.usize) as u64 } } diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs index f0bdb0018ef..f07f2dc3aa7 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) as c_longlong, _ => -1 }; diff --git a/src/librustc_codegen_ssa/base.rs b/src/librustc_codegen_ssa/base.rs index fc04976f511..7db971bc4b8 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::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 8f0bb6ee198..0c1def33ad3 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))); 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 d6951b923bf..a51deafa9d7 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()), _ => 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 202cf147f1f..40f2a000289 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()); 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 8a54fb6bbc4..cce228ff63b 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, 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 4cccaa942b7..c717d269b58 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) { // 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/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index b27be43dda2..7cfb8f552ad 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); 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) diff --git a/src/librustc_mir/borrow_check/places_conflict.rs b/src/librustc_mir/borrow_check/places_conflict.rs index b2a03147ecf..631e7e0309a 100644 --- a/src/librustc_mir/borrow_check/places_conflict.rs +++ b/src/librustc_mir/borrow_check/places_conflict.rs @@ -339,7 +339,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) { // 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 45efbfe9b1a..930b0c93082 100644 --- a/src/librustc_mir/build/matches/test.rs +++ b/src/librustc_mir/build/matches/test.rs @@ -111,7 +111,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { PatternKind::Constant { value } => { indices.entry(value) .or_insert_with(|| { - options.push(value.unwrap_bits(self.hir.tcx(), switch_ty)); + options.push(value.eval_bits(self.hir.tcx(), switch_ty)); options.len() - 1 }); true diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index 242afcf5abb..caa77f2eb0e 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), 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 8baefc3162b..2ef1b76979b 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).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).is_some() => { + let len = len.eval_usize(cx.tcx); 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), ), (ConstValue::Slice{ start, end, .. }, ty::Slice(_)) => max_fixed_len = cmp::max( max_fixed_len, @@ -856,7 +856,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) { + if let Some(val) = val.try_eval_bits(tcx, ty) { let bias = IntRange::signed_bias(tcx, ty); let val = val ^ bias; Some(IntRange { range: val..=val, ty }) @@ -873,8 +873,8 @@ impl<'tcx> IntRange<'tcx> { match pat.kind { box PatternKind::Constant { value } => break ConstantValue(value), box PatternKind::Range(PatternRange { lo, hi, ty, end }) => break ConstantRange( - lo.unwrap_bits(tcx, ty), - hi.unwrap_bits(tcx, ty), + lo.eval_bits(tcx, ty), + hi.eval_bits(tcx, ty), ty, end, ), @@ -1327,14 +1327,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.unwrap_bits(cx.tcx, ty), - hi.unwrap_bits(cx.tcx, ty), + lo.eval_bits(cx.tcx, ty), + hi.eval_bits(cx.tcx, 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)) ]), _ => span_bug!(pat.span, "bad ty {:?} for array pattern", pcx.ty) }, @@ -1402,7 +1402,7 @@ 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).is_none() => cx.tcx.types.err, _ => ty, } @@ -1436,7 +1436,7 @@ fn slice_pat_covered_by_const<'tcx>( 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); let ptr = Pointer::new(AllocId(0), offset); alloc.get_bytes(&tcx, ptr, Size::from_bytes(n)).unwrap() }, @@ -1464,7 +1464,7 @@ fn slice_pat_covered_by_const<'tcx>( { match pat.kind { box PatternKind::Constant { value } => { - let b = value.unwrap_bits(tcx, pat.ty); + let b = value.eval_bits(tcx, pat.ty); assert_eq!(b as u8 as u128, b); if b as u8 != *ch { return Ok(false); @@ -1760,7 +1760,7 @@ fn specialize<'p, 'a: 'p, 'tcx>( ConstValue::ByRef { offset, alloc, .. } => ( alloc, offset, - n.unwrap_usize(cx.tcx), + n.eval_usize(cx.tcx), t, ), _ => span_bug!( diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs index 745266a6485..0614b0b2993 100644 --- a/src/librustc_mir/hair/pattern/mod.rs +++ b/src/librustc_mir/hair/pattern/mod.rs @@ -728,7 +728,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); assert!(len >= prefix.len() as u64 + suffix.len() as u64); PatternKind::Array { prefix: prefix, slice: slice, suffix: suffix } } @@ -1123,7 +1123,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)) .map(|i| adt_subpattern(i as usize, None)) .collect(), slice: None, @@ -1206,7 +1206,7 @@ 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) == Some(0) => { // rust-lang/rust#62336: ignore type of contents // for empty array. return false; @@ -1470,7 +1470,7 @@ pub fn compare_const_vals<'tcx>( return fallback(); } - if let (Some(a), Some(b)) = (a.assert_bits(tcx, ty), b.assert_bits(tcx, ty)) { + if let (Some(a), Some(b)) = (a.try_eval_bits(tcx, ty), b.try_eval_bits(tcx, ty)) { use ::rustc_apfloat::Float; return match ty.sty { ty::Float(ast::FloatTy::F32) => { diff --git a/src/librustc_mir/interpret/cast.rs b/src/librustc_mir/interpret/cast.rs index 8e3450656ab..5efcd1cbeeb 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, ); self.write_immediate(val, dest) diff --git a/src/librustc_mir/interpret/intern.rs b/src/librustc_mir/interpret/intern.rs index e9bba788911..e615645bb2a 100644 --- a/src/librustc_mir/interpret/intern.rs +++ b/src/librustc_mir/interpret/intern.rs @@ -176,7 +176,7 @@ 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) == 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 32b964dbadf..5752a8ccec0 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -313,7 +313,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); 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 ffeaf4e19c2..69ad4126077 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) { 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 dd45595a4fe..160751aac59 100644 --- a/src/librustc_mir/transform/simplify_branches.rs +++ b/src/librustc_mir/transform/simplify_branches.rs @@ -26,7 +26,7 @@ impl MirPass for SimplifyBranches { TerminatorKind::SwitchInt { discr: Operand::Constant(ref c), switch_ty, ref values, ref targets, .. } => { - let constant = c.literal.assert_bits(tcx, switch_ty); + let constant = c.literal.try_eval_bits(tcx, switch_ty); if let Some(constant) = constant { let (otherwise, targets) = targets.split_last().unwrap(); let mut ret = TerminatorKind::Goto { target: *otherwise }; @@ -43,7 +43,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) == 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 6aceeebaea1..2ad6eaa3ed9 100644 --- a/src/librustc_mir/transform/uniform_array_move_out.rs +++ b/src/librustc_mir/transform/uniform_array_move_out.rs @@ -68,7 +68,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) { assert!(size <= u32::max_value() as u64, "uniform array move out doesn't supported for array bigger then u32"); @@ -219,7 +219,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) } else { None } diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs index 61ad2ba8f57..42f90b2ae40 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.open_drop_for_array(ety, size) }, ty::Slice(ety) => self.open_drop_for_array(ety, None), diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index e4dda20c822..9ae4e99ca6e 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) { 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 8d2160c0ec7..845022f506a 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), field.as_str().parse::() ) { let base = self.tcx.sess.source_map() From f9e29b279c2045d520d624d958860f6b8c95ab7b Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Fri, 22 Mar 2019 18:33:12 +0100 Subject: [PATCH 03/10] Add regression tests --- src/test/ui/consts/self_normalization.rs | 16 ++++++++++++++++ src/test/ui/consts/self_normalization2.rs | 21 +++++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 src/test/ui/consts/self_normalization.rs create mode 100644 src/test/ui/consts/self_normalization2.rs diff --git a/src/test/ui/consts/self_normalization.rs b/src/test/ui/consts/self_normalization.rs new file mode 100644 index 00000000000..e11e8b4318e --- /dev/null +++ b/src/test/ui/consts/self_normalization.rs @@ -0,0 +1,16 @@ +// compile-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 00000000000..8c79bed156a --- /dev/null +++ b/src/test/ui/consts/self_normalization2.rs @@ -0,0 +1,21 @@ +// compile-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()); +} From 7710820d184f36c3ab659dace70f8ee366212169 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Tue, 26 Mar 2019 00:13:09 +0100 Subject: [PATCH 04/10] Fiddle param env through to `try_eval_bits` in most places --- src/librustc/infer/combine.rs | 4 + src/librustc/infer/equate.rs | 2 + src/librustc/infer/glb.rs | 2 + src/librustc/infer/lub.rs | 2 + src/librustc/infer/nll_relate/mod.rs | 6 ++ src/librustc/infer/outlives/env.rs | 2 +- src/librustc/infer/sub.rs | 3 + src/librustc/middle/expr_use_visitor.rs | 2 + src/librustc/middle/mem_categorization.rs | 9 +- src/librustc/mir/tcx.rs | 5 +- src/librustc/traits/error_reporting.rs | 2 +- src/librustc/traits/select.rs | 6 +- src/librustc/ty/_match.rs | 6 +- src/librustc/ty/error.rs | 2 +- src/librustc/ty/inhabitedness/mod.rs | 3 +- src/librustc/ty/layout.rs | 2 +- src/librustc/ty/mod.rs | 2 +- src/librustc/ty/print/obsolete.rs | 3 +- src/librustc/ty/print/pretty.rs | 4 +- src/librustc/ty/relate.rs | 6 +- src/librustc/ty/sty.rs | 33 ++++--- .../debuginfo/metadata.rs | 2 +- src/librustc_codegen_ssa/base.rs | 2 +- .../debuginfo/type_names.rs | 2 +- src/librustc_codegen_ssa/mir/constant.rs | 2 +- src/librustc_codegen_ssa/mir/rvalue.rs | 2 +- src/librustc_codegen_utils/symbol_names/v0.rs | 2 +- src/librustc_lint/unused.rs | 2 +- src/librustc_mir/borrow_check/mod.rs | 7 +- .../borrow_check/nll/constraint_generation.rs | 4 + .../borrow_check/nll/invalidation.rs | 7 +- src/librustc_mir/borrow_check/nll/mod.rs | 2 + .../borrow_check/nll/type_check/mod.rs | 15 ++- src/librustc_mir/borrow_check/path_utils.rs | 4 +- .../borrow_check/places_conflict.rs | 10 +- src/librustc_mir/build/matches/test.rs | 13 ++- src/librustc_mir/dataflow/impls/borrows.rs | 6 +- src/librustc_mir/hair/cx/expr.rs | 2 +- src/librustc_mir/hair/pattern/_match.rs | 97 +++++++++++-------- src/librustc_mir/hair/pattern/mod.rs | 17 ++-- src/librustc_mir/interpret/cast.rs | 2 +- src/librustc_mir/interpret/intern.rs | 3 +- src/librustc_mir/shim.rs | 6 +- src/librustc_mir/transform/qualify_consts.rs | 2 +- .../transform/simplify_branches.rs | 7 +- .../transform/uniform_array_move_out.rs | 13 ++- src/librustc_mir/util/elaborate_drops.rs | 2 +- .../chalk_context/resolvent_ops.rs | 5 + src/librustc_typeck/check/_match.rs | 2 +- src/librustc_typeck/check/expr.rs | 2 +- src/librustc_typeck/check/regionck.rs | 1 + 51 files changed, 230 insertions(+), 119 deletions(-) diff --git a/src/librustc/infer/combine.rs b/src/librustc/infer/combine.rs index e20b53455f4..4a9b68f2437 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 5eebe9e78d3..5dfa0d29daf 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 55021316747..2cef5211762 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 156288b9e6a..e20372f1513 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 a0621af0537..5d521def65b 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 d5558861285..e6155454d46 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 1452a6dee5b..cd1d206b5fc 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 2448db032b9..a274d7bbee5 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 723a4f39055..77d6f393244 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.try_eval_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 63f81aa97e7..f8889380b2a 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.eval_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 04e3dad85ea..83bd5c56040 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.try_eval_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 2486f29ab0f..da582c015e4 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 6e10dc03a28..f800a70e0be 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 46b6500e3cd..4a72794b61a 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.try_eval_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 3aeae11685c..2b329165665 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.try_eval_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 7354ad241f9..a66a4ac66f3 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.try_eval_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 e2834cd92ec..646fb7e4c36 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -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.try_eval_bits(tcx.global_tcx(), val.ty) { + if let Some(b) = val.try_eval_bits(tcx.global_tcx(), param_env.and(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 84c45898470..b68e6a74487 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.eval_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 41f85942faa..f14ab1d4441 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -696,7 +696,7 @@ pub trait PrettyPrinter<'tcx>: }, ty::Array(ty, sz) => { p!(write("["), print(ty), write("; ")); - if let Some(n) = sz.try_eval_usize(self.tcx()) { + if let Some(n) = sz.try_eval_usize(self.tcx(), ty::ParamEnv::empty()) { p!(write("{}", n)); } else { p!(write("_")); @@ -915,7 +915,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.eval_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 25ff71cca86..945e3e158ea 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.try_eval_usize(tcx), sz_b.try_eval_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 7bc903e8c4a..497d1d8a917 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -1726,7 +1726,7 @@ impl<'tcx> TyS<'tcx> { ty.expect_ty().conservative_is_privately_uninhabited(tcx) }), ty::Array(ty, len) => { - match len.try_eval_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,21 +2291,24 @@ impl<'tcx> Const<'tcx> { } #[inline] - pub fn try_eval_bits(&self, tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option { - assert_eq!(self.ty, ty); - // FIXME(eddyb, oli-obk) get the right param_env. - let size = tcx.layout_of(ParamEnv::empty().and(ty)).ok()?.size; + pub fn try_eval_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; 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) => { let substs = tcx.lift_to_global(&substs).unwrap(); - let instance = ty::Instance::resolve(tcx, ParamEnv::empty(), did, substs)?; + let instance = ty::Instance::resolve(tcx, ty.param_env, did, substs)?; let gid = GlobalId { instance, promoted: None, }; - let evaluated = tcx.const_eval(ParamEnv::empty().and(gid)).ok()?; + let evaluated = tcx.const_eval(ty.param_env.and(gid)).ok()?; evaluated.val.try_to_bits(size) }, // FIXME(const_generics): try to evaluate generic consts with a given param env? @@ -2315,8 +2318,8 @@ impl<'tcx> Const<'tcx> { } #[inline] - pub fn try_eval_bool(&self, tcx: TyCtxt<'tcx>) -> Option { - self.try_eval_bits(tcx, 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.and(tcx.types.bool)).and_then(|v| match v { 0 => Some(false), 1 => Some(true), _ => None, @@ -2324,19 +2327,19 @@ impl<'tcx> Const<'tcx> { } #[inline] - pub fn try_eval_usize(&self, tcx: TyCtxt<'tcx>) -> Option { - self.try_eval_bits(tcx, 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.and(tcx.types.usize)).map(|v| v as u64) } #[inline] - pub fn eval_bits(&self, tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> u128 { + pub fn eval_bits(&self, tcx: TyCtxt<'tcx>, ty: ParamEnvAnd<'tcx, Ty<'tcx>>) -> u128 { self.try_eval_bits(tcx, ty).unwrap_or_else(|| - bug!("expected bits of {}, got {:#?}", ty, self)) + bug!("expected bits of {:#?}, got {:#?}", ty, self)) } #[inline] - pub fn eval_usize(&self, tcx: TyCtxt<'tcx>) -> u64 { - self.eval_bits(tcx, tcx.types.usize) as u64 + pub fn eval_usize(&self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> u64 { + self.eval_bits(tcx, param_env.and(tcx.types.usize)) as u64 } } diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs index f07f2dc3aa7..3b7aee84862 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.eval_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 7db971bc4b8..cdc54bb179e 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.eval_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 0c1def33ad3..ea39913d4b9 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.eval_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 a51deafa9d7..216e5a4645a 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.eval_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 40f2a000289..21cedb7a9b3 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.eval_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 cce228ff63b..79ec7e63b21 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.try_eval_bits(self.tcx, ct.ty) { + if let Some(bits) = ct.try_eval_bits(self.tcx, ty::ParamEnv::reveal_all().and(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 c717d269b58..23b58892028 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.try_eval_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 9f22d7c51df..340ca5747d8 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 95c3299693b..5c230913a0d 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 631a8142113..71106af7670 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 a2c5ad202e8..d65cdde303c 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 7cfb8f552ad..70d6c15d8e2 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.eval_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 da3f1654826..43a012e1494 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 631e7e0309a..4dd2794f113 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.try_eval_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 930b0c93082..2165b1a342d 100644 --- a/src/librustc_mir/build/matches/test.rs +++ b/src/librustc_mir/build/matches/test.rs @@ -111,7 +111,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { PatternKind::Constant { value } => { indices.entry(value) .or_insert_with(|| { - options.push(value.eval_bits(self.hir.tcx(), switch_ty)); + options.push(value.eval_bits( + self.hir.tcx(), self.hir.param_env.and(switch_ty), + )); options.len() - 1 }); true @@ -653,9 +655,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { use rustc::hir::RangeEnd::*; let tcx = self.hir.tcx(); + let test_ty = self.hir.param_env.and(test.ty); - let lo = compare_const_vals(tcx, test.lo, pat.hi, test.ty)?; - let hi = compare_const_vals(tcx, test.hi, pat.lo, test.ty)?; + let lo = compare_const_vals(tcx, test.lo, pat.hi, test_ty)?; + let hi = compare_const_vals(tcx, test.hi, pat.lo, test_ty)?; match (test.end, pat.end, lo, hi) { // pat < test @@ -772,8 +775,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let tcx = self.hir.tcx(); - let a = compare_const_vals(tcx, range.lo, value, range.ty)?; - let b = compare_const_vals(tcx, value, range.hi, range.ty)?; + let a = compare_const_vals(tcx, range.lo, value, self.hir.param_env.and(range.ty))?; + let b = compare_const_vals(tcx, value, range.hi, self.hir.param_env.and(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 10c3e52b525..018fd2e97b2 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 caa77f2eb0e..1c6a743155e 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.eval_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 2ef1b76979b..2a11ea83136 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.eval_usize(self.tcx).try_into().unwrap(), + end: n.eval_usize(self.tcx, ty::ParamEnv::reveal_all()).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.try_eval_usize(cx.tcx).is_some() => { - let len = len.eval_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.eval_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.try_eval_bits(tcx, ty) { + if let Some(val) = val.try_eval_bits(tcx, param_env.and(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.eval_bits(tcx, ty), - hi.eval_bits(tcx, ty), + lo.eval_bits(tcx, param_env.and(ty)), + hi.eval_bits(tcx, param_env.and(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.eval_bits(cx.tcx, ty), - hi.eval_bits(cx.tcx, ty), + lo.eval_bits(cx.tcx, cx.param_env.and(ty)), + hi.eval_bits(cx.tcx, cx.param_env.and(ty)), ty, end, )]), PatternKind::Array { .. } => match pcx.ty.sty { ty::Array(_, length) => Some(vec![ - Slice(length.eval_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.try_eval_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.eval_usize(tcx); + 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.eval_bits(tcx, pat.ty); + let b = value.eval_bits(tcx, param_env.and(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) + let cmp_from = |c_from| compare_const_vals(tcx, c_from, from, param_env.and(ty)) .map(|res| res != Ordering::Less); - let cmp_to = |c_to| compare_const_vals(tcx, c_to, to, ty); + let cmp_to = |c_to| compare_const_vals(tcx, c_to, to, param_env.and(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.eval_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 0614b0b2993..af030476706 100644 --- a/src/librustc_mir/hair/pattern/mod.rs +++ b/src/librustc_mir/hair/pattern/mod.rs @@ -446,7 +446,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { self.tcx, lo, hi, - ty, + self.param_env.and(ty), ); match (end, cmp) { (RangeEnd::Excluded, Some(Ordering::Less)) => @@ -728,7 +728,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { ty::Array(_, len) => { // fixed-length array - let len = len.eval_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 +1123,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { } ty::Array(_, n) => { PatternKind::Array { - prefix: (0..n.eval_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 +1206,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.try_eval_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 +1452,7 @@ pub fn compare_const_vals<'tcx>( tcx: TyCtxt<'tcx>, a: &'tcx ty::Const<'tcx>, b: &'tcx ty::Const<'tcx>, - ty: Ty<'tcx>, + ty: ty::ParamEnvAnd<'tcx, Ty<'tcx>>, ) -> Option { trace!("compare_const_vals: {:?}, {:?}", a, b); @@ -1466,13 +1467,13 @@ 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 { + if a.ty != b.ty || a.ty != ty.value { return fallback(); } if let (Some(a), Some(b)) = (a.try_eval_bits(tcx, ty), b.try_eval_bits(tcx, ty)) { use ::rustc_apfloat::Float; - return match ty.sty { + return match ty.value.sty { ty::Float(ast::FloatTy::F32) => { let l = ::rustc_apfloat::ieee::Single::from_bits(a); let r = ::rustc_apfloat::ieee::Single::from_bits(b); @@ -1495,7 +1496,7 @@ pub fn compare_const_vals<'tcx>( } } - if let ty::Str = ty.sty { + if let ty::Str = ty.value.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 5efcd1cbeeb..26cfbfe53a3 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.eval_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 e615645bb2a..1074ab941a7 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.eval_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 5752a8ccec0..42945c79ddf 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.eval_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 69ad4126077..163d10b9bd5 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.try_eval_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 160751aac59..973aa706472 100644 --- a/src/librustc_mir/transform/simplify_branches.rs +++ b/src/librustc_mir/transform/simplify_branches.rs @@ -19,14 +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 constant = c.literal.try_eval_bits(tcx, switch_ty); + let constant = c.literal.try_eval_bits(tcx, param_env.and(switch_ty)); if let Some(constant) = constant { let (otherwise, targets) = targets.split_last().unwrap(); let mut ret = TerminatorKind::Goto { target: *otherwise }; @@ -43,7 +44,7 @@ impl MirPass for SimplifyBranches { }, TerminatorKind::Assert { target, cond: Operand::Constant(ref c), expected, .. - } if (c.literal.try_eval_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 2ad6eaa3ed9..60489e7fa36 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.try_eval_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.try_eval_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 42f90b2ae40..d17dcaafc04 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.try_eval_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 59c01b8b1b7..c7aa6fe105e 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 9ae4e99ca6e..3a43e764dd0 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.try_eval_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 845022f506a..d825358beaa 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.try_eval_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 fe6d91b0a6e..3f9e662c6f4 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(), From f4f957d00b5e8f8de0a2818a39cc9ec6a47bc828 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Sun, 31 Mar 2019 18:35:39 +0200 Subject: [PATCH 05/10] Clear the ParamEnv where its information is irrelevant --- src/librustc/ty/mod.rs | 4 +-- src/librustc/ty/sty.rs | 26 +++++++++++-------- src/librustc_codegen_utils/symbol_names/v0.rs | 2 +- src/librustc_mir/build/matches/test.rs | 11 ++++---- src/librustc_mir/hair/pattern/_match.rs | 16 ++++++------ src/librustc_mir/hair/pattern/mod.rs | 17 +++++++----- .../transform/simplify_branches.rs | 2 +- 7 files changed, 43 insertions(+), 35 deletions(-) diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 646fb7e4c36..5fec95e2a3b 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.try_eval_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/sty.rs b/src/librustc/ty/sty.rs index 497d1d8a917..a37fa130813 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -2294,21 +2294,25 @@ impl<'tcx> Const<'tcx> { pub fn try_eval_bits( &self, tcx: TyCtxt<'tcx>, - ty: ParamEnvAnd<'tcx, Ty<'tcx>>, + param_env: ParamEnv<'tcx>, + ty: Ty<'tcx>, ) -> Option { - assert_eq!(self.ty, ty.value); - let size = tcx.layout_of(ty).ok()?.size; + assert_eq!(self.ty, ty); + 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) => { - let substs = tcx.lift_to_global(&substs).unwrap(); - let instance = ty::Instance::resolve(tcx, ty.param_env, did, substs)?; + // if `substs` has no unresolved components, use and empty param_env + let pem_and_substs = param_env.with_reveal_all().and(substs); + let (param_env, substs) = tcx.lift_to_global(&pem_and_substs).unwrap().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(ty.param_env.and(gid)).ok()?; + let evaluated = tcx.const_eval(param_env.and(gid)).ok()?; evaluated.val.try_to_bits(size) }, // FIXME(const_generics): try to evaluate generic consts with a given param env? @@ -2319,7 +2323,7 @@ impl<'tcx> Const<'tcx> { #[inline] pub fn try_eval_bool(&self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Option { - self.try_eval_bits(tcx, param_env.and(tcx.types.bool)).and_then(|v| match v { + self.try_eval_bits(tcx, param_env, tcx.types.bool).and_then(|v| match v { 0 => Some(false), 1 => Some(true), _ => None, @@ -2328,18 +2332,18 @@ impl<'tcx> Const<'tcx> { #[inline] pub fn try_eval_usize(&self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Option { - self.try_eval_bits(tcx, param_env.and(tcx.types.usize)).map(|v| v as u64) + self.try_eval_bits(tcx, param_env, tcx.types.usize).map(|v| v as u64) } #[inline] - pub fn eval_bits(&self, tcx: TyCtxt<'tcx>, ty: ParamEnvAnd<'tcx, Ty<'tcx>>) -> u128 { - self.try_eval_bits(tcx, ty).unwrap_or_else(|| + 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 eval_usize(&self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> u64 { - self.eval_bits(tcx, param_env.and(tcx.types.usize)) as u64 + self.eval_bits(tcx, param_env, tcx.types.usize) as u64 } } diff --git a/src/librustc_codegen_utils/symbol_names/v0.rs b/src/librustc_codegen_utils/symbol_names/v0.rs index 79ec7e63b21..47601da8b7b 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.try_eval_bits(self.tcx, ty::ParamEnv::reveal_all().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_mir/build/matches/test.rs b/src/librustc_mir/build/matches/test.rs index 2165b1a342d..1c93abd40de 100644 --- a/src/librustc_mir/build/matches/test.rs +++ b/src/librustc_mir/build/matches/test.rs @@ -112,7 +112,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { indices.entry(value) .or_insert_with(|| { options.push(value.eval_bits( - self.hir.tcx(), self.hir.param_env.and(switch_ty), + self.hir.tcx(), self.hir.param_env, switch_ty, )); options.len() - 1 }); @@ -655,10 +655,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { use rustc::hir::RangeEnd::*; let tcx = self.hir.tcx(); - let test_ty = self.hir.param_env.and(test.ty); - let lo = compare_const_vals(tcx, test.lo, pat.hi, test_ty)?; - let hi = compare_const_vals(tcx, test.hi, pat.lo, test_ty)?; + 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 @@ -775,8 +774,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let tcx = self.hir.tcx(); - let a = compare_const_vals(tcx, range.lo, value, self.hir.param_env.and(range.ty))?; - let b = compare_const_vals(tcx, value, range.hi, self.hir.param_env.and(range.ty))?; + 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/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs index 2a11ea83136..8da4d737cc5 100644 --- a/src/librustc_mir/hair/pattern/_match.rs +++ b/src/librustc_mir/hair/pattern/_match.rs @@ -860,7 +860,7 @@ impl<'tcx> IntRange<'tcx> { } ConstantValue(val) if is_integral(val.ty) => { let ty = val.ty; - if let Some(val) = val.try_eval_bits(tcx, param_env.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 }) @@ -881,8 +881,8 @@ impl<'tcx> IntRange<'tcx> { match pat.kind { box PatternKind::Constant { value } => break ConstantValue(value), box PatternKind::Range(PatternRange { lo, hi, ty, end }) => break ConstantRange( - lo.eval_bits(tcx, param_env.and(ty)), - hi.eval_bits(tcx, param_env.and(ty)), + lo.eval_bits(tcx, param_env, ty), + hi.eval_bits(tcx, param_env, ty), ty, end, ), @@ -1341,8 +1341,8 @@ 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.eval_bits(cx.tcx, cx.param_env.and(ty)), - hi.eval_bits(cx.tcx, cx.param_env.and(ty)), + lo.eval_bits(cx.tcx, cx.param_env, ty), + hi.eval_bits(cx.tcx, cx.param_env, ty), ty, end, )]), @@ -1480,7 +1480,7 @@ fn slice_pat_covered_by_const<'tcx>( { match pat.kind { box PatternKind::Constant { value } => { - let b = value.eval_bits(tcx, param_env.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); @@ -1660,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, param_env.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, param_env.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 { diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs index af030476706..5ecfb84b632 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)) => @@ -1452,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); @@ -1467,13 +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(); } - if let (Some(a), Some(b)) = (a.try_eval_bits(tcx, ty), b.try_eval_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); @@ -1496,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/transform/simplify_branches.rs b/src/librustc_mir/transform/simplify_branches.rs index 973aa706472..9ffa3db4c2e 100644 --- a/src/librustc_mir/transform/simplify_branches.rs +++ b/src/librustc_mir/transform/simplify_branches.rs @@ -27,7 +27,7 @@ impl MirPass for SimplifyBranches { TerminatorKind::SwitchInt { discr: Operand::Constant(ref c), switch_ty, ref values, ref targets, .. } => { - let constant = c.literal.try_eval_bits(tcx, param_env.and(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 }; From 2d86d040a5472998843008cbb6ffa58de0fd138e Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Fri, 17 May 2019 11:13:55 +0200 Subject: [PATCH 06/10] Address comment and formatting nits --- src/librustc/ty/sty.rs | 4 ++-- src/test/ui/consts/self_normalization.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index a37fa130813..e5e47a51e8d 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -2298,6 +2298,7 @@ impl<'tcx> Const<'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, @@ -2315,8 +2316,7 @@ impl<'tcx> Const<'tcx> { let evaluated = tcx.const_eval(param_env.and(gid)).ok()?; evaluated.val.try_to_bits(size) }, - // FIXME(const_generics): try to evaluate generic consts with a given param env? - // E.g. when you have an associated constant whose value depends on a generic const + // otherwise just extract a `ConstValue`'s bits if possible _ => self.val.try_to_bits(size), } } diff --git a/src/test/ui/consts/self_normalization.rs b/src/test/ui/consts/self_normalization.rs index e11e8b4318e..93aadda1ec5 100644 --- a/src/test/ui/consts/self_normalization.rs +++ b/src/test/ui/consts/self_normalization.rs @@ -1,6 +1,6 @@ // compile-pass -fn testfn(_arr: &mut [();0]) {} +fn testfn(_arr: &mut [(); 0]) {} trait TestTrait { fn method(); From 7385f2177f8e3b66ec8f506ed8ec9689460a9b85 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Sun, 26 May 2019 15:27:04 +0200 Subject: [PATCH 07/10] Fixup: eval_usize needs param env --- src/librustc_mir/hair/pattern/_match.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs index 8da4d737cc5..8a3d904e775 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.eval_usize(self.tcx, ty::ParamEnv::reveal_all()).try_into().unwrap(), + end: n.eval_usize(self.tcx, ty::ParamEnv::empty()).try_into().unwrap(), } }, // fat pointers stay the same From d1f62b92eb60815840647d59132c7a737768a694 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Sun, 26 May 2019 17:33:32 +0200 Subject: [PATCH 08/10] Prevent array length printing cycle with debug assertions --- src/librustc/ty/print/pretty.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index f14ab1d4441..017f67463c3 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.try_eval_usize(self.tcx(), ty::ParamEnv::empty()) { + 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("_")); From f2079338b5ef5b7354def29e2410998f3089066e Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Fri, 26 Jul 2019 07:57:42 +0200 Subject: [PATCH 09/10] Update to new passing-ui-test scheme --- src/test/ui/consts/self_normalization.rs | 2 +- src/test/ui/consts/self_normalization2.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/ui/consts/self_normalization.rs b/src/test/ui/consts/self_normalization.rs index 93aadda1ec5..b2a34f5877b 100644 --- a/src/test/ui/consts/self_normalization.rs +++ b/src/test/ui/consts/self_normalization.rs @@ -1,4 +1,4 @@ -// compile-pass +// check-pass fn testfn(_arr: &mut [(); 0]) {} diff --git a/src/test/ui/consts/self_normalization2.rs b/src/test/ui/consts/self_normalization2.rs index 8c79bed156a..4fca38cba30 100644 --- a/src/test/ui/consts/self_normalization2.rs +++ b/src/test/ui/consts/self_normalization2.rs @@ -1,4 +1,4 @@ -// compile-pass +// check-pass trait Gen { fn gen(x: Self) -> T; From bd57498e7d509168609a685b264289643ef8b2c3 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Mon, 5 Aug 2019 17:49:40 +0200 Subject: [PATCH 10/10] Get rid of one more useless `lift` invocation --- src/librustc/ty/sty.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index e5e47a51e8d..769b6592b6f 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -2305,8 +2305,7 @@ impl<'tcx> Const<'tcx> { // 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 pem_and_substs = param_env.with_reveal_all().and(substs); - let (param_env, substs) = tcx.lift_to_global(&pem_and_substs).unwrap().into_parts(); + 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 {