Skip to content

Commit

Permalink
Auto merge of #59369 - oli-obk:unwrap_usICE, r=eddyb,nikomatsakis
Browse files Browse the repository at this point in the history
`unwrap_usize` should at least try to evaluate the underlying constant

r? @eddyb

fixes #59016

I know that I'm still using `ParamEnv` wrongly, but that's a preexisting issue not amplified by this PR.
  • Loading branch information
bors committed Aug 5, 2019
2 parents f6ecdc2 + bd57498 commit c471519
Show file tree
Hide file tree
Showing 53 changed files with 298 additions and 142 deletions.
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

0 comments on commit c471519

Please sign in to comment.