rustc_type_ir/search_graph/
stack.rs1use std::ops::Index;
2
3use derive_where::derive_where;
4use rustc_index::IndexVec;
5
6use crate::search_graph::{
7 AvailableDepth, CandidateHeadUsages, Cx, CycleHeads, HeadUsages, NestedGoals, PathKind,
8 RequiredDepth,
9};
10
11#[automatically_derived]
impl ::core::marker::Copy for StackDepth { }
impl StackDepth {
#[doc = r" Maximum value the index can take, as a `u32`."]
pub(super) const MAX_AS_U32: u32 = 0xFFFF_FF00;
#[doc = r" Maximum value the index can take."]
pub(super) const MAX: Self = Self::from_u32(0xFFFF_FF00);
#[doc = r" Zero value of the index."]
pub(super) const ZERO: Self = Self::from_u32(0);
#[doc = r" Creates a new index from a given `usize`."]
#[doc = r""]
#[doc = r" # Panics"]
#[doc = r""]
#[doc = r" Will panic if `value` exceeds `MAX`."]
#[inline]
pub(super) const fn from_usize(value: usize) -> Self {
if !(value <= (0xFFFF_FF00 as usize)) {
::core::panicking::panic("assertion failed: value <= (0xFFFF_FF00 as usize)")
};
unsafe { Self::from_u32_unchecked(value as u32) }
}
#[doc = r" Creates a new index from a given `u32`."]
#[doc = r""]
#[doc = r" # Panics"]
#[doc = r""]
#[doc = r" Will panic if `value` exceeds `MAX`."]
#[inline]
pub(super) const fn from_u32(value: u32) -> Self {
if !(value <= 0xFFFF_FF00) {
::core::panicking::panic("assertion failed: value <= 0xFFFF_FF00")
};
unsafe { Self::from_u32_unchecked(value) }
}
#[doc = r" Creates a new index from a given `u16`."]
#[doc = r""]
#[doc = r" # Panics"]
#[doc = r""]
#[doc = r" Will panic if `value` exceeds `MAX`."]
#[inline]
pub(super) const fn from_u16(value: u16) -> Self {
let value = value as u32;
if !(value <= 0xFFFF_FF00) {
::core::panicking::panic("assertion failed: value <= 0xFFFF_FF00")
};
unsafe { Self::from_u32_unchecked(value) }
}
#[doc = r" Creates a new index from a given `u32`."]
#[doc = r""]
#[doc = r" # Safety"]
#[doc = r""]
#[doc =
r" The provided value must be less than or equal to the maximum value for the newtype."]
#[doc =
r" Providing a value outside this range is undefined due to layout restrictions."]
#[doc = r""]
#[doc = r" Prefer using `from_u32`."]
#[inline]
pub(super) const unsafe fn from_u32_unchecked(value: u32) -> Self {
Self {
private_use_as_methods_instead: unsafe {
std::mem::transmute(value)
},
}
}
#[doc = r" Extracts the value of this index as a `usize`."]
#[inline]
pub(super) const fn index(self) -> usize { self.as_usize() }
#[doc = r" Extracts the value of this index as a `u32`."]
#[inline]
pub(super) const fn as_u32(self) -> u32 {
unsafe { std::mem::transmute(self.private_use_as_methods_instead) }
}
#[doc = r" Extracts the value of this index as a `usize`."]
#[inline]
pub(super) const fn as_usize(self) -> usize { self.as_u32() as usize }
}
impl std::ops::Add<usize> for StackDepth {
type Output = Self;
#[inline]
fn add(self, other: usize) -> Self {
Self::from_usize(self.index() + other)
}
}
impl std::ops::AddAssign<usize> for StackDepth {
#[inline]
fn add_assign(&mut self, other: usize) { *self = *self + other; }
}
impl rustc_index::Idx for StackDepth {
#[inline]
fn new(value: usize) -> Self { Self::from_usize(value) }
#[inline]
fn index(self) -> usize { self.as_usize() }
}
impl ::std::iter::Step for StackDepth {
#[inline]
fn steps_between(start: &Self, end: &Self) -> (usize, Option<usize>) {
<usize as
::std::iter::Step>::steps_between(&Self::index(*start),
&Self::index(*end))
}
#[inline]
fn forward_checked(start: Self, u: usize) -> Option<Self> {
Self::index(start).checked_add(u).map(Self::from_usize)
}
#[inline]
fn backward_checked(start: Self, u: usize) -> Option<Self> {
Self::index(start).checked_sub(u).map(Self::from_usize)
}
#[inline]
fn forward_overflowing(start: Self, u: usize) -> (Self, bool) {
let (s, o) = Self::index(start).overflowing_add(u);
(Self::from_usize(s), o)
}
#[inline]
fn backward_overflowing(start: Self, u: usize) -> (Self, bool) {
let (s, o) = Self::index(start).overflowing_sub(u);
(Self::from_usize(s), o)
}
}
impl ::std::cmp::Ord for StackDepth {
#[inline]
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.as_u32().cmp(&other.as_u32())
}
}
impl ::std::cmp::PartialOrd for StackDepth {
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl From<StackDepth> for u32 {
#[inline]
fn from(v: StackDepth) -> u32 { v.as_u32() }
}
impl From<StackDepth> for usize {
#[inline]
fn from(v: StackDepth) -> usize { v.as_usize() }
}
impl From<usize> for StackDepth {
#[inline]
fn from(value: usize) -> Self { Self::from_usize(value) }
}
impl From<u32> for StackDepth {
#[inline]
fn from(value: u32) -> Self { Self::from_u32(value) }
}
impl ::std::cmp::Eq for StackDepth {}
impl ::std::cmp::PartialEq for StackDepth {
fn eq(&self, other: &Self) -> bool { self.as_u32().eq(&other.as_u32()) }
}
impl ::std::marker::StructuralPartialEq for StackDepth { }
impl ::std::hash::Hash for StackDepth {
fn hash<H: ::std::hash::Hasher>(&self, state: &mut H) {
self.as_u32().hash(state)
}
}
impl ::std::fmt::Debug for StackDepth {
fn fmt(&self, fmt: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
fmt.write_fmt(format_args!("{0}", self.as_u32()))
}
}rustc_index::newtype_index! {
12 #[orderable]
13 #[gate_rustc_only]
14 pub(super) struct StackDepth {}
15}
16
17#[automatically_derived]
impl<X: Cx> ::core::fmt::Debug for StackEntry<X> where X: Cx {
fn fmt(&self, __f: &mut ::core::fmt::Formatter<'_>)
-> ::core::fmt::Result {
match self {
StackEntry {
input: ref __field_input,
step_kind_from_parent: ref __field_step_kind_from_parent,
available_depth: ref __field_available_depth,
min_reached_available_depth: ref __field_min_reached_available_depth,
provisional_result: ref __field_provisional_result,
heads: ref __field_heads,
encountered_overflow: ref __field_encountered_overflow,
usages: ref __field_usages,
candidate_usages: ref __field_candidate_usages,
nested_goals: ref __field_nested_goals } => {
let mut __builder =
::core::fmt::Formatter::debug_struct(__f, "StackEntry");
::core::fmt::DebugStruct::field(&mut __builder, "input",
__field_input);
::core::fmt::DebugStruct::field(&mut __builder,
"step_kind_from_parent", __field_step_kind_from_parent);
::core::fmt::DebugStruct::field(&mut __builder,
"available_depth", __field_available_depth);
::core::fmt::DebugStruct::field(&mut __builder,
"min_reached_available_depth",
__field_min_reached_available_depth);
::core::fmt::DebugStruct::field(&mut __builder,
"provisional_result", __field_provisional_result);
::core::fmt::DebugStruct::field(&mut __builder, "heads",
__field_heads);
::core::fmt::DebugStruct::field(&mut __builder,
"encountered_overflow", __field_encountered_overflow);
::core::fmt::DebugStruct::field(&mut __builder, "usages",
__field_usages);
::core::fmt::DebugStruct::field(&mut __builder,
"candidate_usages", __field_candidate_usages);
::core::fmt::DebugStruct::field(&mut __builder,
"nested_goals", __field_nested_goals);
::core::fmt::DebugStruct::finish(&mut __builder)
}
}
}
}#[derive_where(Debug; X: Cx)]
20pub(super) struct StackEntry<X: Cx> {
21 pub input: X::Input,
22
23 pub step_kind_from_parent: PathKind,
28
29 pub available_depth: AvailableDepth,
31
32 pub min_reached_available_depth: AvailableDepth,
35
36 pub provisional_result: Option<X::Result>,
39
40 pub heads: CycleHeads,
43
44 pub encountered_overflow: bool,
46
47 pub usages: Option<HeadUsages>,
49
50 pub candidate_usages: Option<CandidateHeadUsages>,
57
58 pub nested_goals: NestedGoals<X>,
60}
61
62impl<X: Cx> StackEntry<X> {
63 pub(super) fn required_depth(&self) -> RequiredDepth {
64 RequiredDepth(self.available_depth.0 - self.min_reached_available_depth.0)
65 }
66}
67
68#[automatically_derived]
impl<X: Cx> ::core::default::Default for Stack<X> where X: Cx {
fn default() -> Self {
Stack { entries: ::core::default::Default::default() }
}
}#[derive_where(Default; X: Cx)]
75pub(super) struct Stack<X: Cx> {
76 entries: IndexVec<StackDepth, StackEntry<X>>,
77}
78
79impl<X: Cx> Stack<X> {
80 pub(super) fn is_empty(&self) -> bool {
81 self.entries.is_empty()
82 }
83
84 pub(super) fn len(&self) -> usize {
85 self.entries.len()
86 }
87
88 pub(super) fn last(&self) -> Option<&StackEntry<X>> {
89 self.entries.raw.last()
90 }
91
92 pub(super) fn last_mut(&mut self) -> Option<&mut StackEntry<X>> {
93 self.entries.raw.last_mut()
94 }
95
96 pub(super) fn last_mut_with_index(&mut self) -> Option<(StackDepth, &mut StackEntry<X>)> {
97 self.entries.last_index().map(|idx| (idx, &mut self.entries[idx]))
98 }
99
100 pub(super) fn next_index(&self) -> StackDepth {
101 self.entries.next_index()
102 }
103
104 pub(super) fn push(&mut self, entry: StackEntry<X>) -> StackDepth {
105 if truecfg!(debug_assertions) && self.entries.iter().any(|e| e.input == entry.input) {
106 {
::core::panicking::panic_fmt(format_args!("pushing duplicate entry on stack: {1:?} {0:?}",
self.entries, entry));
};panic!("pushing duplicate entry on stack: {entry:?} {:?}", self.entries);
107 }
108 self.entries.push(entry)
109 }
110
111 pub(super) fn pop(&mut self) -> StackEntry<X> {
112 self.entries.pop().unwrap()
113 }
114
115 pub(super) fn cycle_step_kinds(&self, head: StackDepth) -> impl Iterator<Item = PathKind> {
116 self.entries.raw[head.index() + 1..].iter().map(|entry| entry.step_kind_from_parent)
117 }
118
119 pub(super) fn iter(&self) -> impl Iterator<Item = &StackEntry<X>> {
120 self.entries.iter()
121 }
122
123 pub(super) fn find(&self, input: X::Input) -> Option<StackDepth> {
124 self.entries.iter_enumerated().find(|(_, e)| e.input == input).map(|(idx, _)| idx)
125 }
126}
127
128impl<X: Cx> Index<StackDepth> for Stack<X> {
129 type Output = StackEntry<X>;
130 fn index(&self, index: StackDepth) -> &StackEntry<X> {
131 &self.entries[index]
132 }
133}