1
Fork 0

Clear the ParamEnv where its information is irrelevant

This commit is contained in:
Oliver Scherer 2019-03-31 18:35:39 +02:00
parent 7710820d18
commit f4f957d00b
7 changed files with 43 additions and 35 deletions

View file

@ -2357,7 +2357,7 @@ impl<'tcx> AdtDef {
#[inline] #[inline]
pub fn eval_explicit_discr(&self, tcx: TyCtxt<'tcx>, expr_did: DefId) -> Option<Discr<'tcx>> { pub fn eval_explicit_discr(&self, tcx: TyCtxt<'tcx>, expr_did: DefId) -> Option<Discr<'tcx>> {
let param_env = ParamEnv::empty(); let param_env = tcx.param_env(expr_did);
let repr_type = self.repr.discr_type(); let repr_type = self.repr.discr_type();
let substs = InternalSubsts::identity_for_item(tcx.global_tcx(), expr_did); let substs = InternalSubsts::identity_for_item(tcx.global_tcx(), expr_did);
let instance = ty::Instance::new(expr_did, substs); let instance = ty::Instance::new(expr_did, substs);
@ -2368,7 +2368,7 @@ impl<'tcx> AdtDef {
match tcx.const_eval(param_env.and(cid)) { match tcx.const_eval(param_env.and(cid)) {
Ok(val) => { Ok(val) => {
// FIXME: Find the right type and use it instead of `val.ty` here // 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); trace!("discriminants: {} ({:?})", b, repr_type);
Some(Discr { Some(Discr {
val: b, val: b,

View file

@ -2294,21 +2294,25 @@ impl<'tcx> Const<'tcx> {
pub fn try_eval_bits( pub fn try_eval_bits(
&self, &self,
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
ty: ParamEnvAnd<'tcx, Ty<'tcx>>, param_env: ParamEnv<'tcx>,
ty: Ty<'tcx>,
) -> Option<u128> { ) -> Option<u128> {
assert_eq!(self.ty, ty.value); assert_eq!(self.ty, ty);
let size = tcx.layout_of(ty).ok()?.size; let size = tcx.layout_of(param_env.with_reveal_all().and(ty)).ok()?.size;
match self.val { match self.val {
// FIXME(const_generics): this doesn't work right now, // FIXME(const_generics): this doesn't work right now,
// because it tries to relate an `Infer` to a `Param`. // because it tries to relate an `Infer` to a `Param`.
ConstValue::Unevaluated(did, substs) => { ConstValue::Unevaluated(did, substs) => {
let substs = tcx.lift_to_global(&substs).unwrap(); // if `substs` has no unresolved components, use and empty param_env
let instance = ty::Instance::resolve(tcx, ty.param_env, did, substs)?; 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 { let gid = GlobalId {
instance, instance,
promoted: None, 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) evaluated.val.try_to_bits(size)
}, },
// FIXME(const_generics): try to evaluate generic consts with a given param env? // FIXME(const_generics): try to evaluate generic consts with a given param env?
@ -2319,7 +2323,7 @@ impl<'tcx> Const<'tcx> {
#[inline] #[inline]
pub fn try_eval_bool(&self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Option<bool> { pub fn try_eval_bool(&self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Option<bool> {
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), 0 => Some(false),
1 => Some(true), 1 => Some(true),
_ => None, _ => None,
@ -2328,18 +2332,18 @@ impl<'tcx> Const<'tcx> {
#[inline] #[inline]
pub fn try_eval_usize(&self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Option<u64> { pub fn try_eval_usize(&self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Option<u64> {
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] #[inline]
pub fn eval_bits(&self, tcx: TyCtxt<'tcx>, ty: ParamEnvAnd<'tcx, Ty<'tcx>>) -> u128 { pub fn eval_bits(&self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ty: Ty<'tcx>) -> u128 {
self.try_eval_bits(tcx, ty).unwrap_or_else(|| self.try_eval_bits(tcx, param_env, ty).unwrap_or_else(||
bug!("expected bits of {:#?}, got {:#?}", ty, self)) bug!("expected bits of {:#?}, got {:#?}", ty, self))
} }
#[inline] #[inline]
pub fn eval_usize(&self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> 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 self.eval_bits(tcx, param_env, tcx.types.usize) as u64
} }
} }

View file

@ -512,7 +512,7 @@ impl Printer<'tcx> for SymbolMangler<'tcx> {
} }
self = ct.ty.print(self)?; 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); let _ = write!(self.out, "{:x}_", bits);
} else { } else {
// NOTE(eddyb) despite having the path, we need to // NOTE(eddyb) despite having the path, we need to

View file

@ -112,7 +112,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
indices.entry(value) indices.entry(value)
.or_insert_with(|| { .or_insert_with(|| {
options.push(value.eval_bits( 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 options.len() - 1
}); });
@ -655,10 +655,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
use rustc::hir::RangeEnd::*; use rustc::hir::RangeEnd::*;
let tcx = self.hir.tcx(); 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 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, 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) { match (test.end, pat.end, lo, hi) {
// pat < test // pat < test
@ -775,8 +774,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
let tcx = self.hir.tcx(); let tcx = self.hir.tcx();
let a = compare_const_vals(tcx, range.lo, value, 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.and(range.ty))?; let b = compare_const_vals(tcx, value, range.hi, self.hir.param_env, range.ty)?;
match (b, range.end) { match (b, range.end) {
(Less, _) | (Less, _) |

View file

@ -860,7 +860,7 @@ impl<'tcx> IntRange<'tcx> {
} }
ConstantValue(val) if is_integral(val.ty) => { ConstantValue(val) if is_integral(val.ty) => {
let ty = 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 bias = IntRange::signed_bias(tcx, ty);
let val = val ^ bias; let val = val ^ bias;
Some(IntRange { range: val..=val, ty }) Some(IntRange { range: val..=val, ty })
@ -881,8 +881,8 @@ impl<'tcx> IntRange<'tcx> {
match pat.kind { match pat.kind {
box PatternKind::Constant { value } => break ConstantValue(value), box PatternKind::Constant { value } => break ConstantValue(value),
box PatternKind::Range(PatternRange { lo, hi, ty, end }) => break ConstantRange( box PatternKind::Range(PatternRange { lo, hi, ty, end }) => break ConstantRange(
lo.eval_bits(tcx, param_env.and(ty)), lo.eval_bits(tcx, param_env, ty),
hi.eval_bits(tcx, param_env.and(ty)), hi.eval_bits(tcx, param_env, ty),
ty, ty,
end, end,
), ),
@ -1341,8 +1341,8 @@ fn pat_constructors<'tcx>(cx: &mut MatchCheckCtxt<'_, 'tcx>,
PatternKind::Constant { value } => Some(vec![ConstantValue(value)]), PatternKind::Constant { value } => Some(vec![ConstantValue(value)]),
PatternKind::Range(PatternRange { lo, hi, ty, end }) => PatternKind::Range(PatternRange { lo, hi, ty, end }) =>
Some(vec![ConstantRange( Some(vec![ConstantRange(
lo.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.and(ty)), hi.eval_bits(cx.tcx, cx.param_env, ty),
ty, ty,
end, end,
)]), )]),
@ -1480,7 +1480,7 @@ fn slice_pat_covered_by_const<'tcx>(
{ {
match pat.kind { match pat.kind {
box PatternKind::Constant { value } => { 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); assert_eq!(b as u8 as u128, b);
if b as u8 != *ch { if b as u8 != *ch {
return Ok(false); return Ok(false);
@ -1660,9 +1660,9 @@ fn constructor_covered_by_range<'tcx>(
_ => bug!("`constructor_covered_by_range` called with {:?}", pat), _ => bug!("`constructor_covered_by_range` called with {:?}", pat),
}; };
trace!("constructor_covered_by_range {:#?}, {:#?}, {:#?}, {}", ctor, from, to, ty); 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); .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 { macro_rules! some_or_ok {
($e:expr) => { ($e:expr) => {
match $e { match $e {

View file

@ -446,7 +446,8 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
self.tcx, self.tcx,
lo, lo,
hi, hi,
self.param_env.and(ty), self.param_env,
ty,
); );
match (end, cmp) { match (end, cmp) {
(RangeEnd::Excluded, Some(Ordering::Less)) => (RangeEnd::Excluded, Some(Ordering::Less)) =>
@ -1452,7 +1453,8 @@ pub fn compare_const_vals<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
a: &'tcx ty::Const<'tcx>, a: &'tcx ty::Const<'tcx>,
b: &'tcx ty::Const<'tcx>, b: &'tcx ty::Const<'tcx>,
ty: ty::ParamEnvAnd<'tcx, Ty<'tcx>>, param_env: ty::ParamEnv<'tcx>,
ty: Ty<'tcx>,
) -> Option<Ordering> { ) -> Option<Ordering> {
trace!("compare_const_vals: {:?}, {:?}", a, b); trace!("compare_const_vals: {:?}, {:?}", a, b);
@ -1467,13 +1469,16 @@ pub fn compare_const_vals<'tcx>(
let fallback = || from_bool(a == b); let fallback = || from_bool(a == b);
// Use the fallback if any type differs // 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(); 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; use ::rustc_apfloat::Float;
return match ty.value.sty { return match ty.sty {
ty::Float(ast::FloatTy::F32) => { ty::Float(ast::FloatTy::F32) => {
let l = ::rustc_apfloat::ieee::Single::from_bits(a); let l = ::rustc_apfloat::ieee::Single::from_bits(a);
let r = ::rustc_apfloat::ieee::Single::from_bits(b); 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) { match (a.val, b.val) {
( (
ConstValue::Slice { data: alloc_a, start: offset_a, end: end_a }, ConstValue::Slice { data: alloc_a, start: offset_a, end: end_a },

View file

@ -27,7 +27,7 @@ impl MirPass for SimplifyBranches {
TerminatorKind::SwitchInt { TerminatorKind::SwitchInt {
discr: Operand::Constant(ref c), switch_ty, ref values, ref targets, .. 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 { if let Some(constant) = constant {
let (otherwise, targets) = targets.split_last().unwrap(); let (otherwise, targets) = targets.split_last().unwrap();
let mut ret = TerminatorKind::Goto { target: *otherwise }; let mut ret = TerminatorKind::Goto { target: *otherwise };