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 match self {
178 PatOrWild::Wild => PatOrWild::Wild,
179 PatOrWild::Pat(pat) => PatOrWild::Pat(pat),
180 }
181 }
182}
183
184impl<'p, Cx: PatCx> Copy for PatOrWild<'p, Cx> {}
185
186impl<'p, Cx: PatCx> PatOrWild<'p, Cx> {
187 pub(crate) fn as_pat(&self) -> Option<&'p DeconstructedPat<Cx>> {
188 match self {
189 PatOrWild::Wild => None,
190 PatOrWild::Pat(pat) => Some(pat),
191 }
192 }
193 pub(crate) fn ctor(self) -> &'p Constructor<Cx> {
194 match self {
195 PatOrWild::Wild => &Wildcard,
196 PatOrWild::Pat(pat) => pat.ctor(),
197 }
198 }
199
200 pub(crate) fn is_or_pat(&self) -> bool {
201 match self {
202 PatOrWild::Wild => false,
203 PatOrWild::Pat(pat) => pat.is_or_pat(),
204 }
205 }
206
207 pub(crate) fn expand_or_pat(self) -> SmallVec<[Self; 1]> {
210 match self {
211 PatOrWild::Pat(pat) if pat.is_or_pat() => {
212 pat.iter_fields().map(|ipat| PatOrWild::Pat(&ipat.pat)).collect()
213 }
214 _ => smallvec![self],
215 }
216 }
217
218 pub(crate) fn flatten_or_pat(self) -> SmallVec<[Self; 1]> {
220 match self {
221 PatOrWild::Pat(pat) if pat.is_or_pat() => pat
222 .iter_fields()
223 .flat_map(|ipat| PatOrWild::Pat(&ipat.pat).flatten_or_pat())
224 .collect(),
225 _ => smallvec![self],
226 }
227 }
228
229 pub(crate) fn specialize(
232 &self,
233 other_ctor: &Constructor<Cx>,
234 ctor_arity: usize,
235 ) -> SmallVec<[PatOrWild<'p, Cx>; 2]> {
236 match self {
237 PatOrWild::Wild => (0..ctor_arity).map(|_| PatOrWild::Wild).collect(),
238 PatOrWild::Pat(pat) => pat.specialize(other_ctor, ctor_arity),
239 }
240 }
241}
242
243impl<'p, Cx: PatCx> fmt::Debug for PatOrWild<'p, Cx> {
244 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
245 match self {
246 PatOrWild::Wild => write!(f, "_"),
247 PatOrWild::Pat(pat) => pat.fmt(f),
248 }
249 }
250}
251
252pub struct WitnessPat<Cx: PatCx> {
255 ctor: Constructor<Cx>,
256 pub(crate) fields: Vec<WitnessPat<Cx>>,
257 ty: Cx::Ty,
258}
259
260impl<Cx: PatCx> Clone for WitnessPat<Cx> {
261 fn clone(&self) -> Self {
262 Self { ctor: self.ctor.clone(), fields: self.fields.clone(), ty: self.ty.clone() }
263 }
264}
265
266impl<Cx: PatCx> WitnessPat<Cx> {
267 pub(crate) fn new(ctor: Constructor<Cx>, fields: Vec<Self>, ty: Cx::Ty) -> Self {
268 Self { ctor, fields, ty }
269 }
270 pub(crate) fn wildcard(cx: &Cx, ty: Cx::Ty) -> Self {
272 let is_empty = cx.ctors_for_ty(&ty).is_ok_and(|ctors| ctors.all_empty());
273 let ctor = if is_empty { Never } else { Wildcard };
274 Self::new(ctor, Vec::new(), ty)
275 }
276
277 pub(crate) fn wild_from_ctor(cx: &Cx, ctor: Constructor<Cx>, ty: Cx::Ty) -> Self {
281 if matches!(ctor, Wildcard) {
282 return Self::wildcard(cx, ty);
283 }
284 let fields = cx
285 .ctor_sub_tys(&ctor, &ty)
286 .filter(|(_, PrivateUninhabitedField(skip))| !skip)
287 .map(|(ty, _)| Self::wildcard(cx, ty))
288 .collect();
289 Self::new(ctor, fields, ty)
290 }
291
292 pub fn ctor(&self) -> &Constructor<Cx> {
293 &self.ctor
294 }
295 pub fn ty(&self) -> &Cx::Ty {
296 &self.ty
297 }
298
299 pub fn is_never_pattern(&self) -> bool {
300 match self.ctor() {
301 Never => true,
302 Or => self.fields.iter().all(|p| p.is_never_pattern()),
303 _ => self.fields.iter().any(|p| p.is_never_pattern()),
304 }
305 }
306
307 pub fn iter_fields(&self) -> impl Iterator<Item = &WitnessPat<Cx>> {
308 self.fields.iter()
309 }
310}
311
312impl<Cx: PatCx> fmt::Debug for WitnessPat<Cx> {
314 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
315 self.ctor().fmt_fields(f, self.ty(), self.fields.iter())
316 }
317}