rustc_mir_build/builder/matches/
user_ty.rs1use std::iter;
8
9use rustc_abi::{FieldIdx, VariantIdx};
10use rustc_data_structures::assert_matches;
11use rustc_data_structures::smallvec::SmallVec;
12use rustc_middle::mir::{ProjectionElem, UserTypeProjection, UserTypeProjections};
13use rustc_middle::ty::{AdtDef, UserTypeAnnotationIndex};
14use rustc_span::Symbol;
15
16pub(crate) type UserTypeIndices = SmallVec<[UserTypeAnnotationIndex; 4]>;
19
20#[derive(#[automatically_derived]
impl ::core::fmt::Debug for ProjectedUserTypesOp {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
ProjectedUserTypesOp::PushUserTypes { base_types: __self_0 } =>
::core::fmt::Formatter::debug_struct_field1_finish(f,
"PushUserTypes", "base_types", &__self_0),
ProjectedUserTypesOp::Index =>
::core::fmt::Formatter::write_str(f, "Index"),
ProjectedUserTypesOp::Subslice { from: __self_0, to: __self_1 } =>
::core::fmt::Formatter::debug_struct_field2_finish(f,
"Subslice", "from", __self_0, "to", &__self_1),
ProjectedUserTypesOp::Deref =>
::core::fmt::Formatter::write_str(f, "Deref"),
ProjectedUserTypesOp::Leaf { field: __self_0 } =>
::core::fmt::Formatter::debug_struct_field1_finish(f, "Leaf",
"field", &__self_0),
ProjectedUserTypesOp::Variant {
name: __self_0, variant: __self_1, field: __self_2 } =>
::core::fmt::Formatter::debug_struct_field3_finish(f,
"Variant", "name", __self_0, "variant", __self_1, "field",
&__self_2),
}
}
}Debug)]
23pub(crate) enum ProjectedUserTypesOp {
24 PushUserTypes { base_types: UserTypeIndices },
25
26 Index,
27 Subslice { from: u64, to: u64 },
28 Deref,
29 Leaf { field: FieldIdx },
30 Variant { name: Symbol, variant: VariantIdx, field: FieldIdx },
31}
32
33#[derive(#[automatically_derived]
impl<'a> ::core::fmt::Debug for ProjectedUserTypesNode<'a> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
ProjectedUserTypesNode::None =>
::core::fmt::Formatter::write_str(f, "None"),
ProjectedUserTypesNode::Chain { parent: __self_0, op: __self_1 }
=>
::core::fmt::Formatter::debug_struct_field2_finish(f, "Chain",
"parent", __self_0, "op", &__self_1),
}
}
}Debug)]
34pub(crate) enum ProjectedUserTypesNode<'a> {
35 None,
36 Chain { parent: &'a Self, op: ProjectedUserTypesOp },
37}
38
39impl<'a> ProjectedUserTypesNode<'a> {
40 pub(crate) fn push_user_types(&'a self, base_types: UserTypeIndices) -> Self {
41 if !!base_types.is_empty() {
::core::panicking::panic("assertion failed: !base_types.is_empty()")
};assert!(!base_types.is_empty());
42 Self::Chain { parent: self, op: ProjectedUserTypesOp::PushUserTypes { base_types } }
44 }
45
46 fn maybe_push(&'a self, op_fn: impl FnOnce() -> ProjectedUserTypesOp) -> Self {
48 match self {
49 Self::None => Self::None,
50 Self::Chain { .. } => Self::Chain { parent: self, op: op_fn() },
51 }
52 }
53
54 pub(crate) fn index(&'a self) -> Self {
55 self.maybe_push(|| ProjectedUserTypesOp::Index)
56 }
57
58 pub(crate) fn subslice(&'a self, from: u64, to: u64) -> Self {
59 self.maybe_push(|| ProjectedUserTypesOp::Subslice { from, to })
60 }
61
62 pub(crate) fn deref(&'a self) -> Self {
63 self.maybe_push(|| ProjectedUserTypesOp::Deref)
64 }
65
66 pub(crate) fn leaf(&'a self, field: FieldIdx) -> Self {
67 self.maybe_push(|| ProjectedUserTypesOp::Leaf { field })
68 }
69
70 pub(crate) fn variant(
71 &'a self,
72 adt_def: AdtDef<'_>,
73 variant: VariantIdx,
74 field: FieldIdx,
75 ) -> Self {
76 self.maybe_push(|| {
77 let name = adt_def.variant(variant).name;
78 ProjectedUserTypesOp::Variant { name, variant, field }
79 })
80 }
81
82 fn iter_ops_reversed(&'a self) -> impl Iterator<Item = &'a ProjectedUserTypesOp> {
86 let mut next = self;
87 iter::from_fn(move || match next {
88 Self::None => None,
89 Self::Chain { parent, op } => {
90 next = parent;
91 Some(op)
92 }
93 })
94 }
95
96 pub(crate) fn build_user_type_projections(&self) -> Option<Box<UserTypeProjections>> {
98 if #[allow(non_exhaustive_omitted_patterns)] match self {
Self::None => true,
_ => false,
}matches!(self, Self::None) {
100 return None;
101 }
102
103 let ops_reversed = self.iter_ops_reversed().collect::<Vec<_>>();
104 match ops_reversed.last() {
Some(ProjectedUserTypesOp::PushUserTypes { .. }) => {}
ref left_val => {
::core::panicking::assert_matches_failed(left_val,
"Some(ProjectedUserTypesOp::PushUserTypes { .. })",
::core::option::Option::None);
}
};assert_matches!(ops_reversed.last(), Some(ProjectedUserTypesOp::PushUserTypes { .. }));
107
108 let mut projections = ::alloc::vec::Vec::new()vec![];
109 for op in ops_reversed.into_iter().rev() {
110 match *op {
111 ProjectedUserTypesOp::PushUserTypes { ref base_types } => {
112 if !!base_types.is_empty() {
::core::panicking::panic("assertion failed: !base_types.is_empty()")
};assert!(!base_types.is_empty());
113 for &base in base_types {
114 projections.push(UserTypeProjection { base, projs: ::alloc::vec::Vec::new()vec![] })
115 }
116 }
117
118 ProjectedUserTypesOp::Index => {
119 for p in &mut projections {
120 p.projs.push(ProjectionElem::Index(()))
121 }
122 }
123 ProjectedUserTypesOp::Subslice { from, to } => {
124 for p in &mut projections {
125 p.projs.push(ProjectionElem::Subslice { from, to, from_end: true })
126 }
127 }
128 ProjectedUserTypesOp::Deref => {
129 for p in &mut projections {
130 p.projs.push(ProjectionElem::Deref)
131 }
132 }
133 ProjectedUserTypesOp::Leaf { field } => {
134 for p in &mut projections {
135 p.projs.push(ProjectionElem::Field(field, ()))
136 }
137 }
138 ProjectedUserTypesOp::Variant { name, variant, field } => {
139 for p in &mut projections {
140 p.projs.push(ProjectionElem::Downcast(Some(name), variant));
141 p.projs.push(ProjectionElem::Field(field, ()));
142 }
143 }
144 }
145 }
146
147 Some(Box::new(UserTypeProjections { contents: projections }))
148 }
149}