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 } ;
26
37use super :: ScalarInt ;
48use crate :: mir:: interpret:: Scalar ;
@@ -16,9 +20,9 @@ use crate::ty::{self, Ty, TyCtxt};
1620///
1721/// `ValTree` does not have this problem with representation, as it only contains integers or
1822/// lists of (nested) `ValTree`.
19- #[ derive( Copy , Clone , Debug , Hash , Eq , PartialEq ) ]
23+ #[ derive( Clone , Debug , Hash , Eq , PartialEq ) ]
2024#[ derive( HashStable , TyEncodable , TyDecodable ) ]
21- pub enum ValTree < ' tcx > {
25+ pub enum ValTreeKind < ' tcx > {
2226 /// integers, `bool`, `char` are represented as scalars.
2327 /// See the `ScalarInt` documentation for how `ScalarInt` guarantees that equal values
2428 /// of these types have the same representation.
@@ -33,58 +37,98 @@ pub enum ValTree<'tcx> {
3337 /// the fields of the variant.
3438 ///
3539 /// ZST types are represented as an empty slice.
36- Branch ( & ' tcx [ ValTree < ' tcx > ] ) ,
40+ Branch ( Box < [ ValTree < ' tcx > ] > ) ,
3741}
3842
39- impl < ' tcx > ValTree < ' tcx > {
40- pub fn zst ( ) -> Self {
41- Self :: Branch ( & [ ] )
42- }
43-
43+ impl < ' tcx > ValTreeKind < ' tcx > {
4444 #[ inline]
45- pub fn unwrap_leaf ( self ) -> ScalarInt {
45+ pub fn unwrap_leaf ( & self ) -> ScalarInt {
4646 match self {
47- Self :: Leaf ( s) => s,
47+ Self :: Leaf ( s) => * s,
4848 _ => bug ! ( "expected leaf, got {:?}" , self ) ,
4949 }
5050 }
5151
5252 #[ inline]
53- pub fn unwrap_branch ( self ) -> & ' tcx [ Self ] {
53+ pub fn unwrap_branch ( & self ) -> & [ ValTree < ' tcx > ] {
5454 match self {
55- Self :: Branch ( branch) => branch,
55+ Self :: Branch ( branch) => & * * branch,
5656 _ => bug ! ( "expected branch, got {:?}" , self ) ,
5757 }
5858 }
5959
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+ }
6363
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+ }
6569 }
6670
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+ }
6976 }
77+ }
7078
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+ /// Returns the zero-sized valtree: `Branch([])`.
90+ pub fn zst ( tcx : TyCtxt < ' tcx > ) -> Self {
91+ tcx. consts . valtree_zst
7392 }
7493
75- pub fn try_to_scalar_int ( self ) -> Option < ScalarInt > {
76- match self {
77- Self :: Leaf ( s) => Some ( s) ,
78- Self :: Branch ( _) => None ,
79- }
94+ pub fn is_zst ( self ) -> bool {
95+ matches ! ( * self , ValTreeKind :: Branch ( box [ ] ) )
96+ }
97+
98+ pub fn from_raw_bytes ( tcx : TyCtxt < ' tcx > , bytes : & [ u8 ] ) -> Self {
99+ let branches = bytes. iter ( ) . map ( |& b| Self :: from_scalar_int ( tcx, b. into ( ) ) ) ;
100+ Self :: from_branches ( tcx, branches)
101+ }
102+
103+ pub fn from_branches ( tcx : TyCtxt < ' tcx > , branches : impl IntoIterator < Item = Self > ) -> Self {
104+ tcx. intern_valtree ( ValTreeKind :: Branch ( branches. into_iter ( ) . collect ( ) ) )
105+ }
106+
107+ pub fn from_scalar_int ( tcx : TyCtxt < ' tcx > , i : ScalarInt ) -> Self {
108+ tcx. intern_valtree ( ValTreeKind :: Leaf ( i) )
109+ }
110+ }
111+
112+ impl < ' tcx > Deref for ValTree < ' tcx > {
113+ type Target = & ' tcx ValTreeKind < ' tcx > ;
114+
115+ #[ inline]
116+ fn deref ( & self ) -> & & ' tcx ValTreeKind < ' tcx > {
117+ & self . 0 . 0
118+ }
119+ }
120+
121+ impl fmt:: Debug for ValTree < ' _ > {
122+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
123+ ( * * self ) . fmt ( f)
80124 }
81125}
82126
83127/// A type-level constant value.
84128///
85129/// Represents a typed, fully evaluated constant.
86130#[ derive( Copy , Clone , Debug , Hash , Eq , PartialEq ) ]
87- #[ derive( HashStable , TyEncodable , TyDecodable , TypeFoldable , TypeVisitable ) ]
131+ #[ derive( HashStable , TyEncodable , TyDecodable , TypeFoldable , TypeVisitable , Lift ) ]
88132pub struct Value < ' tcx > {
89133 pub ty : Ty < ' tcx > ,
90134 pub valtree : ValTree < ' tcx > ,
0 commit comments