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