rustc_const_eval: keep track of the appropriate ParamEnv.
This commit is contained in:
parent
4c900c5248
commit
60cf5428b3
15 changed files with 107 additions and 64 deletions
|
|
@ -14,7 +14,8 @@ pub use rustc_const_math::ConstInt;
|
|||
use hir;
|
||||
use hir::def::Def;
|
||||
use hir::def_id::DefId;
|
||||
use ty::{TyCtxt, layout};
|
||||
use traits::Reveal;
|
||||
use ty::{self, TyCtxt, layout};
|
||||
use ty::subst::Substs;
|
||||
use util::common::ErrorReported;
|
||||
use rustc_const_math::*;
|
||||
|
|
@ -229,8 +230,9 @@ pub fn eval_length(tcx: TyCtxt,
|
|||
{
|
||||
let count_expr = &tcx.hir.body(count).value;
|
||||
let count_def_id = tcx.hir.body_owner_def_id(count);
|
||||
let param_env = ty::ParamEnv::empty(Reveal::UserFacing);
|
||||
let substs = Substs::identity_for_item(tcx.global_tcx(), count_def_id);
|
||||
match tcx.at(count_expr.span).const_eval((count_def_id, substs)) {
|
||||
match tcx.at(count_expr.span).const_eval(param_env.and((count_def_id, substs))) {
|
||||
Ok(Integral(Usize(count))) => {
|
||||
let val = count.as_u64(tcx.sess.target.uint_type);
|
||||
assert_eq!(val as usize as u64, val);
|
||||
|
|
|
|||
|
|
@ -372,8 +372,8 @@ impl<'tcx> QueryDescription for queries::reachable_set<'tcx> {
|
|||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::const_eval<'tcx> {
|
||||
fn describe(tcx: TyCtxt, (def_id, _): (DefId, &'tcx Substs<'tcx>)) -> String {
|
||||
format!("const-evaluating `{}`", tcx.item_path_str(def_id))
|
||||
fn describe(tcx: TyCtxt, key: ty::ParamEnvAnd<'tcx, (DefId, &'tcx Substs<'tcx>)>) -> String {
|
||||
format!("const-evaluating `{}`", tcx.item_path_str(key.value.0))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -935,7 +935,7 @@ define_maps! { <'tcx>
|
|||
|
||||
/// Results of evaluating const items or constants embedded in
|
||||
/// other items (such as enum variant explicit discriminants).
|
||||
[] const_eval: const_eval_dep_node((DefId, &'tcx Substs<'tcx>))
|
||||
[] const_eval: const_eval_dep_node(ty::ParamEnvAnd<'tcx, (DefId, &'tcx Substs<'tcx>)>)
|
||||
-> const_val::EvalResult<'tcx>,
|
||||
|
||||
/// Performs the privacy check and computes "access levels".
|
||||
|
|
@ -1032,8 +1032,9 @@ fn typeck_item_bodies_dep_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> {
|
|||
DepConstructor::TypeckBodiesKrate
|
||||
}
|
||||
|
||||
fn const_eval_dep_node<'tcx>((def_id, substs): (DefId, &'tcx Substs<'tcx>))
|
||||
fn const_eval_dep_node<'tcx>(key: ty::ParamEnvAnd<'tcx, (DefId, &'tcx Substs<'tcx>)>)
|
||||
-> DepConstructor<'tcx> {
|
||||
let (def_id, substs) = key.value;
|
||||
DepConstructor::ConstEval { def_id, substs }
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1582,6 +1582,7 @@ impl<'a, 'gcx, 'tcx> AdtDef {
|
|||
#[inline]
|
||||
pub fn discriminants(&'a self, tcx: TyCtxt<'a, 'gcx, 'tcx>)
|
||||
-> impl Iterator<Item=ConstInt> + 'a {
|
||||
let param_env = ParamEnv::empty(traits::Reveal::UserFacing);
|
||||
let repr_type = self.repr.discr_type();
|
||||
let initial = repr_type.initial_discriminant(tcx.global_tcx());
|
||||
let mut prev_discr = None::<ConstInt>;
|
||||
|
|
@ -1589,7 +1590,7 @@ impl<'a, 'gcx, 'tcx> AdtDef {
|
|||
let mut discr = prev_discr.map_or(initial, |d| d.wrap_incr());
|
||||
if let VariantDiscr::Explicit(expr_did) = v.discr {
|
||||
let substs = Substs::identity_for_item(tcx.global_tcx(), expr_did);
|
||||
match tcx.const_eval((expr_did, substs)) {
|
||||
match tcx.const_eval(param_env.and((expr_did, substs))) {
|
||||
Ok(ConstVal::Integral(v)) => {
|
||||
discr = v;
|
||||
}
|
||||
|
|
@ -1617,6 +1618,7 @@ impl<'a, 'gcx, 'tcx> AdtDef {
|
|||
tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||
variant_index: usize)
|
||||
-> ConstInt {
|
||||
let param_env = ParamEnv::empty(traits::Reveal::UserFacing);
|
||||
let repr_type = self.repr.discr_type();
|
||||
let mut explicit_value = repr_type.initial_discriminant(tcx.global_tcx());
|
||||
let mut explicit_index = variant_index;
|
||||
|
|
@ -1628,7 +1630,7 @@ impl<'a, 'gcx, 'tcx> AdtDef {
|
|||
}
|
||||
ty::VariantDiscr::Explicit(expr_did) => {
|
||||
let substs = Substs::identity_for_item(tcx.global_tcx(), expr_did);
|
||||
match tcx.const_eval((expr_did, substs)) {
|
||||
match tcx.const_eval(param_env.and((expr_did, substs))) {
|
||||
Ok(ConstVal::Integral(v)) => {
|
||||
explicit_value = v;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -398,7 +398,7 @@ macro_rules! CopyImpls {
|
|||
}
|
||||
}
|
||||
|
||||
CopyImpls! { (), hir::Unsafety, abi::Abi }
|
||||
CopyImpls! { (), hir::Unsafety, abi::Abi, hir::def_id::DefId }
|
||||
|
||||
impl<'tcx, T:TypeFoldable<'tcx>, U:TypeFoldable<'tcx>> TypeFoldable<'tcx> for (T, U) {
|
||||
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> (T, U) {
|
||||
|
|
|
|||
|
|
@ -165,8 +165,9 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> {
|
|||
|
||||
let inlined_arms : Vec<(Vec<_>, _)> = arms.iter().map(|arm| (
|
||||
arm.pats.iter().map(|pat| {
|
||||
let substs = self.identity_substs;
|
||||
let mut patcx = PatternContext::new(self.tcx, self.tables, substs);
|
||||
let mut patcx = PatternContext::new(self.tcx,
|
||||
self.param_env.and(self.identity_substs),
|
||||
self.tables);
|
||||
let pattern = expand_pattern(cx, patcx.lower_pattern(&pat));
|
||||
if !patcx.errors.is_empty() {
|
||||
patcx.report_inlining_errors(pat.span);
|
||||
|
|
@ -233,8 +234,9 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> {
|
|||
fn check_irrefutable(&self, pat: &Pat, origin: &str) {
|
||||
let module = self.tcx.hir.get_module_parent(pat.id);
|
||||
MatchCheckCtxt::create_and_enter(self.tcx, module, |ref mut cx| {
|
||||
let substs = self.identity_substs;
|
||||
let mut patcx = PatternContext::new(self.tcx, self.tables, substs);
|
||||
let mut patcx = PatternContext::new(self.tcx,
|
||||
self.param_env.and(self.identity_substs),
|
||||
self.tables);
|
||||
let pattern = patcx.lower_pattern(pat);
|
||||
let pattern_ty = pattern.ty;
|
||||
let pats : Matrix = vec![vec![
|
||||
|
|
|
|||
|
|
@ -21,7 +21,6 @@ use rustc::ty::{self, Ty, TyCtxt};
|
|||
use rustc::ty::maps::Providers;
|
||||
use rustc::ty::util::IntTypeExt;
|
||||
use rustc::ty::subst::{Substs, Subst};
|
||||
use rustc::traits::Reveal;
|
||||
use rustc::util::common::ErrorReported;
|
||||
use rustc::util::nodemap::DefIdMap;
|
||||
|
||||
|
|
@ -49,24 +48,21 @@ macro_rules! math {
|
|||
}
|
||||
}
|
||||
|
||||
/// * `def_id` is the id of the constant.
|
||||
/// * `substs` is the monomorphized substitutions for the expression.
|
||||
///
|
||||
/// `substs` is optional and is used for associated constants.
|
||||
/// This generally happens in late/trans const evaluation.
|
||||
/// * `DefId` is the id of the constant.
|
||||
/// * `Substs` is the monomorphized substitutions for the expression.
|
||||
pub fn lookup_const_by_id<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
def_id: DefId,
|
||||
substs: &'tcx Substs<'tcx>)
|
||||
key: ty::ParamEnvAnd<'tcx, (DefId, &'tcx Substs<'tcx>)>)
|
||||
-> Option<(DefId, &'tcx Substs<'tcx>)> {
|
||||
let (def_id, _) = key.value;
|
||||
if let Some(node_id) = tcx.hir.as_local_node_id(def_id) {
|
||||
match tcx.hir.find(node_id) {
|
||||
Some(hir_map::NodeTraitItem(_)) => {
|
||||
// If we have a trait item and the substitutions for it,
|
||||
// `resolve_trait_associated_const` will select an impl
|
||||
// or the default.
|
||||
resolve_trait_associated_const(tcx, def_id, substs)
|
||||
resolve_trait_associated_const(tcx, key)
|
||||
}
|
||||
_ => Some((def_id, substs))
|
||||
_ => Some(key.value)
|
||||
}
|
||||
} else {
|
||||
match tcx.describe_def(def_id) {
|
||||
|
|
@ -76,12 +72,12 @@ pub fn lookup_const_by_id<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
// trait-associated const if the caller gives us the
|
||||
// substitutions for the reference to it.
|
||||
if tcx.trait_of_item(def_id).is_some() {
|
||||
resolve_trait_associated_const(tcx, def_id, substs)
|
||||
resolve_trait_associated_const(tcx, key)
|
||||
} else {
|
||||
Some((def_id, substs))
|
||||
Some(key.value)
|
||||
}
|
||||
}
|
||||
_ => Some((def_id, substs))
|
||||
_ => Some(key.value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -89,18 +85,21 @@ pub fn lookup_const_by_id<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
pub struct ConstContext<'a, 'tcx: 'a> {
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
tables: &'a ty::TypeckTables<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
substs: &'tcx Substs<'tcx>,
|
||||
fn_args: Option<DefIdMap<ConstVal<'tcx>>>
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> ConstContext<'a, 'tcx> {
|
||||
pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
tables: &'a ty::TypeckTables<'tcx>,
|
||||
substs: &'tcx Substs<'tcx>) -> Self {
|
||||
param_env_and_substs: ty::ParamEnvAnd<'tcx, &'tcx Substs<'tcx>>,
|
||||
tables: &'a ty::TypeckTables<'tcx>)
|
||||
-> Self {
|
||||
ConstContext {
|
||||
tcx,
|
||||
param_env: param_env_and_substs.param_env,
|
||||
tables,
|
||||
substs,
|
||||
substs: param_env_and_substs.value,
|
||||
fn_args: None
|
||||
}
|
||||
}
|
||||
|
|
@ -279,7 +278,7 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
|
|||
match cx.tables.qpath_def(qpath, e.id) {
|
||||
Def::Const(def_id) |
|
||||
Def::AssociatedConst(def_id) => {
|
||||
match tcx.at(e.span).const_eval((def_id, substs)) {
|
||||
match tcx.at(e.span).const_eval(cx.param_env.and((def_id, substs))) {
|
||||
Ok(val) => val,
|
||||
Err(ConstEvalErr { kind: TypeckError, .. }) => {
|
||||
signal!(e, TypeckError);
|
||||
|
|
@ -323,10 +322,9 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
|
|||
|
||||
if tcx.fn_sig(def_id).abi() == Abi::RustIntrinsic {
|
||||
let layout_of = |ty: Ty<'tcx>| {
|
||||
ty.layout(tcx, ty::ParamEnv::empty(traits::Reveal::All))
|
||||
.map_err(|err| {
|
||||
ConstEvalErr { span: e.span, kind: LayoutError(err) }
|
||||
})
|
||||
ty.layout(tcx, cx.param_env).map_err(|err| {
|
||||
ConstEvalErr { span: e.span, kind: LayoutError(err) }
|
||||
})
|
||||
};
|
||||
match &tcx.item_name(def_id).as_str()[..] {
|
||||
"size_of" => {
|
||||
|
|
@ -377,7 +375,8 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
|
|||
}
|
||||
debug!("const call({:?})", call_args);
|
||||
let callee_cx = ConstContext {
|
||||
tcx: tcx,
|
||||
tcx,
|
||||
param_env: cx.param_env,
|
||||
tables: tcx.typeck_tables_of(def_id),
|
||||
substs: substs,
|
||||
fn_args: Some(call_args)
|
||||
|
|
@ -477,9 +476,10 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
|
|||
}
|
||||
|
||||
fn resolve_trait_associated_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
def_id: DefId,
|
||||
substs: &'tcx Substs<'tcx>)
|
||||
key: ty::ParamEnvAnd<'tcx, (DefId, &'tcx Substs<'tcx>)>)
|
||||
-> Option<(DefId, &'tcx Substs<'tcx>)> {
|
||||
let param_env = key.param_env;
|
||||
let (def_id, substs) = key.value;
|
||||
let trait_item = tcx.associated_item(def_id);
|
||||
let trait_id = trait_item.container.id();
|
||||
let trait_ref = ty::Binder(ty::TraitRef::new(trait_id, substs));
|
||||
|
|
@ -487,7 +487,6 @@ fn resolve_trait_associated_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
trait_ref);
|
||||
|
||||
tcx.infer_ctxt().enter(|infcx| {
|
||||
let param_env = ty::ParamEnv::empty(Reveal::UserFacing);
|
||||
let mut selcx = traits::SelectionContext::new(&infcx);
|
||||
let obligation = traits::Obligation::new(traits::ObligationCause::dummy(),
|
||||
param_env,
|
||||
|
|
@ -506,10 +505,8 @@ fn resolve_trait_associated_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
};
|
||||
|
||||
// NOTE: this code does not currently account for specialization, but when
|
||||
// it does so, it should hook into the Reveal to determine when the
|
||||
// constant should resolve; this will also require plumbing through to this
|
||||
// function whether we are in "trans mode" to pick the right Reveal
|
||||
// when constructing the inference context above.
|
||||
// it does so, it should hook into the param_env.reveal to determine when the
|
||||
// constant should resolve.
|
||||
match selection {
|
||||
traits::VtableImpl(ref impl_data) => {
|
||||
let name = trait_item.name;
|
||||
|
|
@ -524,15 +521,16 @@ fn resolve_trait_associated_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
}
|
||||
None => {
|
||||
if trait_item.defaultness.has_value() {
|
||||
Some((def_id, substs))
|
||||
Some(key.value)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
traits::VtableParam(_) => None,
|
||||
_ => {
|
||||
bug!("resolve_trait_associated_const: unexpected vtable type")
|
||||
bug!("resolve_trait_associated_const: unexpected vtable type {:?}", selection)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
@ -761,13 +759,13 @@ pub fn provide(providers: &mut Providers) {
|
|||
}
|
||||
|
||||
fn const_eval<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
(def_id, substs): (DefId, &'tcx Substs<'tcx>))
|
||||
key: ty::ParamEnvAnd<'tcx, (DefId, &'tcx Substs<'tcx>)>)
|
||||
-> EvalResult<'tcx> {
|
||||
let (def_id, substs) = if let Some(resolved) = lookup_const_by_id(tcx, def_id, substs) {
|
||||
let (def_id, substs) = if let Some(resolved) = lookup_const_by_id(tcx, key) {
|
||||
resolved
|
||||
} else {
|
||||
return Err(ConstEvalErr {
|
||||
span: tcx.def_span(def_id),
|
||||
span: tcx.def_span(key.value.0),
|
||||
kind: TypeckError
|
||||
});
|
||||
};
|
||||
|
|
@ -779,5 +777,5 @@ fn const_eval<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
} else {
|
||||
tcx.sess.cstore.item_body(tcx, def_id)
|
||||
};
|
||||
ConstContext::new(tcx, tables, substs).eval(&body.value)
|
||||
ConstContext::new(tcx, key.param_env.and(substs), tables).eval(&body.value)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -268,6 +268,7 @@ impl<'tcx> fmt::Display for Pattern<'tcx> {
|
|||
|
||||
pub struct PatternContext<'a, 'tcx: 'a> {
|
||||
pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
pub param_env: ty::ParamEnv<'tcx>,
|
||||
pub tables: &'a ty::TypeckTables<'tcx>,
|
||||
pub substs: &'tcx Substs<'tcx>,
|
||||
pub errors: Vec<PatternError<'tcx>>,
|
||||
|
|
@ -275,10 +276,10 @@ pub struct PatternContext<'a, 'tcx: 'a> {
|
|||
|
||||
impl<'a, 'tcx> Pattern<'tcx> {
|
||||
pub fn from_hir(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
param_env_and_substs: ty::ParamEnvAnd<'tcx, &'tcx Substs<'tcx>>,
|
||||
tables: &'a ty::TypeckTables<'tcx>,
|
||||
substs: &'tcx Substs<'tcx>,
|
||||
pat: &hir::Pat) -> Self {
|
||||
let mut pcx = PatternContext::new(tcx, tables, substs);
|
||||
let mut pcx = PatternContext::new(tcx, param_env_and_substs, tables);
|
||||
let result = pcx.lower_pattern(pat);
|
||||
if !pcx.errors.is_empty() {
|
||||
span_bug!(pat.span, "encountered errors lowering pattern: {:?}", pcx.errors)
|
||||
|
|
@ -290,9 +291,15 @@ impl<'a, 'tcx> Pattern<'tcx> {
|
|||
|
||||
impl<'a, 'tcx> PatternContext<'a, 'tcx> {
|
||||
pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
tables: &'a ty::TypeckTables<'tcx>,
|
||||
substs: &'tcx Substs<'tcx>) -> Self {
|
||||
PatternContext { tcx, tables, substs, errors: vec![] }
|
||||
param_env_and_substs: ty::ParamEnvAnd<'tcx, &'tcx Substs<'tcx>>,
|
||||
tables: &'a ty::TypeckTables<'tcx>) -> Self {
|
||||
PatternContext {
|
||||
tcx,
|
||||
param_env: param_env_and_substs.param_env,
|
||||
tables,
|
||||
substs: param_env_and_substs.value,
|
||||
errors: vec![]
|
||||
}
|
||||
}
|
||||
|
||||
pub fn lower_pattern(&mut self, pat: &hir::Pat) -> Pattern<'tcx> {
|
||||
|
|
@ -588,7 +595,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
|
|||
let kind = match def {
|
||||
Def::Const(def_id) | Def::AssociatedConst(def_id) => {
|
||||
let substs = self.tables.node_substs(id);
|
||||
match eval::lookup_const_by_id(self.tcx, def_id, substs) {
|
||||
match eval::lookup_const_by_id(self.tcx, self.param_env.and((def_id, substs))) {
|
||||
Some((def_id, substs)) => {
|
||||
// Enter the inlined constant's tables&substs temporarily.
|
||||
let old_tables = self.tables;
|
||||
|
|
@ -622,7 +629,9 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
|
|||
}
|
||||
|
||||
fn lower_lit(&mut self, expr: &hir::Expr) -> PatternKind<'tcx> {
|
||||
let const_cx = eval::ConstContext::new(self.tcx, self.tables, self.substs);
|
||||
let const_cx = eval::ConstContext::new(self.tcx,
|
||||
self.param_env.and(self.substs),
|
||||
self.tables);
|
||||
match const_cx.eval(expr) {
|
||||
Ok(value) => {
|
||||
if let ConstVal::Variant(def_id) = value {
|
||||
|
|
|
|||
|
|
@ -113,7 +113,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits {
|
|||
let parent_item = cx.tcx.hir.get_parent(e.id);
|
||||
let parent_def_id = cx.tcx.hir.local_def_id(parent_item);
|
||||
let substs = Substs::identity_for_item(cx.tcx, parent_def_id);
|
||||
let const_cx = ConstContext::new(cx.tcx, cx.tables, substs);
|
||||
let const_cx = ConstContext::new(cx.tcx,
|
||||
cx.param_env.and(substs),
|
||||
cx.tables);
|
||||
match const_cx.eval(&r) {
|
||||
Ok(ConstVal::Integral(i)) => {
|
||||
i.is_negative() ||
|
||||
|
|
|
|||
|
|
@ -514,8 +514,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||
|
||||
if let Some(pattern) = pattern {
|
||||
let pattern = Pattern::from_hir(self.hir.tcx().global_tcx(),
|
||||
self.hir.param_env.and(self.hir.identity_substs),
|
||||
self.hir.tables(),
|
||||
self.hir.identity_substs,
|
||||
pattern);
|
||||
scope = self.declare_bindings(scope, ast_body.span, &pattern);
|
||||
unpack!(block = self.lvalue_into_pattern(block, pattern, &lvalue));
|
||||
|
|
|
|||
|
|
@ -71,8 +71,8 @@ fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
|||
});
|
||||
|
||||
let pattern = Pattern::from_hir(cx.tcx.global_tcx(),
|
||||
cx.param_env.and(cx.identity_substs),
|
||||
cx.tables(),
|
||||
cx.identity_substs,
|
||||
&local.pat);
|
||||
result.push(StmtRef::Mirror(Box::new(Stmt {
|
||||
span: stmt.span,
|
||||
|
|
|
|||
|
|
@ -467,7 +467,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
|||
let c = &cx.tcx.hir.body(count).value;
|
||||
let def_id = cx.tcx.hir.body_owner_def_id(count);
|
||||
let substs = Substs::identity_for_item(cx.tcx.global_tcx(), def_id);
|
||||
let count = match cx.tcx.at(c.span).const_eval((def_id, substs)) {
|
||||
let count = match cx.tcx.at(c.span).const_eval(cx.param_env.and((def_id, substs))) {
|
||||
Ok(ConstVal::Integral(ConstInt::Usize(u))) => u,
|
||||
Ok(other) => bug!("constant evaluation of repeat count yielded {:?}", other),
|
||||
Err(s) => cx.fatal_const_eval_err(&s, c.span, "expression")
|
||||
|
|
@ -605,7 +605,10 @@ fn to_borrow_kind(m: hir::Mutability) -> BorrowKind {
|
|||
fn convert_arm<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, arm: &'tcx hir::Arm) -> Arm<'tcx> {
|
||||
Arm {
|
||||
patterns: arm.pats.iter().map(|p| {
|
||||
Pattern::from_hir(cx.tcx.global_tcx(), cx.tables(), cx.identity_substs, p)
|
||||
Pattern::from_hir(cx.tcx.global_tcx(),
|
||||
cx.param_env.and(cx.identity_substs),
|
||||
cx.tables(),
|
||||
p)
|
||||
}).collect(),
|
||||
guard: arm.guard.to_ref(),
|
||||
body: arm.body.to_ref(),
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ pub struct Cx<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
|
|||
tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
|
||||
|
||||
pub param_env: ty::ParamEnv<'tcx>,
|
||||
pub param_env: ty::ParamEnv<'gcx>,
|
||||
|
||||
/// Identity `Substs` for use with const-evaluation.
|
||||
pub identity_substs: &'gcx Substs<'gcx>,
|
||||
|
|
@ -135,7 +135,10 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
|
|||
|
||||
pub fn const_eval_literal(&mut self, e: &hir::Expr) -> Literal<'tcx> {
|
||||
let tcx = self.tcx.global_tcx();
|
||||
match ConstContext::new(tcx, self.tables(), self.identity_substs).eval(e) {
|
||||
let const_cx = ConstContext::new(tcx,
|
||||
self.param_env.and(self.identity_substs),
|
||||
self.tables());
|
||||
match const_cx.eval(e) {
|
||||
Ok(value) => Literal::Value { value: value },
|
||||
Err(s) => self.fatal_const_eval_err(&s, e.span, "expression")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ struct CheckCrateVisitor<'a, 'tcx: 'a> {
|
|||
|
||||
impl<'a, 'gcx> CheckCrateVisitor<'a, 'gcx> {
|
||||
fn const_cx(&self) -> ConstContext<'a, 'gcx> {
|
||||
ConstContext::new(self.tcx, self.tables, self.identity_substs)
|
||||
ConstContext::new(self.tcx, self.param_env.and(self.identity_substs), self.tables)
|
||||
}
|
||||
|
||||
fn check_const_eval(&self, expr: &'gcx hir::Expr) {
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@ use constrained_type_params as ctp;
|
|||
use middle::lang_items::SizedTraitLangItem;
|
||||
use middle::const_val::ConstVal;
|
||||
use middle::resolve_lifetime as rl;
|
||||
use rustc::traits::Reveal;
|
||||
use rustc::ty::subst::Substs;
|
||||
use rustc::ty::{ToPredicate, ReprOptions};
|
||||
use rustc::ty::{self, AdtKind, ToPolyTraitRef, Ty, TyCtxt};
|
||||
|
|
@ -550,6 +551,7 @@ fn convert_variant_ctor<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
fn convert_enum_variant_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
def_id: DefId,
|
||||
variants: &[hir::Variant]) {
|
||||
let param_env = ty::ParamEnv::empty(Reveal::UserFacing);
|
||||
let def = tcx.adt_def(def_id);
|
||||
let repr_type = def.repr.discr_type();
|
||||
let initial = repr_type.initial_discriminant(tcx);
|
||||
|
|
@ -561,7 +563,7 @@ fn convert_enum_variant_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
prev_discr = Some(if let Some(e) = variant.node.disr_expr {
|
||||
let expr_did = tcx.hir.local_def_id(e.node_id);
|
||||
let substs = Substs::identity_for_item(tcx, expr_did);
|
||||
let result = tcx.at(variant.span).const_eval((expr_did, substs));
|
||||
let result = tcx.at(variant.span).const_eval(param_env.and((expr_did, substs)));
|
||||
|
||||
// enum variant evaluation happens before the global constant check
|
||||
// so we need to report the real error
|
||||
|
|
|
|||
19
src/test/run-pass/issue-43357.rs
Normal file
19
src/test/run-pass/issue-43357.rs
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
trait Trait {
|
||||
type Output;
|
||||
}
|
||||
|
||||
fn f<T: Trait>() {
|
||||
std::mem::size_of::<T::Output>();
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
Loading…
Add table
Add a link
Reference in a new issue