Skip to content

Commit 5e449b9

Browse files
committed
Auto merge of #74949 - oli-obk:validate_const_eval_raw, r=RalfJung
Validate constants during `const_eval_raw` This PR implements the groundwork for #72396 * constants are now validated during `const_eval_raw` * to prevent cycle errors, we do not validate references to statics anymore beyond the fact that they are not dangling * the `const_eval` query ICEs if used on `static` items * as a side effect promoteds are now evaluated to `ConstValue::Scalar` again (since they are just a reference to the actual promoted allocation in most cases).
2 parents 10b3595 + 34785fc commit 5e449b9

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+296
-369
lines changed

compiler/rustc_codegen_llvm/src/consts.rs

+2-5
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use rustc_hir::def_id::DefId;
1212
use rustc_hir::Node;
1313
use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
1414
use rustc_middle::mir::interpret::{
15-
read_target_uint, Allocation, ConstValue, ErrorHandled, GlobalAlloc, Pointer,
15+
read_target_uint, Allocation, ErrorHandled, GlobalAlloc, Pointer,
1616
};
1717
use rustc_middle::mir::mono::MonoItem;
1818
use rustc_middle::ty::{self, Instance, Ty};
@@ -85,10 +85,7 @@ pub fn codegen_static_initializer(
8585
cx: &CodegenCx<'ll, 'tcx>,
8686
def_id: DefId,
8787
) -> Result<(&'ll Value, &'tcx Allocation), ErrorHandled> {
88-
let alloc = match cx.tcx.const_eval_poly(def_id)? {
89-
ConstValue::ByRef { alloc, offset } if offset.bytes() == 0 => alloc,
90-
val => bug!("static const eval returned {:#?}", val),
91-
};
88+
let alloc = cx.tcx.eval_static_initializer(def_id)?;
9289
Ok((const_alloc_to_llvm(cx, alloc), alloc))
9390
}
9491

compiler/rustc_codegen_ssa/src/mir/block.rs

+7-19
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use rustc_ast as ast;
1313
use rustc_hir::lang_items::LangItem;
1414
use rustc_index::vec::Idx;
1515
use rustc_middle::mir;
16-
use rustc_middle::mir::interpret::{AllocId, ConstValue, Pointer, Scalar};
16+
use rustc_middle::mir::interpret::ConstValue;
1717
use rustc_middle::mir::AssertKind;
1818
use rustc_middle::ty::layout::{FnAbiExt, HasTyCtxt};
1919
use rustc_middle::ty::print::with_no_trimmed_paths;
@@ -867,24 +867,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
867867
let ty = constant.literal.ty;
868868
let size = bx.layout_of(ty).size;
869869
let scalar = match const_value {
870-
// Promoted constants are evaluated into a ByRef instead of a Scalar,
871-
// but we want the scalar value here.
872-
ConstValue::ByRef { alloc, offset } => {
873-
let ptr = Pointer::new(AllocId(0), offset);
874-
alloc
875-
.read_scalar(&bx, ptr, size)
876-
.and_then(|s| s.check_init())
877-
.unwrap_or_else(|e| {
878-
bx.tcx().sess.span_err(
879-
span,
880-
&format!("Could not evaluate asm const: {}", e),
881-
);
882-
883-
// We are erroring out, just emit a dummy constant.
884-
Scalar::from_u64(0)
885-
})
886-
}
887-
_ => span_bug!(span, "expected ByRef for promoted asm const"),
870+
ConstValue::Scalar(s) => s,
871+
_ => span_bug!(
872+
span,
873+
"expected Scalar for promoted asm const, but got {:#?}",
874+
const_value
875+
),
888876
};
889877
let value = scalar.assert_bits(size);
890878
let string = match ty.kind() {

compiler/rustc_infer/src/infer/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use rustc_middle::infer::canonical::{Canonical, CanonicalVarValues};
2121
use rustc_middle::infer::unify_key::{ConstVarValue, ConstVariableValue};
2222
use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind, ToType};
2323
use rustc_middle::mir;
24-
use rustc_middle::mir::interpret::ConstEvalResult;
24+
use rustc_middle::mir::interpret::EvalToConstValueResult;
2525
use rustc_middle::traits::select;
2626
use rustc_middle::ty::error::{ExpectedFound, TypeError, UnconstrainedNumeric};
2727
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder};
@@ -1542,7 +1542,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
15421542
substs: SubstsRef<'tcx>,
15431543
promoted: Option<mir::Promoted>,
15441544
span: Option<Span>,
1545-
) -> ConstEvalResult<'tcx> {
1545+
) -> EvalToConstValueResult<'tcx> {
15461546
let mut original_values = OriginalQueryValues::default();
15471547
let canonical = self.canonicalize_query(&(param_env, substs), &mut original_values);
15481548

compiler/rustc_lint/src/builtin.rs

+7-9
Original file line numberDiff line numberDiff line change
@@ -1474,21 +1474,19 @@ declare_lint_pass!(
14741474
UnusedBrokenConst => []
14751475
);
14761476

1477-
fn check_const(cx: &LateContext<'_>, body_id: hir::BodyId) {
1478-
let def_id = cx.tcx.hir().body_owner_def_id(body_id).to_def_id();
1479-
// trigger the query once for all constants since that will already report the errors
1480-
// FIXME: Use ensure here
1481-
let _ = cx.tcx.const_eval_poly(def_id);
1482-
}
1483-
14841477
impl<'tcx> LateLintPass<'tcx> for UnusedBrokenConst {
14851478
fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) {
14861479
match it.kind {
14871480
hir::ItemKind::Const(_, body_id) => {
1488-
check_const(cx, body_id);
1481+
let def_id = cx.tcx.hir().body_owner_def_id(body_id).to_def_id();
1482+
// trigger the query once for all constants since that will already report the errors
1483+
// FIXME: Use ensure here
1484+
let _ = cx.tcx.const_eval_poly(def_id);
14891485
}
14901486
hir::ItemKind::Static(_, _, body_id) => {
1491-
check_const(cx, body_id);
1487+
let def_id = cx.tcx.hir().body_owner_def_id(body_id).to_def_id();
1488+
// FIXME: Use ensure here
1489+
let _ = cx.tcx.eval_static_initializer(def_id);
14921490
}
14931491
_ => {}
14941492
}

compiler/rustc_middle/src/mir/interpret/error.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use super::{AllocId, Pointer, RawConst, Scalar};
1+
use super::{AllocId, ConstAlloc, Pointer, Scalar};
22

33
use crate::mir::interpret::ConstValue;
44
use crate::ty::{layout, query::TyCtxtAt, tls, FnSig, Ty};
@@ -27,8 +27,8 @@ CloneTypeFoldableAndLiftImpls! {
2727
ErrorHandled,
2828
}
2929

30-
pub type ConstEvalRawResult<'tcx> = Result<RawConst<'tcx>, ErrorHandled>;
31-
pub type ConstEvalResult<'tcx> = Result<ConstValue<'tcx>, ErrorHandled>;
30+
pub type EvalToAllocationRawResult<'tcx> = Result<ConstAlloc<'tcx>, ErrorHandled>;
31+
pub type EvalToConstValueResult<'tcx> = Result<ConstValue<'tcx>, ErrorHandled>;
3232

3333
pub fn struct_error<'tcx>(tcx: TyCtxtAt<'tcx>, msg: &str) -> DiagnosticBuilder<'tcx> {
3434
struct_span_err!(tcx.sess, tcx.span, E0080, "{}", msg)

compiler/rustc_middle/src/mir/interpret/mod.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -118,12 +118,12 @@ use crate::ty::subst::GenericArgKind;
118118
use crate::ty::{self, Instance, Ty, TyCtxt};
119119

120120
pub use self::error::{
121-
struct_error, CheckInAllocMsg, ConstEvalRawResult, ConstEvalResult, ErrorHandled, InterpError,
122-
InterpErrorInfo, InterpResult, InvalidProgramInfo, MachineStopType, ResourceExhaustionInfo,
123-
UndefinedBehaviorInfo, UninitBytesAccess, UnsupportedOpInfo,
121+
struct_error, CheckInAllocMsg, ErrorHandled, EvalToAllocationRawResult, EvalToConstValueResult,
122+
InterpError, InterpErrorInfo, InterpResult, InvalidProgramInfo, MachineStopType,
123+
ResourceExhaustionInfo, UndefinedBehaviorInfo, UninitBytesAccess, UnsupportedOpInfo,
124124
};
125125

126-
pub use self::value::{get_slice_bytes, ConstValue, RawConst, Scalar, ScalarMaybeUninit};
126+
pub use self::value::{get_slice_bytes, ConstAlloc, ConstValue, Scalar, ScalarMaybeUninit};
127127

128128
pub use self::allocation::{Allocation, AllocationExtra, InitMask, Relocations};
129129

compiler/rustc_middle/src/mir/interpret/queries.rs

+8-8
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use super::{ConstEvalResult, ErrorHandled, GlobalId};
1+
use super::{ErrorHandled, EvalToConstValueResult, GlobalId};
22

33
use crate::mir;
44
use crate::ty::subst::{InternalSubsts, SubstsRef};
@@ -10,7 +10,7 @@ impl<'tcx> TyCtxt<'tcx> {
1010
/// Evaluates a constant without providing any substitutions. This is useful to evaluate consts
1111
/// that can't take any generic arguments like statics, const items or enum discriminants. If a
1212
/// generic parameter is used within the constant `ErrorHandled::ToGeneric` will be returned.
13-
pub fn const_eval_poly(self, def_id: DefId) -> ConstEvalResult<'tcx> {
13+
pub fn const_eval_poly(self, def_id: DefId) -> EvalToConstValueResult<'tcx> {
1414
// In some situations def_id will have substitutions within scope, but they aren't allowed
1515
// to be used. So we can't use `Instance::mono`, instead we feed unresolved substitutions
1616
// into `const_eval` which will return `ErrorHandled::ToGeneric` if any of them are
@@ -38,7 +38,7 @@ impl<'tcx> TyCtxt<'tcx> {
3838
substs: SubstsRef<'tcx>,
3939
promoted: Option<mir::Promoted>,
4040
span: Option<Span>,
41-
) -> ConstEvalResult<'tcx> {
41+
) -> EvalToConstValueResult<'tcx> {
4242
match ty::Instance::resolve_opt_const_arg(self, param_env, def, substs) {
4343
Ok(Some(instance)) => {
4444
let cid = GlobalId { instance, promoted };
@@ -54,7 +54,7 @@ impl<'tcx> TyCtxt<'tcx> {
5454
param_env: ty::ParamEnv<'tcx>,
5555
instance: ty::Instance<'tcx>,
5656
span: Option<Span>,
57-
) -> ConstEvalResult<'tcx> {
57+
) -> EvalToConstValueResult<'tcx> {
5858
self.const_eval_global_id(param_env, GlobalId { instance, promoted: None }, span)
5959
}
6060

@@ -64,14 +64,14 @@ impl<'tcx> TyCtxt<'tcx> {
6464
param_env: ty::ParamEnv<'tcx>,
6565
cid: GlobalId<'tcx>,
6666
span: Option<Span>,
67-
) -> ConstEvalResult<'tcx> {
67+
) -> EvalToConstValueResult<'tcx> {
6868
// Const-eval shouldn't depend on lifetimes at all, so we can erase them, which should
6969
// improve caching of queries.
7070
let inputs = self.erase_regions(&param_env.and(cid));
7171
if let Some(span) = span {
72-
self.at(span).const_eval_validated(inputs)
72+
self.at(span).eval_to_const_value_raw(inputs)
7373
} else {
74-
self.const_eval_validated(inputs)
74+
self.eval_to_const_value_raw(inputs)
7575
}
7676
}
7777

@@ -94,7 +94,7 @@ impl<'tcx> TyCtxt<'tcx> {
9494
param_env: ty::ParamEnv<'tcx>,
9595
) -> Result<&'tcx mir::Allocation, ErrorHandled> {
9696
trace!("eval_to_allocation: Need to compute {:?}", gid);
97-
let raw_const = self.const_eval_raw(param_env.and(gid))?;
97+
let raw_const = self.eval_to_allocation_raw(param_env.and(gid))?;
9898
Ok(self.global_alloc(raw_const.alloc_id).unwrap_memory())
9999
}
100100
}

compiler/rustc_middle/src/mir/interpret/value.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ use crate::ty::{ParamEnv, Ty, TyCtxt};
1212

1313
use super::{sign_extend, truncate, AllocId, Allocation, InterpResult, Pointer, PointerArithmetic};
1414

15-
/// Represents the result of a raw const operation, pre-validation.
15+
/// Represents the result of const evaluation via the `eval_to_allocation` query.
1616
#[derive(Clone, HashStable)]
17-
pub struct RawConst<'tcx> {
17+
pub struct ConstAlloc<'tcx> {
1818
// the value lives here, at offset 0, and that allocation definitely is a `AllocKind::Memory`
1919
// (so you can use `AllocMap::unwrap_memory`).
2020
pub alloc_id: AllocId,

compiler/rustc_middle/src/query/mod.rs

+11-16
Original file line numberDiff line numberDiff line change
@@ -707,32 +707,27 @@ rustc_queries! {
707707
}
708708

709709
Other {
710-
/// Evaluates a constant without running sanity checks.
710+
/// Evaluates a constant and returns the computed allocation.
711711
///
712-
/// **Do not use this** outside const eval. Const eval uses this to break query cycles
713-
/// during validation. Please add a comment to every use site explaining why using
714-
/// `const_eval_validated` isn't sufficient. The returned constant also isn't in a suitable
715-
/// form to be used outside of const eval.
716-
query const_eval_raw(key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>)
717-
-> ConstEvalRawResult<'tcx> {
712+
/// **Do not use this** directly, use the `tcx.eval_static_initializer` wrapper.
713+
query eval_to_allocation_raw(key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>)
714+
-> EvalToAllocationRawResult<'tcx> {
718715
desc { |tcx|
719-
"const-evaluating `{}`",
716+
"const-evaluating + checking `{}`",
720717
key.value.display(tcx)
721718
}
722719
}
723720

724-
/// Results of evaluating const items or constants embedded in
725-
/// other items (such as enum variant explicit discriminants).
726-
///
727-
/// In contrast to `const_eval_raw` this performs some validation on the constant, and
728-
/// returns a proper constant that is usable by the rest of the compiler.
721+
/// Evaluates const items or anonymous constants
722+
/// (such as enum variant explicit discriminants or array lengths)
723+
/// into a representation suitable for the type system and const generics.
729724
///
730725
/// **Do not use this** directly, use one of the following wrappers: `tcx.const_eval_poly`,
731726
/// `tcx.const_eval_resolve`, `tcx.const_eval_instance`, or `tcx.const_eval_global_id`.
732-
query const_eval_validated(key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>)
733-
-> ConstEvalResult<'tcx> {
727+
query eval_to_const_value_raw(key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>)
728+
-> EvalToConstValueResult<'tcx> {
734729
desc { |tcx|
735-
"const-evaluating + checking `{}`",
730+
"simplifying constant for the type system `{}`",
736731
key.value.display(tcx)
737732
}
738733
cache_on_disk_if(_, opt_result) {

compiler/rustc_middle/src/ty/query/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use crate::middle::resolve_lifetime::{ObjectLifetimeDefault, Region, ResolveLife
1414
use crate::middle::stability::{self, DeprecationEntry};
1515
use crate::mir;
1616
use crate::mir::interpret::GlobalId;
17-
use crate::mir::interpret::{ConstEvalRawResult, ConstEvalResult, ConstValue};
17+
use crate::mir::interpret::{ConstValue, EvalToAllocationRawResult, EvalToConstValueResult};
1818
use crate::mir::interpret::{LitToConstError, LitToConstInput};
1919
use crate::mir::mono::CodegenUnit;
2020
use crate::traits::query::{

0 commit comments

Comments
 (0)