Skip to content

Commit

Permalink
Promoteds also need param envs.
Browse files Browse the repository at this point in the history
This also allows us to use the `const_eval` query again without causing cycles
  • Loading branch information
oli-obk committed Jan 10, 2020
1 parent 36b1756 commit 6e1bbff
Show file tree
Hide file tree
Showing 4 changed files with 18 additions and 16 deletions.
4 changes: 2 additions & 2 deletions src/librustc/mir/interpret/queries.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ impl<'tcx> TyCtxt<'tcx> {
let instance = ty::Instance::resolve(self, param_env, def_id, substs);
if let Some(instance) = instance {
if let Some(promoted) = promoted {
self.const_eval_promoted(instance, promoted)
self.const_eval_promoted(param_env, instance, promoted)
} else {
self.const_eval_instance(param_env, instance, span)
}
Expand All @@ -68,11 +68,11 @@ impl<'tcx> TyCtxt<'tcx> {
/// Evaluate a promoted constant.
pub fn const_eval_promoted(
self,
param_env: ty::ParamEnv<'tcx>,
instance: ty::Instance<'tcx>,
promoted: mir::Promoted,
) -> ConstEvalResult<'tcx> {
let cid = GlobalId { instance, promoted: Some(promoted) };
let param_env = ty::ParamEnv::reveal_all();
self.const_eval_validated(param_env.and(cid))
}
}
19 changes: 14 additions & 5 deletions src/librustc_mir/interpret/eval_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -757,13 +757,22 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
&self,
gid: GlobalId<'tcx>,
) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> {
let val = if self.tcx.is_static(gid.instance.def_id()) {
self.tcx.const_eval_poly(gid.instance.def_id())?
} else if let Some(promoted) = gid.promoted {
self.tcx.const_eval_promoted(gid.instance, promoted)?
// For statics we pick `ParamEnv::reveal_all`, because statics don't have generics
// and thus don't care about the parameter environment. While we could just use
// `self.param_env`, that would mean we invoke the query to evaluate the static
// with different parameter environments, thus causing the static to be evaluated
// multiple times.
let param_env = if self.tcx.is_static(gid.instance.def_id()) {
ty::ParamEnv::reveal_all()
} else {
self.tcx.const_eval_instance(self.param_env, gid.instance, Some(self.tcx.span))?
self.param_env
};
let val = if let Some(promoted) = gid.promoted {
self.tcx.const_eval_promoted(param_env, gid.instance, promoted)?
} else {
self.tcx.const_eval_instance(param_env, gid.instance, Some(self.tcx.span))?
};

// Even though `ecx.const_eval` is called from `eval_const_to_op` we can never have a
// recursion deeper than one level, because the `tcx.const_eval` above is guaranteed to not
// return `ConstValue::Unevaluated`, which is the only way that `eval_const_to_op` will call
Expand Down
9 changes: 1 addition & 8 deletions src/librustc_mir/interpret/operand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -537,14 +537,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
// potentially requiring the current static to be evaluated again. This is not a
// problem here, because we are building an operand which means an actual read is
// happening.
// FIXME(oli-obk): eliminate all the `const_eval_raw` usages when we get rid of
// `StaticKind` once and for all.
// FIXME the following line should have been:
// return self.const_eval(GlobalId { instance, promoted });
// but since the addition of Promoteds being Constants is causing const validation
// cycles. Promoteds being Constants exercise const validation more often and it
// may have made show up a pre-existing bug.
return Ok(OpTy::from(self.const_eval_raw(GlobalId { instance, promoted })?));
return Ok(OpTy::from(self.const_eval(GlobalId { instance, promoted })?));
}
ty::ConstKind::Infer(..)
| ty::ConstKind::Bound(..)
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/consts/const-eval/ub-nonnull.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ LL | / const OUT_OF_BOUNDS_PTR: NonNull<u8> = { unsafe {
LL | | let ptr: &[u8; 256] = mem::transmute(&0u8); // &0 gets promoted so it does not dangle
LL | | // Use address-of-element for pointer arithmetic. This could wrap around to NULL!
LL | | let out_of_bounds_ptr = &ptr[255];
| | ^^^^^^^^^ Memory access failed: pointer must be in-bounds at offset 256, but is outside bounds of allocation 8 which has size 1
| | ^^^^^^^^^ Memory access failed: pointer must be in-bounds at offset 256, but is outside bounds of allocation 9 which has size 1
LL | | mem::transmute(out_of_bounds_ptr)
LL | | } };
| |____-
Expand Down

0 comments on commit 6e1bbff

Please sign in to comment.