Skip to content

unwrap_usize should at least try to evaluate the underlying constant #59369

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Aug 5, 2019
4 changes: 4 additions & 0 deletions src/librustc/infer/combine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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"
Expand Down
2 changes: 2 additions & 0 deletions src/librustc/infer/equate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
2 changes: 2 additions & 0 deletions src/librustc/infer/glb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<T: Relate<'tcx>>(&mut self,
Expand Down
2 changes: 2 additions & 0 deletions src/librustc/infer/lub.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<T: Relate<'tcx>>(&mut self,
Expand Down
6 changes: 6 additions & 0 deletions src/librustc/infer/nll_relate/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}
Expand Down Expand Up @@ -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"
}
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/infer/outlives/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 3 additions & 0 deletions src/librustc/infer/sub.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<F,R>(&mut self, cause: Cause, f: F) -> R
Expand Down
2 changes: 2 additions & 0 deletions src/librustc/middle/expr_use_visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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,
Expand Down
9 changes: 7 additions & 2 deletions src/librustc/middle/mem_categorization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<hir::HirId, hir::Upvar>>,
pub region_scope_tree: &'a region::ScopeTree,
Expand Down Expand Up @@ -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>,
Expand All @@ -342,7 +344,8 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
region_scope_tree,
tables,
rvalue_promotable_map,
infcx: None
infcx: None,
param_env,
}
}
}
Expand All @@ -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>,
Expand All @@ -379,6 +383,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
tables,
rvalue_promotable_map,
infcx: Some(infcx),
param_env,
}
}

Expand Down Expand Up @@ -896,7 +901,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {

// Always promote `[T; 0]` (even when e.g., borrowed mutably).
let promotable = match expr_ty.sty {
ty::Array(_, len) if len.assert_usize(self.tcx) == Some(0) => true,
ty::Array(_, len) if len.try_eval_usize(self.tcx, self.param_env) == Some(0) => true,
_ => promotable,
};

Expand Down
5 changes: 3 additions & 2 deletions src/librustc/mir/tcx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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, |...| { ... })`
Expand All @@ -68,6 +68,7 @@ impl<'tcx> PlaceTy<'tcx> {
pub fn projection_ty_core<V, T>(
self,
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
elem: &ProjectionElem<V, T>,
mut handle_field: impl FnMut(&Self, &Field, &T) -> Ty<'tcx>,
) -> PlaceTy<'tcx>
Expand All @@ -90,7 +91,7 @@ impl<'tcx> PlaceTy<'tcx> {
ProjectionElem::Subslice { from, to } => {
PlaceTy::from_ty(match self.ty.sty {
ty::Array(inner, size) => {
let size = size.unwrap_usize(tcx);
let size = size.eval_usize(tcx, param_env);
let len = size - (from as u64) - (to as u64);
tcx.mk_array(inner, len)
}
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/traits/error_reporting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -417,7 +417,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
Some(format!("[{}]", self.tcx.type_of(def.did).to_string())),
));
let tcx = self.tcx;
if let Some(len) = len.assert_usize(tcx) {
if let Some(len) = len.try_eval_usize(tcx, ty::ParamEnv::empty()) {
flags.push((
sym::_Self,
Some(format!("[{}; {}]", self.tcx.type_of(def.did).to_string(), len)),
Expand Down
6 changes: 4 additions & 2 deletions src/librustc/traits/select.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand 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()
}

Expand Down
6 changes: 4 additions & 2 deletions src/librustc/ty/_match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<T: Relate<'tcx>>(&mut self,
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/ty/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ impl<'tcx> ty::TyS<'tcx> {
ty::Foreign(def_id) => format!("extern type `{}`", tcx.def_path_str(def_id)).into(),
ty::Array(_, n) => {
let n = tcx.lift_to_global(&n).unwrap();
match n.assert_usize(tcx) {
match n.try_eval_usize(tcx, ty::ParamEnv::empty()) {
Some(n) => format!("array of {} elements", n).into(),
None => "array".into(),
}
Expand Down
3 changes: 2 additions & 1 deletion src/librustc/ty/inhabitedness/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -190,7 +191,7 @@ impl<'tcx> TyS<'tcx> {
}))
}

Array(ty, len) => match len.assert_usize(tcx) {
Array(ty, len) => match len.try_eval_usize(tcx, ty::ParamEnv::empty()) {
// If the array is definitely non-empty, it's uninhabited if
// the type of its elements is uninhabited.
Some(n) if n != 0 => ty.uninhabited_from(tcx),
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/ty/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -594,7 +594,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
}
}

let count = count.assert_usize(tcx).ok_or(LayoutError::Unknown(ty))?;
let count = count.try_eval_usize(tcx, param_env).ok_or(LayoutError::Unknown(ty))?;
let element = self.layout_of(element)?;
let size = element.size.checked_mul(count, dl)
.ok_or(LayoutError::SizeOverflow(ty))?;
Expand Down
4 changes: 2 additions & 2 deletions src/librustc/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2357,7 +2357,7 @@ impl<'tcx> AdtDef {

#[inline]
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 substs = InternalSubsts::identity_for_item(tcx.global_tcx(), expr_did);
let instance = ty::Instance::new(expr_did, substs);
Expand All @@ -2368,7 +2368,7 @@ impl<'tcx> AdtDef {
match tcx.const_eval(param_env.and(cid)) {
Ok(val) => {
// FIXME: Find the right type and use it instead of `val.ty` here
if let Some(b) = val.assert_bits(tcx.global_tcx(), param_env.and(val.ty)) {
if let Some(b) = val.try_eval_bits(tcx.global_tcx(), param_env, val.ty) {
trace!("discriminants: {} ({:?})", b, repr_type);
Some(Discr {
val: b,
Expand Down
3 changes: 2 additions & 1 deletion src/librustc/ty/print/obsolete.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,8 @@ impl DefPathBasedNames<'tcx> {
ty::Array(inner_type, len) => {
output.push('[');
self.push_type_name(inner_type, output, debug);
write!(output, "; {}", len.unwrap_usize(self.tcx)).unwrap();
let len = len.eval_usize(self.tcx, ty::ParamEnv::reveal_all());
write!(output, "; {}", len).unwrap();
output.push(']');
}
ty::Slice(inner_type) => {
Expand Down
9 changes: 7 additions & 2 deletions src/librustc/ty/print/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -696,7 +696,12 @@ pub trait PrettyPrinter<'tcx>:
},
ty::Array(ty, sz) => {
p!(write("["), print(ty), write("; "));
if let Some(n) = sz.assert_usize(self.tcx()) {
if let ConstValue::Unevaluated(..) = sz.val {
// do not try to evalute unevaluated constants. If we are const evaluating an
// array length anon const, rustc will (with debug assertions) print the
// constant's path. Which will end up here again.
p!(write("_"));
} else if let Some(n) = sz.try_eval_usize(self.tcx(), ty::ParamEnv::empty()) {
p!(write("{}", n));
} else {
p!(write("_"));
Expand Down Expand Up @@ -915,7 +920,7 @@ pub trait PrettyPrinter<'tcx>:
if let ty::Ref(_, ref_ty, _) = ct.ty.sty {
let byte_str = match (ct.val, &ref_ty.sty) {
(ConstValue::Scalar(Scalar::Ptr(ptr)), ty::Array(t, n)) if *t == u8 => {
let n = n.unwrap_usize(self.tcx());
let n = n.eval_usize(self.tcx(), ty::ParamEnv::empty());
Some(self.tcx()
.alloc_map.lock()
.unwrap_memory(ptr.alloc_id)
Expand Down
6 changes: 5 additions & 1 deletion src/librustc/ty/relate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -466,7 +468,9 @@ pub fn super_relate_tys<R: TypeRelation<'tcx>>(
Err(err) => {
// Check whether the lengths are both concrete/known values,
// but are unequal, for better diagnostics.
match (sz_a.assert_usize(tcx), sz_b.assert_usize(tcx)) {
let sz_a = sz_a.try_eval_usize(tcx, relation.param_env());
let sz_b = sz_b.try_eval_usize(tcx, relation.param_env());
match (sz_a, sz_b) {
(Some(sz_a_val), Some(sz_b_val)) => {
Err(TypeError::FixedArraySize(
expected_found(relation, &sz_a_val, &sz_b_val)
Expand Down
Loading