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 };