11use super :: eval_queries:: { mk_eval_cx, op_to_const} ;
22use super :: machine:: CompileTimeEvalContext ;
3- use super :: { ValTreeCreationError , ValTreeCreationResult } ;
3+ use super :: { ValTreeCreationError , ValTreeCreationResult , VALTREE_MAX_NODES } ;
44use 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" ) ]
4652fn 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>(
6572pub ( 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
0 commit comments