Skip to content

Commit 60cf542

Browse files
committed
rustc_const_eval: keep track of the appropriate ParamEnv.
1 parent 4c900c5 commit 60cf542

File tree

15 files changed

+107
-64
lines changed

15 files changed

+107
-64
lines changed

src/librustc/middle/const_val.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ pub use rustc_const_math::ConstInt;
1414
use hir;
1515
use hir::def::Def;
1616
use hir::def_id::DefId;
17-
use ty::{TyCtxt, layout};
17+
use traits::Reveal;
18+
use ty::{self, TyCtxt, layout};
1819
use ty::subst::Substs;
1920
use util::common::ErrorReported;
2021
use rustc_const_math::*;
@@ -229,8 +230,9 @@ pub fn eval_length(tcx: TyCtxt,
229230
{
230231
let count_expr = &tcx.hir.body(count).value;
231232
let count_def_id = tcx.hir.body_owner_def_id(count);
233+
let param_env = ty::ParamEnv::empty(Reveal::UserFacing);
232234
let substs = Substs::identity_for_item(tcx.global_tcx(), count_def_id);
233-
match tcx.at(count_expr.span).const_eval((count_def_id, substs)) {
235+
match tcx.at(count_expr.span).const_eval(param_env.and((count_def_id, substs))) {
234236
Ok(Integral(Usize(count))) => {
235237
let val = count.as_u64(tcx.sess.target.uint_type);
236238
assert_eq!(val as usize as u64, val);

src/librustc/ty/maps.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -372,8 +372,8 @@ impl<'tcx> QueryDescription for queries::reachable_set<'tcx> {
372372
}
373373

374374
impl<'tcx> QueryDescription for queries::const_eval<'tcx> {
375-
fn describe(tcx: TyCtxt, (def_id, _): (DefId, &'tcx Substs<'tcx>)) -> String {
376-
format!("const-evaluating `{}`", tcx.item_path_str(def_id))
375+
fn describe(tcx: TyCtxt, key: ty::ParamEnvAnd<'tcx, (DefId, &'tcx Substs<'tcx>)>) -> String {
376+
format!("const-evaluating `{}`", tcx.item_path_str(key.value.0))
377377
}
378378
}
379379

@@ -935,7 +935,7 @@ define_maps! { <'tcx>
935935

936936
/// Results of evaluating const items or constants embedded in
937937
/// other items (such as enum variant explicit discriminants).
938-
[] const_eval: const_eval_dep_node((DefId, &'tcx Substs<'tcx>))
938+
[] const_eval: const_eval_dep_node(ty::ParamEnvAnd<'tcx, (DefId, &'tcx Substs<'tcx>)>)
939939
-> const_val::EvalResult<'tcx>,
940940

941941
/// Performs the privacy check and computes "access levels".
@@ -1032,8 +1032,9 @@ fn typeck_item_bodies_dep_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> {
10321032
DepConstructor::TypeckBodiesKrate
10331033
}
10341034

1035-
fn const_eval_dep_node<'tcx>((def_id, substs): (DefId, &'tcx Substs<'tcx>))
1035+
fn const_eval_dep_node<'tcx>(key: ty::ParamEnvAnd<'tcx, (DefId, &'tcx Substs<'tcx>)>)
10361036
-> DepConstructor<'tcx> {
1037+
let (def_id, substs) = key.value;
10371038
DepConstructor::ConstEval { def_id, substs }
10381039
}
10391040

src/librustc/ty/mod.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -1582,14 +1582,15 @@ impl<'a, 'gcx, 'tcx> AdtDef {
15821582
#[inline]
15831583
pub fn discriminants(&'a self, tcx: TyCtxt<'a, 'gcx, 'tcx>)
15841584
-> impl Iterator<Item=ConstInt> + 'a {
1585+
let param_env = ParamEnv::empty(traits::Reveal::UserFacing);
15851586
let repr_type = self.repr.discr_type();
15861587
let initial = repr_type.initial_discriminant(tcx.global_tcx());
15871588
let mut prev_discr = None::<ConstInt>;
15881589
self.variants.iter().map(move |v| {
15891590
let mut discr = prev_discr.map_or(initial, |d| d.wrap_incr());
15901591
if let VariantDiscr::Explicit(expr_did) = v.discr {
15911592
let substs = Substs::identity_for_item(tcx.global_tcx(), expr_did);
1592-
match tcx.const_eval((expr_did, substs)) {
1593+
match tcx.const_eval(param_env.and((expr_did, substs))) {
15931594
Ok(ConstVal::Integral(v)) => {
15941595
discr = v;
15951596
}
@@ -1617,6 +1618,7 @@ impl<'a, 'gcx, 'tcx> AdtDef {
16171618
tcx: TyCtxt<'a, 'gcx, 'tcx>,
16181619
variant_index: usize)
16191620
-> ConstInt {
1621+
let param_env = ParamEnv::empty(traits::Reveal::UserFacing);
16201622
let repr_type = self.repr.discr_type();
16211623
let mut explicit_value = repr_type.initial_discriminant(tcx.global_tcx());
16221624
let mut explicit_index = variant_index;
@@ -1628,7 +1630,7 @@ impl<'a, 'gcx, 'tcx> AdtDef {
16281630
}
16291631
ty::VariantDiscr::Explicit(expr_did) => {
16301632
let substs = Substs::identity_for_item(tcx.global_tcx(), expr_did);
1631-
match tcx.const_eval((expr_did, substs)) {
1633+
match tcx.const_eval(param_env.and((expr_did, substs))) {
16321634
Ok(ConstVal::Integral(v)) => {
16331635
explicit_value = v;
16341636
break;

src/librustc/ty/structural_impls.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -398,7 +398,7 @@ macro_rules! CopyImpls {
398398
}
399399
}
400400

401-
CopyImpls! { (), hir::Unsafety, abi::Abi }
401+
CopyImpls! { (), hir::Unsafety, abi::Abi, hir::def_id::DefId }
402402

403403
impl<'tcx, T:TypeFoldable<'tcx>, U:TypeFoldable<'tcx>> TypeFoldable<'tcx> for (T, U) {
404404
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> (T, U) {

src/librustc_const_eval/check_match.rs

+6-4
Original file line numberDiff line numberDiff line change
@@ -165,8 +165,9 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> {
165165

166166
let inlined_arms : Vec<(Vec<_>, _)> = arms.iter().map(|arm| (
167167
arm.pats.iter().map(|pat| {
168-
let substs = self.identity_substs;
169-
let mut patcx = PatternContext::new(self.tcx, self.tables, substs);
168+
let mut patcx = PatternContext::new(self.tcx,
169+
self.param_env.and(self.identity_substs),
170+
self.tables);
170171
let pattern = expand_pattern(cx, patcx.lower_pattern(&pat));
171172
if !patcx.errors.is_empty() {
172173
patcx.report_inlining_errors(pat.span);
@@ -233,8 +234,9 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> {
233234
fn check_irrefutable(&self, pat: &Pat, origin: &str) {
234235
let module = self.tcx.hir.get_module_parent(pat.id);
235236
MatchCheckCtxt::create_and_enter(self.tcx, module, |ref mut cx| {
236-
let substs = self.identity_substs;
237-
let mut patcx = PatternContext::new(self.tcx, self.tables, substs);
237+
let mut patcx = PatternContext::new(self.tcx,
238+
self.param_env.and(self.identity_substs),
239+
self.tables);
238240
let pattern = patcx.lower_pattern(pat);
239241
let pattern_ty = pattern.ty;
240242
let pats : Matrix = vec![vec![

src/librustc_const_eval/eval.rs

+33-35
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ use rustc::ty::{self, Ty, TyCtxt};
2121
use rustc::ty::maps::Providers;
2222
use rustc::ty::util::IntTypeExt;
2323
use rustc::ty::subst::{Substs, Subst};
24-
use rustc::traits::Reveal;
2524
use rustc::util::common::ErrorReported;
2625
use rustc::util::nodemap::DefIdMap;
2726

@@ -49,24 +48,21 @@ macro_rules! math {
4948
}
5049
}
5150

52-
/// * `def_id` is the id of the constant.
53-
/// * `substs` is the monomorphized substitutions for the expression.
54-
///
55-
/// `substs` is optional and is used for associated constants.
56-
/// This generally happens in late/trans const evaluation.
51+
/// * `DefId` is the id of the constant.
52+
/// * `Substs` is the monomorphized substitutions for the expression.
5753
pub fn lookup_const_by_id<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
58-
def_id: DefId,
59-
substs: &'tcx Substs<'tcx>)
54+
key: ty::ParamEnvAnd<'tcx, (DefId, &'tcx Substs<'tcx>)>)
6055
-> Option<(DefId, &'tcx Substs<'tcx>)> {
56+
let (def_id, _) = key.value;
6157
if let Some(node_id) = tcx.hir.as_local_node_id(def_id) {
6258
match tcx.hir.find(node_id) {
6359
Some(hir_map::NodeTraitItem(_)) => {
6460
// If we have a trait item and the substitutions for it,
6561
// `resolve_trait_associated_const` will select an impl
6662
// or the default.
67-
resolve_trait_associated_const(tcx, def_id, substs)
63+
resolve_trait_associated_const(tcx, key)
6864
}
69-
_ => Some((def_id, substs))
65+
_ => Some(key.value)
7066
}
7167
} else {
7268
match tcx.describe_def(def_id) {
@@ -76,31 +72,34 @@ pub fn lookup_const_by_id<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
7672
// trait-associated const if the caller gives us the
7773
// substitutions for the reference to it.
7874
if tcx.trait_of_item(def_id).is_some() {
79-
resolve_trait_associated_const(tcx, def_id, substs)
75+
resolve_trait_associated_const(tcx, key)
8076
} else {
81-
Some((def_id, substs))
77+
Some(key.value)
8278
}
8379
}
84-
_ => Some((def_id, substs))
80+
_ => Some(key.value)
8581
}
8682
}
8783
}
8884

8985
pub struct ConstContext<'a, 'tcx: 'a> {
9086
tcx: TyCtxt<'a, 'tcx, 'tcx>,
9187
tables: &'a ty::TypeckTables<'tcx>,
88+
param_env: ty::ParamEnv<'tcx>,
9289
substs: &'tcx Substs<'tcx>,
9390
fn_args: Option<DefIdMap<ConstVal<'tcx>>>
9491
}
9592

9693
impl<'a, 'tcx> ConstContext<'a, 'tcx> {
9794
pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
98-
tables: &'a ty::TypeckTables<'tcx>,
99-
substs: &'tcx Substs<'tcx>) -> Self {
95+
param_env_and_substs: ty::ParamEnvAnd<'tcx, &'tcx Substs<'tcx>>,
96+
tables: &'a ty::TypeckTables<'tcx>)
97+
-> Self {
10098
ConstContext {
10199
tcx,
100+
param_env: param_env_and_substs.param_env,
102101
tables,
103-
substs,
102+
substs: param_env_and_substs.value,
104103
fn_args: None
105104
}
106105
}
@@ -279,7 +278,7 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
279278
match cx.tables.qpath_def(qpath, e.id) {
280279
Def::Const(def_id) |
281280
Def::AssociatedConst(def_id) => {
282-
match tcx.at(e.span).const_eval((def_id, substs)) {
281+
match tcx.at(e.span).const_eval(cx.param_env.and((def_id, substs))) {
283282
Ok(val) => val,
284283
Err(ConstEvalErr { kind: TypeckError, .. }) => {
285284
signal!(e, TypeckError);
@@ -323,10 +322,9 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
323322

324323
if tcx.fn_sig(def_id).abi() == Abi::RustIntrinsic {
325324
let layout_of = |ty: Ty<'tcx>| {
326-
ty.layout(tcx, ty::ParamEnv::empty(traits::Reveal::All))
327-
.map_err(|err| {
328-
ConstEvalErr { span: e.span, kind: LayoutError(err) }
329-
})
325+
ty.layout(tcx, cx.param_env).map_err(|err| {
326+
ConstEvalErr { span: e.span, kind: LayoutError(err) }
327+
})
330328
};
331329
match &tcx.item_name(def_id).as_str()[..] {
332330
"size_of" => {
@@ -377,7 +375,8 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
377375
}
378376
debug!("const call({:?})", call_args);
379377
let callee_cx = ConstContext {
380-
tcx: tcx,
378+
tcx,
379+
param_env: cx.param_env,
381380
tables: tcx.typeck_tables_of(def_id),
382381
substs: substs,
383382
fn_args: Some(call_args)
@@ -477,17 +476,17 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
477476
}
478477

479478
fn resolve_trait_associated_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
480-
def_id: DefId,
481-
substs: &'tcx Substs<'tcx>)
479+
key: ty::ParamEnvAnd<'tcx, (DefId, &'tcx Substs<'tcx>)>)
482480
-> Option<(DefId, &'tcx Substs<'tcx>)> {
481+
let param_env = key.param_env;
482+
let (def_id, substs) = key.value;
483483
let trait_item = tcx.associated_item(def_id);
484484
let trait_id = trait_item.container.id();
485485
let trait_ref = ty::Binder(ty::TraitRef::new(trait_id, substs));
486486
debug!("resolve_trait_associated_const: trait_ref={:?}",
487487
trait_ref);
488488

489489
tcx.infer_ctxt().enter(|infcx| {
490-
let param_env = ty::ParamEnv::empty(Reveal::UserFacing);
491490
let mut selcx = traits::SelectionContext::new(&infcx);
492491
let obligation = traits::Obligation::new(traits::ObligationCause::dummy(),
493492
param_env,
@@ -506,10 +505,8 @@ fn resolve_trait_associated_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
506505
};
507506

508507
// NOTE: this code does not currently account for specialization, but when
509-
// it does so, it should hook into the Reveal to determine when the
510-
// constant should resolve; this will also require plumbing through to this
511-
// function whether we are in "trans mode" to pick the right Reveal
512-
// when constructing the inference context above.
508+
// it does so, it should hook into the param_env.reveal to determine when the
509+
// constant should resolve.
513510
match selection {
514511
traits::VtableImpl(ref impl_data) => {
515512
let name = trait_item.name;
@@ -524,15 +521,16 @@ fn resolve_trait_associated_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
524521
}
525522
None => {
526523
if trait_item.defaultness.has_value() {
527-
Some((def_id, substs))
524+
Some(key.value)
528525
} else {
529526
None
530527
}
531528
}
532529
}
533530
}
531+
traits::VtableParam(_) => None,
534532
_ => {
535-
bug!("resolve_trait_associated_const: unexpected vtable type")
533+
bug!("resolve_trait_associated_const: unexpected vtable type {:?}", selection)
536534
}
537535
}
538536
})
@@ -761,13 +759,13 @@ pub fn provide(providers: &mut Providers) {
761759
}
762760

763761
fn const_eval<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
764-
(def_id, substs): (DefId, &'tcx Substs<'tcx>))
762+
key: ty::ParamEnvAnd<'tcx, (DefId, &'tcx Substs<'tcx>)>)
765763
-> EvalResult<'tcx> {
766-
let (def_id, substs) = if let Some(resolved) = lookup_const_by_id(tcx, def_id, substs) {
764+
let (def_id, substs) = if let Some(resolved) = lookup_const_by_id(tcx, key) {
767765
resolved
768766
} else {
769767
return Err(ConstEvalErr {
770-
span: tcx.def_span(def_id),
768+
span: tcx.def_span(key.value.0),
771769
kind: TypeckError
772770
});
773771
};
@@ -779,5 +777,5 @@ fn const_eval<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
779777
} else {
780778
tcx.sess.cstore.item_body(tcx, def_id)
781779
};
782-
ConstContext::new(tcx, tables, substs).eval(&body.value)
780+
ConstContext::new(tcx, key.param_env.and(substs), tables).eval(&body.value)
783781
}

src/librustc_const_eval/pattern.rs

+16-7
Original file line numberDiff line numberDiff line change
@@ -268,17 +268,18 @@ impl<'tcx> fmt::Display for Pattern<'tcx> {
268268

269269
pub struct PatternContext<'a, 'tcx: 'a> {
270270
pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
271+
pub param_env: ty::ParamEnv<'tcx>,
271272
pub tables: &'a ty::TypeckTables<'tcx>,
272273
pub substs: &'tcx Substs<'tcx>,
273274
pub errors: Vec<PatternError<'tcx>>,
274275
}
275276

276277
impl<'a, 'tcx> Pattern<'tcx> {
277278
pub fn from_hir(tcx: TyCtxt<'a, 'tcx, 'tcx>,
279+
param_env_and_substs: ty::ParamEnvAnd<'tcx, &'tcx Substs<'tcx>>,
278280
tables: &'a ty::TypeckTables<'tcx>,
279-
substs: &'tcx Substs<'tcx>,
280281
pat: &hir::Pat) -> Self {
281-
let mut pcx = PatternContext::new(tcx, tables, substs);
282+
let mut pcx = PatternContext::new(tcx, param_env_and_substs, tables);
282283
let result = pcx.lower_pattern(pat);
283284
if !pcx.errors.is_empty() {
284285
span_bug!(pat.span, "encountered errors lowering pattern: {:?}", pcx.errors)
@@ -290,9 +291,15 @@ impl<'a, 'tcx> Pattern<'tcx> {
290291

291292
impl<'a, 'tcx> PatternContext<'a, 'tcx> {
292293
pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
293-
tables: &'a ty::TypeckTables<'tcx>,
294-
substs: &'tcx Substs<'tcx>) -> Self {
295-
PatternContext { tcx, tables, substs, errors: vec![] }
294+
param_env_and_substs: ty::ParamEnvAnd<'tcx, &'tcx Substs<'tcx>>,
295+
tables: &'a ty::TypeckTables<'tcx>) -> Self {
296+
PatternContext {
297+
tcx,
298+
param_env: param_env_and_substs.param_env,
299+
tables,
300+
substs: param_env_and_substs.value,
301+
errors: vec![]
302+
}
296303
}
297304

298305
pub fn lower_pattern(&mut self, pat: &hir::Pat) -> Pattern<'tcx> {
@@ -588,7 +595,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
588595
let kind = match def {
589596
Def::Const(def_id) | Def::AssociatedConst(def_id) => {
590597
let substs = self.tables.node_substs(id);
591-
match eval::lookup_const_by_id(self.tcx, def_id, substs) {
598+
match eval::lookup_const_by_id(self.tcx, self.param_env.and((def_id, substs))) {
592599
Some((def_id, substs)) => {
593600
// Enter the inlined constant's tables&substs temporarily.
594601
let old_tables = self.tables;
@@ -622,7 +629,9 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
622629
}
623630

624631
fn lower_lit(&mut self, expr: &hir::Expr) -> PatternKind<'tcx> {
625-
let const_cx = eval::ConstContext::new(self.tcx, self.tables, self.substs);
632+
let const_cx = eval::ConstContext::new(self.tcx,
633+
self.param_env.and(self.substs),
634+
self.tables);
626635
match const_cx.eval(expr) {
627636
Ok(value) => {
628637
if let ConstVal::Variant(def_id) = value {

src/librustc_lint/types.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits {
113113
let parent_item = cx.tcx.hir.get_parent(e.id);
114114
let parent_def_id = cx.tcx.hir.local_def_id(parent_item);
115115
let substs = Substs::identity_for_item(cx.tcx, parent_def_id);
116-
let const_cx = ConstContext::new(cx.tcx, cx.tables, substs);
116+
let const_cx = ConstContext::new(cx.tcx,
117+
cx.param_env.and(substs),
118+
cx.tables);
117119
match const_cx.eval(&r) {
118120
Ok(ConstVal::Integral(i)) => {
119121
i.is_negative() ||

src/librustc_mir/build/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -514,8 +514,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
514514

515515
if let Some(pattern) = pattern {
516516
let pattern = Pattern::from_hir(self.hir.tcx().global_tcx(),
517+
self.hir.param_env.and(self.hir.identity_substs),
517518
self.hir.tables(),
518-
self.hir.identity_substs,
519519
pattern);
520520
scope = self.declare_bindings(scope, ast_body.span, &pattern);
521521
unpack!(block = self.lvalue_into_pattern(block, pattern, &lvalue));

src/librustc_mir/hair/cx/block.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,8 @@ fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
7171
});
7272

7373
let pattern = Pattern::from_hir(cx.tcx.global_tcx(),
74+
cx.param_env.and(cx.identity_substs),
7475
cx.tables(),
75-
cx.identity_substs,
7676
&local.pat);
7777
result.push(StmtRef::Mirror(Box::new(Stmt {
7878
span: stmt.span,

0 commit comments

Comments
 (0)