Skip to content

Commit dbef6e4

Browse files
committed
address review
1 parent 5c95a3d commit dbef6e4

File tree

16 files changed

+80
-93
lines changed

16 files changed

+80
-93
lines changed

Cargo.lock

-1
Original file line numberDiff line numberDiff line change
@@ -358,7 +358,6 @@ dependencies = [
358358
"libgit2-sys",
359359
"log",
360360
"memchr",
361-
"num_cpus",
362361
"opener",
363362
"openssl",
364363
"os_info",

compiler/rustc_const_eval/src/const_eval/error.rs

+2
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ impl<'tcx> ConstEvalErr<'tcx> {
140140
///
141141
/// If `lint_root.is_some()` report it as a lint, else report it as a hard error.
142142
/// (Except that for some errors, we ignore all that -- see `must_error` below.)
143+
#[instrument(skip(self, tcx, decorate, lint_root), level = "debug")]
143144
fn struct_generic(
144145
&self,
145146
tcx: TyCtxtAt<'tcx>,
@@ -190,6 +191,7 @@ impl<'tcx> ConstEvalErr<'tcx> {
190191
decorate(err);
191192
};
192193

194+
debug!("self.error: {:?}", self.error);
193195
// Special handling for certain errors
194196
match &self.error {
195197
// Don't emit a new diagnostic for these errors

compiler/rustc_const_eval/src/const_eval/mod.rs

+31-10
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,6 @@ pub use fn_queries::*;
2424
pub use machine::*;
2525
pub(crate) use valtrees::{const_to_valtree_inner, valtree_to_const_value};
2626

27-
pub(crate) enum ValTreeCreationError {
28-
NonSupportedType,
29-
Other,
30-
}
31-
pub(crate) type ValTreeCreationResult<'tcx> = Result<ty::ValTree<'tcx>, ValTreeCreationError>;
32-
3327
pub(crate) fn const_caller_location(
3428
tcx: TyCtxt<'_>,
3529
(file, line, col): (Symbol, u32, u32),
@@ -44,6 +38,16 @@ pub(crate) fn const_caller_location(
4438
ConstValue::Scalar(Scalar::from_maybe_pointer(loc_place.ptr, &tcx))
4539
}
4640

41+
// We forbid type-level constants that contain more than `VALTREE_MAX_NODES` nodes.
42+
const VALTREE_MAX_NODES: usize = 100000;
43+
44+
pub(crate) enum ValTreeCreationError {
45+
NodesOverflow,
46+
NonSupportedType,
47+
Other,
48+
}
49+
pub(crate) type ValTreeCreationResult<'tcx> = Result<ty::ValTree<'tcx>, ValTreeCreationError>;
50+
4751
/// Evaluates a constant and turns it into a type-level constant value.
4852
pub(crate) fn eval_to_valtree<'tcx>(
4953
tcx: TyCtxt<'tcx>,
@@ -62,11 +66,28 @@ pub(crate) fn eval_to_valtree<'tcx>(
6266
let place = ecx.raw_const_to_mplace(const_alloc).unwrap();
6367
debug!(?place);
6468

65-
let valtree_result = const_to_valtree_inner(&ecx, &place);
69+
let mut num_nodes = 0;
70+
let valtree_result = const_to_valtree_inner(&ecx, &place, &mut num_nodes);
6671

6772
match valtree_result {
6873
Ok(valtree) => Ok(Some(valtree)),
69-
Err(_) => Ok(None),
74+
Err(err) => {
75+
let did = cid.instance.def_id();
76+
let s = cid.display(tcx);
77+
match err {
78+
ValTreeCreationError::NodesOverflow => {
79+
let msg = format!("maximum number of nodes exceeded in constant {}", &s);
80+
let mut diag = match tcx.hir().span_if_local(did) {
81+
Some(span) => tcx.sess.struct_span_err(span, &msg),
82+
None => tcx.sess.struct_err(&msg),
83+
};
84+
diag.emit();
85+
86+
Ok(None)
87+
}
88+
ValTreeCreationError::NonSupportedType | ValTreeCreationError::Other => Ok(None),
89+
}
90+
}
7091
}
7192
}
7293

@@ -75,7 +96,7 @@ pub(crate) fn eval_to_valtree<'tcx>(
7596
pub(crate) fn try_destructure_const<'tcx>(
7697
tcx: TyCtxt<'tcx>,
7798
const_: ty::Const<'tcx>,
78-
) -> Option<mir::DestructuredConst<'tcx>> {
99+
) -> Option<ty::DestructuredConst<'tcx>> {
79100
if let ty::ConstKind::Value(valtree) = const_.val() {
80101
let branches = match valtree {
81102
ty::ValTree::Branch(b) => b,
@@ -141,7 +162,7 @@ pub(crate) fn try_destructure_const<'tcx>(
141162

142163
let fields = tcx.arena.alloc_from_iter(fields.into_iter());
143164

144-
Some(mir::DestructuredConst { variant, fields })
165+
Some(ty::DestructuredConst { variant, fields })
145166
} else {
146167
None
147168
}

compiler/rustc_const_eval/src/const_eval/valtrees.rs

+21-7
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use super::eval_queries::{mk_eval_cx, op_to_const};
22
use super::machine::CompileTimeEvalContext;
3-
use super::{ValTreeCreationError, ValTreeCreationResult};
3+
use super::{ValTreeCreationError, ValTreeCreationResult, VALTREE_MAX_NODES};
44
use crate::interpret::{
55
intern_const_alloc_recursive, ConstValue, ImmTy, Immediate, InternKind, MemPlaceMeta,
66
MemoryKind, PlaceTy, Scalar, ScalarMaybeUninit,
@@ -16,6 +16,7 @@ fn branches<'tcx>(
1616
place: &MPlaceTy<'tcx>,
1717
n: usize,
1818
variant: Option<VariantIdx>,
19+
num_nodes: &mut usize,
1920
) -> ValTreeCreationResult<'tcx> {
2021
let place = match variant {
2122
Some(variant) => ecx.mplace_downcast(&place, variant).unwrap(),
@@ -27,7 +28,7 @@ fn branches<'tcx>(
2728
let mut fields = Vec::with_capacity(n);
2829
for i in 0..n {
2930
let field = ecx.mplace_field(&place, i).unwrap();
30-
let valtree = const_to_valtree_inner(ecx, &field)?;
31+
let valtree = const_to_valtree_inner(ecx, &field, num_nodes)?;
3132
fields.push(Some(valtree));
3233
}
3334

@@ -39,13 +40,19 @@ fn branches<'tcx>(
3940
.collect::<Option<Vec<_>>>()
4041
.expect("should have already checked for errors in ValTree creation");
4142

43+
// Have to account for ZSTs here
44+
if branches.len() == 0 {
45+
*num_nodes += 1;
46+
}
47+
4248
Ok(ty::ValTree::Branch(ecx.tcx.arena.alloc_from_iter(branches)))
4349
}
4450

4551
#[instrument(skip(ecx), level = "debug")]
4652
fn slice_branches<'tcx>(
4753
ecx: &CompileTimeEvalContext<'tcx, 'tcx>,
4854
place: &MPlaceTy<'tcx>,
55+
num_nodes: &mut usize,
4956
) -> ValTreeCreationResult<'tcx> {
5057
let n = place
5158
.len(&ecx.tcx.tcx)
@@ -54,7 +61,7 @@ fn slice_branches<'tcx>(
5461
let mut elems = Vec::with_capacity(n as usize);
5562
for i in 0..n {
5663
let place_elem = ecx.mplace_index(place, i).unwrap();
57-
let valtree = const_to_valtree_inner(ecx, &place_elem)?;
64+
let valtree = const_to_valtree_inner(ecx, &place_elem, num_nodes)?;
5865
elems.push(valtree);
5966
}
6067

@@ -65,19 +72,26 @@ fn slice_branches<'tcx>(
6572
pub(crate) fn const_to_valtree_inner<'tcx>(
6673
ecx: &CompileTimeEvalContext<'tcx, 'tcx>,
6774
place: &MPlaceTy<'tcx>,
75+
num_nodes: &mut usize,
6876
) -> ValTreeCreationResult<'tcx> {
6977
let ty = place.layout.ty;
7078
debug!("ty kind: {:?}", ty.kind());
7179

80+
if *num_nodes >= VALTREE_MAX_NODES {
81+
return Err(ValTreeCreationError::NodesOverflow);
82+
}
83+
7284
match ty.kind() {
7385
ty::FnDef(..) => {
86+
*num_nodes += 1;
7487
Ok(ty::ValTree::zst())
7588
}
7689
ty::Bool | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Char => {
7790
let Ok(val) = ecx.read_immediate(&place.into()) else {
7891
return Err(ValTreeCreationError::Other);
7992
};
8093
let val = val.to_scalar().unwrap();
94+
*num_nodes += 1;
8195

8296
Ok(ty::ValTree::Leaf(val.assert_int()))
8397
}
@@ -94,11 +108,11 @@ pub(crate) fn const_to_valtree_inner<'tcx>(
94108
};
95109
debug!(?derefd_place);
96110

97-
const_to_valtree_inner(ecx, &derefd_place)
111+
const_to_valtree_inner(ecx, &derefd_place, num_nodes)
98112
}
99113

100114
ty::Str | ty::Slice(_) | ty::Array(_, _) => {
101-
slice_branches(ecx, place)
115+
slice_branches(ecx, place, num_nodes)
102116
}
103117
// Trait objects are not allowed in type level constants, as we have no concept for
104118
// resolving their backing type, even if we can do that at const eval time. We may
@@ -107,7 +121,7 @@ pub(crate) fn const_to_valtree_inner<'tcx>(
107121
ty::Dynamic(..) => Err(ValTreeCreationError::NonSupportedType),
108122

109123
ty::Tuple(elem_tys) => {
110-
branches(ecx, place, elem_tys.len(), None)
124+
branches(ecx, place, elem_tys.len(), None, num_nodes)
111125
}
112126

113127
ty::Adt(def, _) => {
@@ -120,7 +134,7 @@ pub(crate) fn const_to_valtree_inner<'tcx>(
120134
let Ok((_, variant)) = ecx.read_discriminant(&place.into()) else {
121135
return Err(ValTreeCreationError::Other);
122136
};
123-
branches(ecx, place, def.variant(variant).fields.len(), def.is_enum().then_some(variant))
137+
branches(ecx, place, def.variant(variant).fields.len(), def.is_enum().then_some(variant), num_nodes)
124138
}
125139

126140
ty::Never

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ impl<'tcx> TyCtxtAt<'tcx> {
194194
impl<'tcx> TyCtxt<'tcx> {
195195
/// Destructure a type-level constant ADT or array into its variant index and its field values.
196196
/// Panics if the destructuring fails, use `try_destructure_const` for fallible version.
197-
pub fn destructure_const(self, const_: ty::Const<'tcx>) -> mir::DestructuredConst<'tcx> {
197+
pub fn destructure_const(self, const_: ty::Const<'tcx>) -> ty::DestructuredConst<'tcx> {
198198
self.try_destructure_const(const_).unwrap()
199199
}
200200

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

-1
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,6 @@ impl<'tcx> ConstValue<'tcx> {
7878
Some(self.try_to_scalar()?.assert_int())
7979
}
8080

81-
#[inline(always)]
8281
pub fn try_to_bits(&self, size: Size) -> Option<u128> {
8382
self.try_to_scalar_int()?.to_bits(size).ok()
8483
}

compiler/rustc_middle/src/query/mod.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -967,26 +967,26 @@ rustc_queries! {
967967
query eval_to_valtree(
968968
key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>
969969
) -> EvalToValTreeResult<'tcx> {
970-
desc { "evaluate type-level constant" }
970+
desc { "evaluating type-level constant" }
971971
}
972972

973973
/// Converts a type level constant value into `ConstValue`
974974
query valtree_to_const_val(key: (Ty<'tcx>, ty::ValTree<'tcx>)) -> ConstValue<'tcx> {
975-
desc { "convert type-level constant value to mir constant value"}
975+
desc { "converting type-level constant value to mir constant value"}
976976
}
977977

978978
/// Destructure a constant ADT or array into its variant index and its
979979
/// field values or return `None` if constant is invalid.
980980
///
981981
/// Use infallible `TyCtxt::destructure_const` when you know that constant is valid.
982-
query try_destructure_const(key: ty::Const<'tcx>) -> Option<mir::DestructuredConst<'tcx>> {
983-
desc { "destructure type level constant"}
982+
query try_destructure_const(key: ty::Const<'tcx>) -> Option<ty::DestructuredConst<'tcx>> {
983+
desc { "destructuring type level constant"}
984984
}
985985

986986
/// Tries to destructure an `mir::ConstantKind` ADT or array into its variant index
987987
/// and its field values.
988988
query try_destructure_mir_constant(key: ty::ParamEnvAnd<'tcx, mir::ConstantKind<'tcx>>) -> Option<mir::DestructuredMirConstant<'tcx>> {
989-
desc { "destructure mir constant"}
989+
desc { "destructuring mir constant"}
990990
remap_env_constness
991991
}
992992

@@ -995,7 +995,7 @@ rustc_queries! {
995995
query deref_mir_constant(
996996
key: ty::ParamEnvAnd<'tcx, mir::ConstantKind<'tcx>>
997997
) -> mir::ConstantKind<'tcx> {
998-
desc { "deref constant" }
998+
desc { "dereferencing mir constant" }
999999
remap_env_constness
10001000
}
10011001

compiler/rustc_middle/src/ty/mod.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@ use rustc_query_system::ich::StableHashingContext;
4242
use rustc_session::cstore::CrateStoreDyn;
4343
use rustc_span::symbol::{kw, sym, Ident, Symbol};
4444
use rustc_span::Span;
45-
use rustc_target::abi::Align;
4645
pub use subst::*;
46+
use rustc_target::abi::{Align, VariantIdx};
4747
pub use vtable::*;
4848

4949
use std::fmt::Debug;
@@ -2453,3 +2453,10 @@ pub struct FoundRelationships {
24532453
/// _>::AssocType = ?T`
24542454
pub output: bool,
24552455
}
2456+
2457+
/// The constituent parts of a type level constant of kind ADT or array.
2458+
#[derive(Copy, Clone, Debug, HashStable)]
2459+
pub struct DestructuredConst<'tcx> {
2460+
pub variant: Option<VariantIdx>,
2461+
pub fields: &'tcx [ty::Const<'tcx>],
2462+
}

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

+1
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ pub trait Printer<'tcx>: Sized {
9898

9999
// Defaults (should not be overridden):
100100

101+
#[instrument(skip(self), level = "debug")]
101102
fn default_print_def_path(
102103
self,
103104
def_id: DefId,

compiler/rustc_middle/src/ty/print/pretty.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -1460,9 +1460,7 @@ pub trait PrettyPrinter<'tcx>:
14601460
return Ok(self);
14611461
}
14621462
// Aggregates, printed as array/tuple/struct/variant construction syntax.
1463-
(ty::ValTree::Branch(_), ty::Array(..) | ty::Tuple(..) | ty::Adt(..))
1464-
if !ty.has_param_types_or_consts() =>
1465-
{
1463+
(ty::ValTree::Branch(_), ty::Array(..) | ty::Tuple(..) | ty::Adt(..)) => {
14661464
let Some(contents) = self.tcx().try_destructure_const(
14671465
ty::Const::from_value(self.tcx(), valtree, ty)
14681466
) else {

0 commit comments

Comments
 (0)