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