1use std::fmt;
5
6use smallvec::{SmallVec, smallvec};
7
8use self::Constructor::*;
9use crate::constructor::{Constructor, Slice, SliceKind};
10use crate::{PatCx, PrivateUninhabitedField};
11
12#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
14pub(crate) struct PatId(u32);
15impl PatId {
16 fn new() -> Self {
17 use std::sync::atomic::{AtomicU32, Ordering};
18 static PAT_ID: AtomicU32 = AtomicU32::new(0);
19 PatId(PAT_ID.fetch_add(1, Ordering::SeqCst))
20 }
21}
22
23pub struct IndexedPat<Cx: PatCx> {
25 pub idx: usize,
26 pub pat: DeconstructedPat<Cx>,
27}
28
29pub struct DeconstructedPat<Cx: PatCx> {
33 ctor: Constructor<Cx>,
34 fields: Vec<IndexedPat<Cx>>,
35 arity: usize,
39 ty: Cx::Ty,
40 data: Cx::PatData,
42 pub(crate) uid: PatId,
44}
45
46impl<Cx: PatCx> DeconstructedPat<Cx> {
47 pub fn new(
48 ctor: Constructor<Cx>,
49 fields: Vec<IndexedPat<Cx>>,
50 arity: usize,
51 ty: Cx::Ty,
52 data: Cx::PatData,
53 ) -> Self {
54 DeconstructedPat { ctor, fields, arity, ty, data, uid: PatId::new() }
55 }
56
57 pub fn at_index(self, idx: usize) -> IndexedPat<Cx> {
58 IndexedPat { idx, pat: self }
59 }
60
61 pub(crate) fn is_or_pat(&self) -> bool {
62 matches!(self.ctor, Or)
63 }
64
65 pub fn ctor(&self) -> &Constructor<Cx> {
66 &self.ctor
67 }
68 pub fn ty(&self) -> &Cx::Ty {
69 &self.ty
70 }
71 pub fn data(&self) -> &Cx::PatData {
73 &self.data
74 }
75 pub fn arity(&self) -> usize {
76 self.arity
77 }
78
79 pub fn iter_fields<'a>(&'a self) -> impl Iterator<Item = &'a IndexedPat<Cx>> {
80 self.fields.iter()
81 }
82
83 pub(crate) fn specialize<'a>(
86 &'a self,
87 other_ctor: &Constructor<Cx>,
88 other_ctor_arity: usize,
89 ) -> SmallVec<[PatOrWild<'a, Cx>; 2]> {
90 if matches!(other_ctor, PrivateUninhabited) {
91 return smallvec![];
93 }
94
95 let mut fields: SmallVec<[_; 2]> = (0..other_ctor_arity).map(|_| PatOrWild::Wild).collect();
97 match self.ctor {
99 Slice(Slice { kind: SliceKind::VarLen(prefix, _), .. })
103 if self.arity != other_ctor_arity =>
104 {
105 for ipat in &self.fields {
106 let new_idx = if ipat.idx < prefix {
107 ipat.idx
108 } else {
109 ipat.idx + other_ctor_arity - self.arity
111 };
112 fields[new_idx] = PatOrWild::Pat(&ipat.pat);
113 }
114 }
115 _ => {
116 for ipat in &self.fields {
117 fields[ipat.idx] = PatOrWild::Pat(&ipat.pat);
118 }
119 }
120 }
121 fields
122 }
123
124 pub fn walk<'a>(&'a self, it: &mut impl FnMut(&'a Self) -> bool) {
128 if !it(self) {
129 return;
130 }
131
132 for p in self.iter_fields() {
133 p.pat.walk(it)
134 }
135 }
136}
137
138impl<Cx: PatCx> fmt::Debug for DeconstructedPat<Cx> {
140 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
141 let mut fields: Vec<_> = (0..self.arity).map(|_| PatOrWild::Wild).collect();
142 for ipat in self.iter_fields() {
143 fields[ipat.idx] = PatOrWild::Pat(&ipat.pat);
144 }
145 self.ctor().fmt_fields(f, self.ty(), fields.into_iter())
146 }
147}
148
149impl<Cx: PatCx> PartialEq for DeconstructedPat<Cx> {
151 fn eq(&self, other: &Self) -> bool {
152 self.uid == other.uid
153 }
154}
155impl<Cx: PatCx> Eq for DeconstructedPat<Cx> {}
157impl<Cx: PatCx> std::hash::Hash for DeconstructedPat<Cx> {
159 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
160 self.uid.hash(state);
161 }
162}
163
164pub(crate) enum PatOrWild<'p, Cx: PatCx> {
169 Wild,
171 Pat(&'p DeconstructedPat<Cx>),
173}
174
175impl<'p, Cx: PatCx> Clone for PatOrWild<'p, Cx> {
176 fn clone(&self) -> Self {
177 *self
178 }
179}
180
181impl<'p, Cx: PatCx> Copy for PatOrWild<'p, Cx> {}
182
183impl<'p, Cx: PatCx> PatOrWild<'p, Cx> {
184 pub(crate) fn as_pat(&self) -> Option<&'p DeconstructedPat<Cx>> {
185 match self {
186 PatOrWild::Wild => None,
187 PatOrWild::Pat(pat) => Some(pat),
188 }
189 }
190 pub(crate) fn ctor(self) -> &'p Constructor<Cx> {
191 match self {
192 PatOrWild::Wild => &Wildcard,
193 PatOrWild::Pat(pat) => pat.ctor(),
194 }
195 }
196
197 pub(crate) fn is_or_pat(&self) -> bool {
198 match self {
199 PatOrWild::Wild => false,
200 PatOrWild::Pat(pat) => pat.is_or_pat(),
201 }
202 }
203
204 pub(crate) fn expand_or_pat(self) -> SmallVec<[Self; 1]> {
207 match self {
208 PatOrWild::Pat(pat) if pat.is_or_pat() => {
209 pat.iter_fields().map(|ipat| PatOrWild::Pat(&ipat.pat)).collect()
210 }
211 _ => smallvec![self],
212 }
213 }
214
215 pub(crate) fn flatten_or_pat(self) -> SmallVec<[Self; 1]> {
217 match self {
218 PatOrWild::Pat(pat) if pat.is_or_pat() => pat
219 .iter_fields()
220 .flat_map(|ipat| PatOrWild::Pat(&ipat.pat).flatten_or_pat())
221 .collect(),
222 _ => smallvec![self],
223 }
224 }
225
226 pub(crate) fn specialize(
229 &self,
230 other_ctor: &Constructor<Cx>,
231 ctor_arity: usize,
232 ) -> SmallVec<[PatOrWild<'p, Cx>; 2]> {
233 match self {
234 PatOrWild::Wild => (0..ctor_arity).map(|_| PatOrWild::Wild).collect(),
235 PatOrWild::Pat(pat) => pat.specialize(other_ctor, ctor_arity),
236 }
237 }
238}
239
240impl<'p, Cx: PatCx> fmt::Debug for PatOrWild<'p, Cx> {
241 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
242 match self {
243 PatOrWild::Wild => write!(f, "_"),
244 PatOrWild::Pat(pat) => pat.fmt(f),
245 }
246 }
247}
248
249pub struct WitnessPat<Cx: PatCx> {
252 ctor: Constructor<Cx>,
253 pub(crate) fields: Vec<WitnessPat<Cx>>,
254 ty: Cx::Ty,
255}
256
257impl<Cx: PatCx> Clone for WitnessPat<Cx> {
258 fn clone(&self) -> Self {
259 Self { ctor: self.ctor.clone(), fields: self.fields.clone(), ty: self.ty.clone() }
260 }
261}
262
263impl<Cx: PatCx> WitnessPat<Cx> {
264 pub(crate) fn new(ctor: Constructor<Cx>, fields: Vec<Self>, ty: Cx::Ty) -> Self {
265 Self { ctor, fields, ty }
266 }
267 pub(crate) fn wildcard(cx: &Cx, ty: Cx::Ty) -> Self {
269 let is_empty = cx.ctors_for_ty(&ty).is_ok_and(|ctors| ctors.all_empty());
270 let ctor = if is_empty { Never } else { Wildcard };
271 Self::new(ctor, Vec::new(), ty)
272 }
273
274 pub(crate) fn wild_from_ctor(cx: &Cx, ctor: Constructor<Cx>, ty: Cx::Ty) -> Self {
278 if matches!(ctor, Wildcard) {
279 return Self::wildcard(cx, ty);
280 }
281 let fields = cx
282 .ctor_sub_tys(&ctor, &ty)
283 .filter(|(_, PrivateUninhabitedField(skip))| !skip)
284 .map(|(ty, _)| Self::wildcard(cx, ty))
285 .collect();
286 Self::new(ctor, fields, ty)
287 }
288
289 pub fn ctor(&self) -> &Constructor<Cx> {
290 &self.ctor
291 }
292 pub fn ty(&self) -> &Cx::Ty {
293 &self.ty
294 }
295
296 pub fn is_never_pattern(&self) -> bool {
297 match self.ctor() {
298 Never => true,
299 Or => self.fields.iter().all(|p| p.is_never_pattern()),
300 _ => self.fields.iter().any(|p| p.is_never_pattern()),
301 }
302 }
303
304 pub fn iter_fields(&self) -> impl Iterator<Item = &WitnessPat<Cx>> {
305 self.fields.iter()
306 }
307}
308
309impl<Cx: PatCx> fmt::Debug for WitnessPat<Cx> {
311 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
312 self.ctor().fmt_fields(f, self.ty(), self.fields.iter())
313 }
314}