Skip to content

Commit

Permalink
rustc: expose monomorphic const_eval through on-demand.
Browse files Browse the repository at this point in the history
  • Loading branch information
eddyb committed Apr 15, 2017
1 parent 8854164 commit 63064ec
Show file tree
Hide file tree
Showing 13 changed files with 61 additions and 55 deletions.
2 changes: 0 additions & 2 deletions src/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

37 changes: 36 additions & 1 deletion src/librustc/middle/const_val.rs
Expand Up @@ -11,9 +11,12 @@
use self::ConstVal::*;
pub use rustc_const_math::ConstInt;

use hir;
use hir::def::Def;
use hir::def_id::DefId;
use ty::TyCtxt;
use ty::{self, TyCtxt};
use ty::subst::Substs;
use util::common::ErrorReported;
use rustc_const_math::*;

use graphviz::IntoCow;
Expand Down Expand Up @@ -215,3 +218,35 @@ impl<'a, 'gcx, 'tcx> ConstEvalErr<'tcx> {
self.struct_error(tcx, primary_span, primary_kind).emit();
}
}

/// Returns the value of the length-valued expression
pub fn eval_length(tcx: TyCtxt,
count: hir::BodyId,
reason: &str)
-> Result<usize, ErrorReported>
{
let count_expr = &tcx.hir.body(count).value;
let count_def_id = tcx.hir.body_owner_def_id(count);
match ty::queries::monomorphic_const_eval::get(tcx, count_expr.span, count_def_id) {
Ok(Integral(Usize(count))) => {
let val = count.as_u64(tcx.sess.target.uint_type);
assert_eq!(val as usize as u64, val);
Ok(val as usize)
},
Ok(_) |
Err(ConstEvalErr { kind: ErrKind::TypeckError, .. }) => Err(ErrorReported),
Err(err) => {
let mut diag = err.struct_error(tcx, count_expr.span, reason);

if let hir::ExprPath(hir::QPath::Resolved(None, ref path)) = count_expr.node {
if let Def::Local(..) = path.def {
diag.note(&format!("`{}` is a variable",
tcx.hir.node_to_pretty_string(count_expr.id)));
}
}

diag.emit();
Err(ErrorReported)
}
}
}
49 changes: 15 additions & 34 deletions src/librustc_const_eval/eval.rs
Expand Up @@ -18,6 +18,7 @@ use rustc::traits;
use rustc::hir::def::Def;
use rustc::hir::def_id::DefId;
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;
Expand Down Expand Up @@ -163,12 +164,6 @@ pub struct ConstContext<'a, 'tcx: 'a> {
}

impl<'a, 'tcx> ConstContext<'a, 'tcx> {
pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, body: hir::BodyId) -> Self {
let def_id = tcx.hir.body_owner_def_id(body);
ty::queries::mir_const_qualif::get(tcx, DUMMY_SP, def_id);
ConstContext::with_tables(tcx, tcx.item_tables(def_id))
}

pub fn with_tables(tcx: TyCtxt<'a, 'tcx, 'tcx>, tables: &'a ty::TypeckTables<'tcx>) -> Self {
ConstContext {
tcx: tcx,
Expand Down Expand Up @@ -799,34 +794,20 @@ impl<'a, 'tcx> ConstContext<'a, 'tcx> {
}
}

pub fn provide(providers: &mut Providers) {
*providers = Providers {
monomorphic_const_eval,
..*providers
};
}

/// Returns the value of the length-valued expression
pub fn eval_length<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
count: hir::BodyId,
reason: &str)
-> Result<usize, ErrorReported>
{
let count_expr = &tcx.hir.body(count).value;
match ConstContext::new(tcx, count).eval(count_expr) {
Ok(Integral(Usize(count))) => {
let val = count.as_u64(tcx.sess.target.uint_type);
assert_eq!(val as usize as u64, val);
Ok(val as usize)
},
Ok(_) |
Err(ConstEvalErr { kind: TypeckError, .. }) => Err(ErrorReported),
Err(err) => {
let mut diag = err.struct_error(tcx, count_expr.span, reason);

if let hir::ExprPath(hir::QPath::Resolved(None, ref path)) = count_expr.node {
if let Def::Local(..) = path.def {
diag.note(&format!("`{}` is a variable",
tcx.hir.node_to_pretty_string(count_expr.id)));
}
}
fn monomorphic_const_eval<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
def_id: DefId)
-> EvalResult<'tcx> {
ty::queries::mir_const_qualif::get(tcx, DUMMY_SP, def_id);
let cx = ConstContext::with_tables(tcx, tcx.item_tables(def_id));

diag.emit();
Err(ErrorReported)
}
}
let id = tcx.hir.as_local_node_id(def_id).unwrap();
let body = tcx.hir.body_owned_by(id);
cx.eval(&tcx.hir.body(body).value)
}
3 changes: 2 additions & 1 deletion src/librustc_driver/driver.rs
Expand Up @@ -37,7 +37,7 @@ use rustc_plugin::registry::Registry;
use rustc_plugin as plugin;
use rustc_passes::{ast_validation, no_asm, loops, consts,
static_recursion, hir_stats, mir_stats};
use rustc_const_eval::check_match;
use rustc_const_eval::{self, check_match};
use super::Compilation;

use serialize::json;
Expand Down Expand Up @@ -895,6 +895,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
typeck::provide(&mut local_providers);
ty::provide(&mut local_providers);
reachable::provide(&mut local_providers);
rustc_const_eval::provide(&mut local_providers);

let mut extern_providers = ty::maps::Providers::default();
cstore::provide(&mut extern_providers);
Expand Down
5 changes: 2 additions & 3 deletions src/librustc_mir/hair/cx/expr.rs
Expand Up @@ -17,7 +17,6 @@ use hair::cx::to_ref::ToRef;
use rustc::hir::map;
use rustc::hir::def::{Def, CtorKind};
use rustc::middle::const_val::ConstVal;
use rustc_const_eval::ConstContext;
use rustc::ty::{self, AdtKind, VariantDef, Ty};
use rustc::ty::cast::CastKind as TyCastKind;
use rustc::hir;
Expand Down Expand Up @@ -592,9 +591,9 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,

// Now comes the rote stuff:
hir::ExprRepeat(ref v, count) => {
let tcx = cx.tcx.global_tcx();
let c = &cx.tcx.hir.body(count).value;
let count = match ConstContext::new(tcx, count).eval(c) {
let def_id = cx.tcx.hir.body_owner_def_id(count);
let count = match ty::queries::monomorphic_const_eval::get(cx.tcx, c.span, def_id) {
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")
Expand Down
1 change: 0 additions & 1 deletion src/librustc_typeck/Cargo.toml
Expand Up @@ -16,7 +16,6 @@ arena = { path = "../libarena" }
fmt_macros = { path = "../libfmt_macros" }
rustc = { path = "../librustc" }
rustc_back = { path = "../librustc_back" }
rustc_const_eval = { path = "../librustc_const_eval" }
rustc_const_math = { path = "../librustc_const_math" }
rustc_data_structures = { path = "../librustc_data_structures" }
rustc_platform_intrinsics = { path = "../librustc_platform_intrinsics" }
Expand Down
4 changes: 2 additions & 2 deletions src/librustc_typeck/astconv.rs
Expand Up @@ -12,7 +12,7 @@
//! representation. The main routine here is `ast_ty_to_ty()`: each use
//! is parameterized by an instance of `AstConv`.

use rustc_const_eval::eval_length;
use rustc::middle::const_val::eval_length;
use rustc_data_structures::accumulate_vec::AccumulateVec;
use hir;
use hir::def::Def;
Expand Down Expand Up @@ -1208,7 +1208,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
self.associated_path_def_to_ty(ast_ty.id, ast_ty.span, ty, def, segment).0
}
hir::TyArray(ref ty, length) => {
if let Ok(length) = eval_length(tcx.global_tcx(), length, "array length") {
if let Ok(length) = eval_length(tcx, length, "array length") {
tcx.mk_array(self.ast_ty_to_ty(&ty), length)
} else {
self.tcx().types.err
Expand Down
4 changes: 2 additions & 2 deletions src/librustc_typeck/check/mod.rs
Expand Up @@ -126,7 +126,7 @@ use rustc::hir::itemlikevisit::ItemLikeVisitor;
use rustc::hir::{self, PatKind};
use rustc::middle::lang_items;
use rustc_back::slice;
use rustc_const_eval::eval_length;
use rustc::middle::const_val::eval_length;
use rustc_const_math::ConstInt;

mod assoc;
Expand Down Expand Up @@ -3634,7 +3634,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
tcx.mk_array(element_ty, args.len())
}
hir::ExprRepeat(ref element, count) => {
let count = eval_length(self.tcx.global_tcx(), count, "repeat count")
let count = eval_length(self.tcx, count, "repeat count")
.unwrap_or(0);

let uty = match expected {
Expand Down
6 changes: 1 addition & 5 deletions src/librustc_typeck/collect.rs
Expand Up @@ -59,14 +59,12 @@ use constrained_type_params as ctp;
use middle::lang_items::SizedTraitLangItem;
use middle::const_val::ConstVal;
use middle::resolve_lifetime as rl;
use rustc_const_eval::ConstContext;
use rustc::ty::subst::Substs;
use rustc::ty::{ToPredicate, ReprOptions};
use rustc::ty::{self, AdtKind, ToPolyTraitRef, Ty, TyCtxt};
use rustc::ty::maps::Providers;
use rustc::ty::util::IntTypeExt;
use rustc::dep_graph::DepNode;
use util::common::MemoizationMap;
use util::nodemap::{NodeMap, FxHashMap};

use rustc_const_math::ConstInt;
Expand Down Expand Up @@ -600,9 +598,7 @@ fn convert_enum_variant_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
let wrapped_discr = prev_discr.map_or(initial, |d| d.wrap_incr());
prev_discr = Some(if let Some(e) = variant.node.disr_expr {
let expr_did = tcx.hir.local_def_id(e.node_id);
let result = tcx.maps.monomorphic_const_eval.memoize(expr_did, || {
ConstContext::new(tcx, e).eval(&tcx.hir.body(e).value)
});
let result = ty::queries::monomorphic_const_eval::get(tcx, variant.span, expr_did);

// enum variant evaluation happens before the global constant check
// so we need to report the real error
Expand Down
1 change: 0 additions & 1 deletion src/librustc_typeck/lib.rs
Expand Up @@ -94,7 +94,6 @@ extern crate fmt_macros;
extern crate rustc_platform_intrinsics as intrinsics;
extern crate rustc_back;
extern crate rustc_const_math;
extern crate rustc_const_eval;
extern crate rustc_data_structures;
extern crate rustc_errors as errors;

Expand Down
1 change: 0 additions & 1 deletion src/librustdoc/Cargo.toml
Expand Up @@ -14,7 +14,6 @@ env_logger = { version = "0.4", default-features = false }
log = "0.3"
rustc = { path = "../librustc" }
rustc_back = { path = "../librustc_back" }
rustc_const_eval = { path = "../librustc_const_eval" }
rustc_data_structures = { path = "../librustc_data_structures" }
rustc_driver = { path = "../librustc_driver" }
rustc_errors = { path = "../librustc_errors" }
Expand Down
2 changes: 1 addition & 1 deletion src/librustdoc/clean/mod.rs
Expand Up @@ -1715,7 +1715,7 @@ impl Clean<Type> for hir::Ty {
}
TySlice(ref ty) => Vector(box ty.clean(cx)),
TyArray(ref ty, length) => {
use rustc_const_eval::eval_length;
use rustc::middle::const_val::eval_length;
let n = eval_length(cx.tcx, length, "array length").unwrap();
FixedVector(box ty.clean(cx), n.to_string())
},
Expand Down
1 change: 0 additions & 1 deletion src/librustdoc/lib.rs
Expand Up @@ -33,7 +33,6 @@ extern crate getopts;
extern crate env_logger;
extern crate libc;
extern crate rustc;
extern crate rustc_const_eval;
extern crate rustc_data_structures;
extern crate rustc_trans;
extern crate rustc_driver;
Expand Down

0 comments on commit 63064ec

Please sign in to comment.