1
1
use super :: eval_queries:: { mk_eval_cx, op_to_const} ;
2
2
use super :: machine:: CompileTimeEvalContext ;
3
- use super :: { ValTreeCreationError , ValTreeCreationResult } ;
3
+ use super :: { ValTreeCreationError , ValTreeCreationResult , VALTREE_MAX_NODES } ;
4
4
use crate :: interpret:: {
5
5
intern_const_alloc_recursive, ConstValue , ImmTy , Immediate , InternKind , MemPlaceMeta ,
6
6
MemoryKind , PlaceTy , Scalar , ScalarMaybeUninit ,
@@ -16,6 +16,7 @@ fn branches<'tcx>(
16
16
place : & MPlaceTy < ' tcx > ,
17
17
n : usize ,
18
18
variant : Option < VariantIdx > ,
19
+ num_nodes : & mut usize ,
19
20
) -> ValTreeCreationResult < ' tcx > {
20
21
let place = match variant {
21
22
Some ( variant) => ecx. mplace_downcast ( & place, variant) . unwrap ( ) ,
@@ -27,7 +28,7 @@ fn branches<'tcx>(
27
28
let mut fields = Vec :: with_capacity ( n) ;
28
29
for i in 0 ..n {
29
30
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 ) ?;
31
32
fields. push ( Some ( valtree) ) ;
32
33
}
33
34
@@ -39,13 +40,19 @@ fn branches<'tcx>(
39
40
. collect :: < Option < Vec < _ > > > ( )
40
41
. expect ( "should have already checked for errors in ValTree creation" ) ;
41
42
43
+ // Have to account for ZSTs here
44
+ if branches. len ( ) == 0 {
45
+ * num_nodes += 1 ;
46
+ }
47
+
42
48
Ok ( ty:: ValTree :: Branch ( ecx. tcx . arena . alloc_from_iter ( branches) ) )
43
49
}
44
50
45
51
#[ instrument( skip( ecx) , level = "debug" ) ]
46
52
fn slice_branches < ' tcx > (
47
53
ecx : & CompileTimeEvalContext < ' tcx , ' tcx > ,
48
54
place : & MPlaceTy < ' tcx > ,
55
+ num_nodes : & mut usize ,
49
56
) -> ValTreeCreationResult < ' tcx > {
50
57
let n = place
51
58
. len ( & ecx. tcx . tcx )
@@ -54,7 +61,7 @@ fn slice_branches<'tcx>(
54
61
let mut elems = Vec :: with_capacity ( n as usize ) ;
55
62
for i in 0 ..n {
56
63
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 ) ?;
58
65
elems. push ( valtree) ;
59
66
}
60
67
@@ -65,19 +72,26 @@ fn slice_branches<'tcx>(
65
72
pub ( crate ) fn const_to_valtree_inner < ' tcx > (
66
73
ecx : & CompileTimeEvalContext < ' tcx , ' tcx > ,
67
74
place : & MPlaceTy < ' tcx > ,
75
+ num_nodes : & mut usize ,
68
76
) -> ValTreeCreationResult < ' tcx > {
69
77
let ty = place. layout . ty ;
70
78
debug ! ( "ty kind: {:?}" , ty. kind( ) ) ;
71
79
80
+ if * num_nodes >= VALTREE_MAX_NODES {
81
+ return Err ( ValTreeCreationError :: NodesOverflow ) ;
82
+ }
83
+
72
84
match ty. kind ( ) {
73
85
ty:: FnDef ( ..) => {
86
+ * num_nodes += 1 ;
74
87
Ok ( ty:: ValTree :: zst ( ) )
75
88
}
76
89
ty:: Bool | ty:: Int ( _) | ty:: Uint ( _) | ty:: Float ( _) | ty:: Char => {
77
90
let Ok ( val) = ecx. read_immediate ( & place. into ( ) ) else {
78
91
return Err ( ValTreeCreationError :: Other ) ;
79
92
} ;
80
93
let val = val. to_scalar ( ) . unwrap ( ) ;
94
+ * num_nodes += 1 ;
81
95
82
96
Ok ( ty:: ValTree :: Leaf ( val. assert_int ( ) ) )
83
97
}
@@ -94,11 +108,11 @@ pub(crate) fn const_to_valtree_inner<'tcx>(
94
108
} ;
95
109
debug ! ( ?derefd_place) ;
96
110
97
- const_to_valtree_inner ( ecx, & derefd_place)
111
+ const_to_valtree_inner ( ecx, & derefd_place, num_nodes )
98
112
}
99
113
100
114
ty:: Str | ty:: Slice ( _) | ty:: Array ( _, _) => {
101
- slice_branches ( ecx, place)
115
+ slice_branches ( ecx, place, num_nodes )
102
116
}
103
117
// Trait objects are not allowed in type level constants, as we have no concept for
104
118
// 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>(
107
121
ty:: Dynamic ( ..) => Err ( ValTreeCreationError :: NonSupportedType ) ,
108
122
109
123
ty:: Tuple ( elem_tys) => {
110
- branches ( ecx, place, elem_tys. len ( ) , None )
124
+ branches ( ecx, place, elem_tys. len ( ) , None , num_nodes )
111
125
}
112
126
113
127
ty:: Adt ( def, _) => {
@@ -120,7 +134,7 @@ pub(crate) fn const_to_valtree_inner<'tcx>(
120
134
let Ok ( ( _, variant) ) = ecx. read_discriminant ( & place. into ( ) ) else {
121
135
return Err ( ValTreeCreationError :: Other ) ;
122
136
} ;
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 )
124
138
}
125
139
126
140
ty:: Never
0 commit comments