1
- use rustc_macros:: { HashStable , TyDecodable , TyEncodable , TypeFoldable , TypeVisitable } ;
1
+ use std:: fmt;
2
+ use std:: ops:: Deref ;
3
+
4
+ use rustc_data_structures:: intern:: Interned ;
5
+ use rustc_macros:: { HashStable , Lift , TyDecodable , TyEncodable , TypeFoldable , TypeVisitable } ;
2
6
3
7
use super :: ScalarInt ;
4
8
use crate :: mir:: interpret:: Scalar ;
@@ -16,9 +20,9 @@ use crate::ty::{self, Ty, TyCtxt};
16
20
///
17
21
/// `ValTree` does not have this problem with representation, as it only contains integers or
18
22
/// lists of (nested) `ValTree`.
19
- #[ derive( Copy , Clone , Debug , Hash , Eq , PartialEq ) ]
23
+ #[ derive( Clone , Debug , Hash , Eq , PartialEq ) ]
20
24
#[ derive( HashStable , TyEncodable , TyDecodable ) ]
21
- pub enum ValTree < ' tcx > {
25
+ pub enum ValTreeKind < ' tcx > {
22
26
/// integers, `bool`, `char` are represented as scalars.
23
27
/// See the `ScalarInt` documentation for how `ScalarInt` guarantees that equal values
24
28
/// of these types have the same representation.
@@ -33,58 +37,97 @@ pub enum ValTree<'tcx> {
33
37
/// the fields of the variant.
34
38
///
35
39
/// ZST types are represented as an empty slice.
36
- Branch ( & ' tcx [ ValTree < ' tcx > ] ) ,
40
+ Branch ( Box < [ ValTree < ' tcx > ] > ) ,
37
41
}
38
42
39
- impl < ' tcx > ValTree < ' tcx > {
40
- pub fn zst ( ) -> Self {
41
- Self :: Branch ( & [ ] )
42
- }
43
-
43
+ impl < ' tcx > ValTreeKind < ' tcx > {
44
44
#[ inline]
45
- pub fn unwrap_leaf ( self ) -> ScalarInt {
45
+ pub fn unwrap_leaf ( & self ) -> ScalarInt {
46
46
match self {
47
- Self :: Leaf ( s) => s,
47
+ Self :: Leaf ( s) => * s,
48
48
_ => bug ! ( "expected leaf, got {:?}" , self ) ,
49
49
}
50
50
}
51
51
52
52
#[ inline]
53
- pub fn unwrap_branch ( self ) -> & ' tcx [ Self ] {
53
+ pub fn unwrap_branch ( & self ) -> & [ ValTree < ' tcx > ] {
54
54
match self {
55
- Self :: Branch ( branch) => branch,
55
+ Self :: Branch ( branch) => & * * branch,
56
56
_ => bug ! ( "expected branch, got {:?}" , self ) ,
57
57
}
58
58
}
59
59
60
- pub fn from_raw_bytes < ' a > ( tcx : TyCtxt < ' tcx > , bytes : & ' a [ u8 ] ) -> Self {
61
- let branches = bytes . iter ( ) . map ( |b| Self :: Leaf ( ScalarInt :: from ( * b ) ) ) ;
62
- let interned = tcx . arena . alloc_from_iter ( branches ) ;
60
+ pub fn try_to_scalar ( & self ) -> Option < Scalar > {
61
+ self . try_to_scalar_int ( ) . map ( Scalar :: Int )
62
+ }
63
63
64
- Self :: Branch ( interned)
64
+ pub fn try_to_scalar_int ( & self ) -> Option < ScalarInt > {
65
+ match self {
66
+ Self :: Leaf ( s) => Some ( * s) ,
67
+ Self :: Branch ( _) => None ,
68
+ }
65
69
}
66
70
67
- pub fn from_scalar_int ( i : ScalarInt ) -> Self {
68
- Self :: Leaf ( i)
71
+ pub fn try_to_branch ( & self ) -> Option < & [ ValTree < ' tcx > ] > {
72
+ match self {
73
+ Self :: Branch ( branch) => Some ( & * * branch) ,
74
+ Self :: Leaf ( _) => None ,
75
+ }
69
76
}
77
+ }
70
78
71
- pub fn try_to_scalar ( self ) -> Option < Scalar > {
72
- self . try_to_scalar_int ( ) . map ( Scalar :: Int )
79
+ /// An interned valtree. Use this rather than `ValTreeKind`, whenever possible.
80
+ ///
81
+ /// See the docs of [`ValTreeKind`] or the [dev guide] for an explanation of this type.
82
+ ///
83
+ /// [dev guide]: https://rustc-dev-guide.rust-lang.org/mir/index.html#valtrees
84
+ #[ derive( Copy , Clone , Hash , Eq , PartialEq ) ]
85
+ #[ derive( HashStable ) ]
86
+ pub struct ValTree < ' tcx > ( pub ( crate ) Interned < ' tcx , ValTreeKind < ' tcx > > ) ;
87
+
88
+ impl < ' tcx > ValTree < ' tcx > {
89
+ pub fn zst ( tcx : TyCtxt < ' tcx > ) -> Self {
90
+ tcx. consts . valtree_zst
73
91
}
74
92
75
- pub fn try_to_scalar_int ( self ) -> Option < ScalarInt > {
76
- match self {
77
- Self :: Leaf ( s) => Some ( s) ,
78
- Self :: Branch ( _) => None ,
79
- }
93
+ pub fn is_zst ( self ) -> bool {
94
+ matches ! ( * self , ValTreeKind :: Branch ( box [ ] ) )
95
+ }
96
+
97
+ pub fn from_raw_bytes ( tcx : TyCtxt < ' tcx > , bytes : & [ u8 ] ) -> Self {
98
+ let branches = bytes. iter ( ) . map ( |& b| Self :: from_scalar_int ( tcx, b. into ( ) ) ) ;
99
+ Self :: from_branches ( tcx, branches)
100
+ }
101
+
102
+ pub fn from_branches ( tcx : TyCtxt < ' tcx > , branches : impl IntoIterator < Item = Self > ) -> Self {
103
+ tcx. mk_valtree ( ValTreeKind :: Branch ( branches. into_iter ( ) . collect ( ) ) )
104
+ }
105
+
106
+ pub fn from_scalar_int ( tcx : TyCtxt < ' tcx > , i : ScalarInt ) -> Self {
107
+ tcx. mk_valtree ( ValTreeKind :: Leaf ( i) )
108
+ }
109
+ }
110
+
111
+ impl < ' tcx > Deref for ValTree < ' tcx > {
112
+ type Target = & ' tcx ValTreeKind < ' tcx > ;
113
+
114
+ #[ inline]
115
+ fn deref ( & self ) -> & & ' tcx ValTreeKind < ' tcx > {
116
+ & self . 0 . 0
117
+ }
118
+ }
119
+
120
+ impl fmt:: Debug for ValTree < ' _ > {
121
+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
122
+ ( * * self ) . fmt ( f)
80
123
}
81
124
}
82
125
83
126
/// A type-level constant value.
84
127
///
85
128
/// Represents a typed, fully evaluated constant.
86
129
#[ derive( Copy , Clone , Debug , Hash , Eq , PartialEq ) ]
87
- #[ derive( HashStable , TyEncodable , TyDecodable , TypeFoldable , TypeVisitable ) ]
130
+ #[ derive( HashStable , TyEncodable , TyDecodable , TypeFoldable , TypeVisitable , Lift ) ]
88
131
pub struct Value < ' tcx > {
89
132
pub ty : Ty < ' tcx > ,
90
133
pub valtree : ValTree < ' tcx > ,
0 commit comments