1use rustc_macros::extension;
2use rustc_span::bug;
3use rustc_type_ir::walk::TypeWalker;
4use rustc_type_ir::{selfas ir};
56use crate::mir::interpret::Scalar;
7use crate::ty::{self, Ty, TyCtxt};
89mod int;
10mod kind;
11mod lit;
12mod valtree;
1314pub use int::*;
15pub use kind::*;
16pub use lit::*;
17pub use valtree::*;
1819pub type ConstKind<'tcx> = ir::ConstKind<TyCtxt<'tcx>>;
20pub type AliasConst<'tcx> = ir::AliasConst<TyCtxt<'tcx>>;
21pub type AliasConstKind<'tcx> = ir::AliasConstKind<TyCtxt<'tcx>>;
22pub type Const<'tcx> = ir::Const<TyCtxt<'tcx>>;
2324#[cfg(target_pointer_width = "64")]
25const _: [(); 32] = [(); ::std::mem::size_of::<ConstKind<'_>>()];rustc_data_structures::static_assert_size!(ConstKind<'_>, 32);
2627pub trait ConstExt<'tcx> {
#[doc =
" Creates a constant with the given integer value and interns it."]
fn from_bits(tcx: TyCtxt<'tcx>, bits: u128,
typing_env: ty::TypingEnv<'tcx>, ty: Ty<'tcx>)
-> Self;
#[doc = " Creates an interned zst constant."]
fn zero_sized(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>)
-> Self;
fn new_value(tcx: TyCtxt<'tcx>, valtree: ty::ValTree<'tcx>, ty: Ty<'tcx>)
-> Const<'tcx>;
#[doc = " Creates an interned bool constant."]
fn from_bool(tcx: TyCtxt<'tcx>, v: bool)
-> Self;
#[doc = " Creates an interned usize constant."]
fn from_target_usize(tcx: TyCtxt<'tcx>, n: u64)
-> Self;
#[doc = " Panics if `self.kind != ty::ConstKind::Value`."]
fn to_value(self)
-> ty::Value<'tcx>;
#[doc = " Attempts to convert to a value."]
#[doc = ""]
#[doc = " Note that this does not normalize the constant."]
fn try_to_value(self)
-> Option<ty::Value<'tcx>>;
#[doc = " Converts to a `ValTreeKind::Leaf` value, `panic`\'ing"]
#[doc = " if this constant is some other kind."]
#[doc = ""]
#[doc = " Note that this does not normalize the constant."]
fn to_leaf(self)
-> ScalarInt;
#[doc = " Converts to a `ValTreeKind::Branch` value, `panic`\'ing"]
#[doc = " if this constant is some other kind."]
#[doc = ""]
#[doc = " Note that this does not normalize the constant."]
fn to_branch(self)
-> &'tcx [ty::Const<'tcx>];
#[doc = " Attempts to convert to a `ValTreeKind::Leaf` value."]
#[doc = ""]
#[doc = " Note that this does not normalize the constant."]
fn try_to_leaf(self)
-> Option<ScalarInt>;
#[doc = " Attempts to convert to a `ValTreeKind::Leaf` value."]
#[doc = ""]
#[doc = " Note that this does not normalize the constant."]
fn try_to_scalar(self)
-> Option<Scalar>;
#[doc = " Attempts to convert to a `ValTreeKind::Branch` value."]
#[doc = ""]
#[doc = " Note that this does not normalize the constant."]
fn try_to_branch(self)
-> Option<&'tcx [ty::Const<'tcx>]>;
#[doc = " Convenience method to extract the value of a usize constant,"]
#[doc = " useful to get the length of an array type."]
#[doc = ""]
#[doc = " Note that this does not evaluate the constant."]
fn try_to_target_usize(self, tcx: TyCtxt<'tcx>)
-> Option<u64>;
#[doc = " Iterator that walks `self` and any types reachable from"]
#[doc = " `self`, in depth-first order. Note that just walks the types"]
#[doc = " that appear in `self`, it does not descend into the fields of"]
#[doc = " structs or variants. For example:"]
#[doc = ""]
#[doc = " ```text"]
#[doc = " isize => { isize }"]
#[doc = " Foo<Bar<isize>> => { Foo<Bar<isize>>, Bar<isize>, isize }"]
#[doc = " [isize] => { [isize], isize }"]
#[doc = " ```"]
fn walk(self)
-> TypeWalker<TyCtxt<'tcx>>;
}
impl<'tcx> ConstExt<'tcx> for Const<'tcx> {
#[doc =
" Creates a constant with the given integer value and interns it."]
#[inline]
fn from_bits(tcx: TyCtxt<'tcx>, bits: u128,
typing_env: ty::TypingEnv<'tcx>, ty: Ty<'tcx>) -> Self {
let size =
tcx.layout_of(typing_env.as_query_input(ty)).unwrap_or_else(|e|
{
::core::panicking::panic_fmt(format_args!("could not compute layout for {0:?}: {1:?}",
ty, e));
}).size;
let valtree =
ty::ValTree::from_scalar_int(tcx,
ScalarInt::try_from_uint(bits, size).unwrap());
ty::Const::new_value(tcx, valtree, ty)
}
#[inline]
#[doc = " Creates an interned zst constant."]
fn zero_sized(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Self {
ty::Const::new_value(tcx, ty::ValTree::zst(tcx), ty)
}
#[inline]
fn new_value(tcx: TyCtxt<'tcx>, valtree: ty::ValTree<'tcx>, ty: Ty<'tcx>)
-> Const<'tcx> {
Const::new(tcx, ty::ConstKind::Value(ty::Value { ty, valtree }))
}
#[inline]
#[doc = " Creates an interned bool constant."]
fn from_bool(tcx: TyCtxt<'tcx>, v: bool) -> Self {
Self::from_bits(tcx, v as u128, ty::TypingEnv::fully_monomorphized(),
tcx.types.bool)
}
#[inline]
#[doc = " Creates an interned usize constant."]
fn from_target_usize(tcx: TyCtxt<'tcx>, n: u64) -> Self {
Self::from_bits(tcx, n as u128, ty::TypingEnv::fully_monomorphized(),
tcx.types.usize)
}
#[doc = " Panics if `self.kind != ty::ConstKind::Value`."]
fn to_value(self) -> ty::Value<'tcx> {
match self.kind() {
ty::ConstKind::Value(cv) => cv,
_ =>
::rustc_span::macros::bug_impl(None,
format_args!("expected ConstKind::Value, got {0:?}",
self.kind()), Location::caller()),
}
}
#[doc = " Attempts to convert to a value."]
#[doc = ""]
#[doc = " Note that this does not normalize the constant."]
fn try_to_value(self) -> Option<ty::Value<'tcx>> {
match self.kind() { ty::ConstKind::Value(cv) => Some(cv), _ => None, }
}
#[doc = " Converts to a `ValTreeKind::Leaf` value, `panic`\'ing"]
#[doc = " if this constant is some other kind."]
#[doc = ""]
#[doc = " Note that this does not normalize the constant."]
#[inline]
fn to_leaf(self) -> ScalarInt { self.to_value().to_leaf() }
#[doc = " Converts to a `ValTreeKind::Branch` value, `panic`\'ing"]
#[doc = " if this constant is some other kind."]
#[doc = ""]
#[doc = " Note that this does not normalize the constant."]
#[inline]
fn to_branch(self) -> &'tcx [ty::Const<'tcx>] {
self.to_value().to_branch()
}
#[doc = " Attempts to convert to a `ValTreeKind::Leaf` value."]
#[doc = ""]
#[doc = " Note that this does not normalize the constant."]
fn try_to_leaf(self) -> Option<ScalarInt> {
self.try_to_value()?.try_to_leaf()
}
#[doc = " Attempts to convert to a `ValTreeKind::Leaf` value."]
#[doc = ""]
#[doc = " Note that this does not normalize the constant."]
fn try_to_scalar(self) -> Option<Scalar> {
self.try_to_leaf().map(Scalar::Int)
}
#[doc = " Attempts to convert to a `ValTreeKind::Branch` value."]
#[doc = ""]
#[doc = " Note that this does not normalize the constant."]
fn try_to_branch(self) -> Option<&'tcx [ty::Const<'tcx>]> {
self.try_to_value()?.try_to_branch()
}
#[doc = " Convenience method to extract the value of a usize constant,"]
#[doc = " useful to get the length of an array type."]
#[doc = ""]
#[doc = " Note that this does not evaluate the constant."]
#[inline]
fn try_to_target_usize(self, tcx: TyCtxt<'tcx>) -> Option<u64> {
self.try_to_value()?.try_to_target_usize(tcx)
}
#[doc = " Iterator that walks `self` and any types reachable from"]
#[doc = " `self`, in depth-first order. Note that just walks the types"]
#[doc = " that appear in `self`, it does not descend into the fields of"]
#[doc = " structs or variants. For example:"]
#[doc = ""]
#[doc = " ```text"]
#[doc = " isize => { isize }"]
#[doc = " Foo<Bar<isize>> => { Foo<Bar<isize>>, Bar<isize>, isize }"]
#[doc = " [isize] => { [isize], isize }"]
#[doc = " ```"]
fn walk(self) -> TypeWalker<TyCtxt<'tcx>> { TypeWalker::new(self.into()) }
}#[extension(pub trait ConstExt<'tcx>)]28impl<'tcx> Const<'tcx> {
29/// Creates a constant with the given integer value and interns it.
30#[inline]
31fn from_bits(
32 tcx: TyCtxt<'tcx>,
33 bits: u128,
34 typing_env: ty::TypingEnv<'tcx>,
35 ty: Ty<'tcx>,
36 ) -> Self {
37let size = tcx38 .layout_of(typing_env.as_query_input(ty))
39 .unwrap_or_else(|e| panic!("could not compute layout for {ty:?}: {e:?}"))
40 .size;
41let valtree =
42 ty::ValTree::from_scalar_int(tcx, ScalarInt::try_from_uint(bits, size).unwrap());
43 ty::Const::new_value(tcx, valtree, ty)
44 }
4546#[inline]
47/// Creates an interned zst constant.
48fn zero_sized(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Self {
49 ty::Const::new_value(tcx, ty::ValTree::zst(tcx), ty)
50 }
5152#[inline]
53fn new_value(tcx: TyCtxt<'tcx>, valtree: ty::ValTree<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> {
54Const::new(tcx, ty::ConstKind::Value(ty::Value { ty, valtree }))
55 }
5657#[inline]
58/// Creates an interned bool constant.
59fn from_bool(tcx: TyCtxt<'tcx>, v: bool) -> Self {
60Self::from_bits(tcx, vas u128, ty::TypingEnv::fully_monomorphized(), tcx.types.bool)
61 }
6263#[inline]
64/// Creates an interned usize constant.
65fn from_target_usize(tcx: TyCtxt<'tcx>, n: u64) -> Self {
66Self::from_bits(tcx, nas u128, ty::TypingEnv::fully_monomorphized(), tcx.types.usize)
67 }
6869/// Panics if `self.kind != ty::ConstKind::Value`.
70fn to_value(self) -> ty::Value<'tcx> {
71match self.kind() {
72 ty::ConstKind::Value(cv) => cv,
73_ => bug!("expected ConstKind::Value, got {:?}", self.kind()),
74 }
75 }
7677/// Attempts to convert to a value.
78 ///
79 /// Note that this does not normalize the constant.
80fn try_to_value(self) -> Option<ty::Value<'tcx>> {
81match self.kind() {
82 ty::ConstKind::Value(cv) => Some(cv),
83_ => None,
84 }
85 }
8687/// Converts to a `ValTreeKind::Leaf` value, `panic`'ing
88 /// if this constant is some other kind.
89 ///
90 /// Note that this does not normalize the constant.
91#[inline]
92fn to_leaf(self) -> ScalarInt {
93self.to_value().to_leaf()
94 }
9596/// Converts to a `ValTreeKind::Branch` value, `panic`'ing
97 /// if this constant is some other kind.
98 ///
99 /// Note that this does not normalize the constant.
100#[inline]
101fn to_branch(self) -> &'tcx [ty::Const<'tcx>] {
102self.to_value().to_branch()
103 }
104105/// Attempts to convert to a `ValTreeKind::Leaf` value.
106 ///
107 /// Note that this does not normalize the constant.
108fn try_to_leaf(self) -> Option<ScalarInt> {
109self.try_to_value()?.try_to_leaf()
110 }
111112/// Attempts to convert to a `ValTreeKind::Leaf` value.
113 ///
114 /// Note that this does not normalize the constant.
115fn try_to_scalar(self) -> Option<Scalar> {
116self.try_to_leaf().map(Scalar::Int)
117 }
118119/// Attempts to convert to a `ValTreeKind::Branch` value.
120 ///
121 /// Note that this does not normalize the constant.
122fn try_to_branch(self) -> Option<&'tcx [ty::Const<'tcx>]> {
123self.try_to_value()?.try_to_branch()
124 }
125126/// Convenience method to extract the value of a usize constant,
127 /// useful to get the length of an array type.
128 ///
129 /// Note that this does not evaluate the constant.
130#[inline]
131fn try_to_target_usize(self, tcx: TyCtxt<'tcx>) -> Option<u64> {
132self.try_to_value()?.try_to_target_usize(tcx)
133 }
134135/// Iterator that walks `self` and any types reachable from
136 /// `self`, in depth-first order. Note that just walks the types
137 /// that appear in `self`, it does not descend into the fields of
138 /// structs or variants. For example:
139 ///
140 /// ```text
141 /// isize => { isize }
142 /// Foo<Bar<isize>> => { Foo<Bar<isize>>, Bar<isize>, isize }
143 /// [isize] => { [isize], isize }
144 /// ```
145fn walk(self) -> TypeWalker<TyCtxt<'tcx>> {
146TypeWalker::new(self.into())
147 }
148}