1
use crate::ast::enumerated::EnumeratedType;
2

            
3
use super::categories::{Category, CategoryOf};
4
use super::name::Name;
5
use super::serde::{DefaultWithId, HasId, IdPtr, ObjId, PtrAsInner};
6
use super::{
7
    DecisionVariable, DomainPtr, Expression, GroundDomain, HasDomain, Moo, Reference, ReturnType,
8
    Typeable,
9
};
10
use crate::representation::{ReprRule, ReprStore};
11
use parking_lot::{
12
    MappedRwLockReadGuard, MappedRwLockWriteGuard, RwLock, RwLockReadGuard, RwLockWriteGuard,
13
};
14
use serde::{Deserialize, Serialize};
15
use serde_with::serde_as;
16
use std::any::TypeId;
17
use std::collections::BTreeSet;
18
use std::collections::VecDeque;
19
use std::fmt::{Debug, Display};
20
use std::hash::{DefaultHasher, Hash, Hasher};
21
use std::mem;
22
use std::ops::{Deref, DerefMut};
23
use std::sync::Arc;
24
use std::sync::atomic::{AtomicU32, AtomicU64, Ordering};
25
use uniplate::{Biplate, Tree, Uniplate};
26

            
27
/// Global counter of declarations.
28
/// Note that the counter is shared between all threads
29
/// Thus, when running multiple models in parallel, IDs may
30
/// be different with every run depending on scheduling order
31
static DECLARATION_PTR_ID_COUNTER: AtomicU32 = const { AtomicU32::new(0) };
32

            
33
/// Global generation of declaration contents.
34
///
35
/// Declaration pointers are shared across symbol tables, so an in-place update cannot cheaply
36
/// notify every table that contains the pointer. Symbol-table content caches compare against this
37
/// generation instead.
38
static DECLARATION_CONTENT_GENERATION: AtomicU64 = const { AtomicU64::new(1) };
39

            
40
/// Returns the generation shared by all mutable declaration contents.
41
2250148415
pub(crate) fn declaration_content_generation() -> u64 {
42
2250148415
    DECLARATION_CONTENT_GENERATION.load(Ordering::Acquire)
43
2250148415
}
44

            
45
/// Records that a declaration's contents may have changed.
46
44030556
fn mark_declaration_content_changed() {
47
44030556
    DECLARATION_CONTENT_GENERATION.fetch_add(1, Ordering::AcqRel);
48
44030556
}
49

            
50
/// Mutable access to part of a declaration that records a semantic change when released.
51
pub struct DeclarationMutGuard<'a, T: ?Sized> {
52
    inner: Option<MappedRwLockWriteGuard<'a, T>>,
53
}
54

            
55
impl<'a, T: ?Sized> DeclarationMutGuard<'a, T> {
56
    /// Wraps a mapped write guard so dropping it records a content change.
57
42937235
    fn new(inner: MappedRwLockWriteGuard<'a, T>) -> Self {
58
42937235
        Self { inner: Some(inner) }
59
42937235
    }
60
}
61

            
62
impl<T: ?Sized> Deref for DeclarationMutGuard<'_, T> {
63
    type Target = T;
64

            
65
246326
    fn deref(&self) -> &Self::Target {
66
246326
        self.inner.as_deref().expect("declaration guard is live")
67
246326
    }
68
}
69

            
70
impl<T: ?Sized> DerefMut for DeclarationMutGuard<'_, T> {
71
42690968
    fn deref_mut(&mut self) -> &mut Self::Target {
72
42690968
        self.inner
73
42690968
            .as_deref_mut()
74
42690968
            .expect("declaration guard is live")
75
42690968
    }
76
}
77

            
78
impl<T: ?Sized> Drop for DeclarationMutGuard<'_, T> {
79
42937235
    fn drop(&mut self) {
80
42937235
        drop(self.inner.take());
81
42937235
        mark_declaration_content_changed();
82
42937235
    }
83
}
84

            
85
#[doc(hidden)]
86
/// Resets the id counter of `DeclarationPtr` to 0.
87
///
88
/// This is probably always a bad idea.
89
pub fn reset_declaration_id_unchecked() {
90
    let _ = DECLARATION_PTR_ID_COUNTER.swap(0, Ordering::Relaxed);
91
}
92

            
93
/// A shared pointer to a [`Declaration`].
94
///
95
/// Two declaration pointers are equal if they point to the same underlying declaration.
96
///
97
/// # Id
98
///
99
///  The id of `DeclarationPtr` obeys the following invariants:
100
///
101
/// 1. Declaration pointers have the same id if they point to the same
102
///    underlying declaration.
103
///
104
/// 2. The id is immutable.
105
///
106
/// 3. Changing the declaration pointed to by the declaration pointer does not change the id. This
107
///    allows declarations to be updated by replacing them with a newer version of themselves.
108
///
109
/// `Ord`, `Hash`, and `Eq` use id for comparisons.
110
/// # Serde
111
///
112
/// Declaration pointers can be serialised using the following serializers:
113
///
114
/// + [`DeclarationPtrFull`](serde::DeclarationPtrFull)
115
/// + [`DeclarationPtrAsId`](serde::DeclarationPtrAsId)
116
///
117
/// See their documentation for more information.
118
#[derive(Clone, Debug)]
119
pub struct DeclarationPtr
120
where
121
    Self: Send + Sync,
122
{
123
    // the shared bits of the pointer
124
    inner: Arc<DeclarationPtrInner>,
125
}
126

            
127
// The bits of a declaration that are shared between all pointers.
128
#[derive(Debug)]
129
struct DeclarationPtrInner {
130
    // Identity hash/order key. Declaration content is mutable and is hashed separately by
131
    // `DeclarationPtr::content_hash`.
132
    // We don't want this to be mutable, as `HashMap` and `BTreeMap` rely on the hash or order of
133
    // keys to be unchanging.
134
    //
135
    // See:  https://rust-lang.github.io/rust-clippy/master/index.html#mutable_key_type
136
    id: ObjId,
137

            
138
    // The contents of the declaration itself should be mutable.
139
    value: RwLock<Declaration>,
140

            
141
    /// Representations initialised for this declaration.
142
    representations: RwLock<ReprStore>,
143

            
144
    /// The declaration from which this auxiliary declaration was created.
145
    source: RwLock<Option<DeclarationPtr>>,
146
}
147

            
148
impl DeclarationPtrInner {
149
722822697
    fn new(value: RwLock<Declaration>) -> Arc<DeclarationPtrInner> {
150
722822697
        Arc::new(DeclarationPtrInner {
151
722822697
            id: ObjId {
152
722822697
                type_name: ustr::ustr(DeclarationPtr::TYPE_NAME),
153
722822697
                object_id: DECLARATION_PTR_ID_COUNTER.fetch_add(1, Ordering::Relaxed),
154
722822697
            },
155
722822697
            value,
156
722822697
            representations: RwLock::new(ReprStore::new()),
157
722822697
            source: RwLock::new(None),
158
722822697
        })
159
722822697
    }
160

            
161
    // SAFETY: only use if you are really really sure you arn't going to break the id invariants of
162
    // DeclarationPtr and HasId!
163
    fn new_with_id_unchecked(value: RwLock<Declaration>, id: ObjId) -> Arc<DeclarationPtrInner> {
164
        Arc::new(DeclarationPtrInner {
165
            id,
166
            value,
167
            representations: RwLock::new(ReprStore::new()),
168
            source: RwLock::new(None),
169
        })
170
    }
171
}
172

            
173
#[allow(dead_code)]
174
impl DeclarationPtr {
175
    /******************************/
176
    /*        Constructors        */
177
    /******************************/
178

            
179
    /// Creates a `DeclarationPtr` for the given `Declaration`.
180
654824292
    fn from_declaration(declaration: Declaration) -> DeclarationPtr {
181
654824292
        DeclarationPtr {
182
654824292
            inner: DeclarationPtrInner::new(RwLock::new(declaration)),
183
654824292
        }
184
654824292
    }
185

            
186
    /// Gets the declaration from which this auxiliary declaration was created.
187
692447537
    pub fn source(&self) -> RwLockReadGuard<'_, Option<DeclarationPtr>> {
188
692447537
        self.inner.source.read()
189
692447537
    }
190

            
191
    /// Mutates the declaration from which this auxiliary declaration was created.
192
52443023
    pub fn source_mut(&mut self) -> RwLockWriteGuard<'_, Option<DeclarationPtr>> {
193
52443023
        self.inner.source.write()
194
52443023
    }
195

            
196
    /// Gets the representations initialised for this declaration.
197
9239267109
    pub fn reprs(&self) -> RwLockReadGuard<'_, ReprStore> {
198
9239267109
        self.inner.representations.read()
199
9239267109
    }
200

            
201
    /// Mutates the representations initialised for this declaration.
202
13240090
    pub fn reprs_mut(&mut self) -> RwLockWriteGuard<'_, ReprStore> {
203
13240090
        self.inner.representations.write()
204
13240090
    }
205

            
206
    /// Gets a particular representation state, if it has been initialised.
207
7223701
    pub fn get_repr<T: ReprRule + ?Sized>(
208
7223701
        &self,
209
7223701
    ) -> Option<MappedRwLockReadGuard<'_, T::DeclLevel>> {
210
7223701
        RwLockReadGuard::try_map(self.inner.representations.read(), |reprs| reprs.get::<T>()).ok()
211
7223701
    }
212

            
213
    /// Creates a new declaration.
214
    ///
215
    /// # Examples
216
    ///
217
    /// ```
218
    /// use conjure_cp_core::ast::{DeclarationPtr,Name,DeclarationKind,Domain,Range};
219
    ///
220
    /// // letting MyDomain be int(1..5)
221
    /// let declaration = DeclarationPtr::new(
222
    ///     Name::User("MyDomain".into()),
223
    ///     DeclarationKind::DomainLetting(Domain::int(vec![
224
    ///         Range::Bounded(1,5)])));
225
    /// ```
226
654824292
    pub fn new(name: Name, kind: DeclarationKind) -> DeclarationPtr {
227
654824292
        DeclarationPtr::from_declaration(Declaration::new(name, kind))
228
654824292
    }
229

            
230
    /// Creates a new find declaration.
231
    ///
232
    /// # Examples
233
    ///
234
    /// ```
235
    /// use conjure_cp_core::ast::{DeclarationPtr,Name,DeclarationKind,Domain,Range};
236
    ///
237
    /// // find x: int(1..5)
238
    /// let declaration = DeclarationPtr::new_find(
239
    ///     Name::User("x".into()),
240
    ///     Domain::int(vec![Range::Bounded(1,5)]));
241
    ///
242
    /// ```
243
51803078
    pub fn new_find(name: Name, domain: DomainPtr) -> DeclarationPtr {
244
51803078
        let kind = DeclarationKind::Find(DecisionVariable::new(domain));
245
51803078
        DeclarationPtr::new(name, kind)
246
51803078
    }
247

            
248
    /// Creates a new auxiliary find declaration.
249
    ///
250
    /// Auxiliary finds are introduced by rewriting (for example, turning a top-level `exists`
251
    /// into constraints), and can also be written in Essence as `findAux`.
252
    /// They are decision variables for solvers, but must not be branched on during search:
253
    /// different assignments to them must not produce distinct user-facing solutions.
254
600837966
    pub fn new_find_auxiliary(name: Name, domain: DomainPtr) -> DeclarationPtr {
255
600837966
        let kind = DeclarationKind::FindAuxiliary(DecisionVariable::new(domain));
256
600837966
        DeclarationPtr::new(name, kind)
257
600837966
    }
258

            
259
    /// Creates a new given declaration.
260
    ///
261
    /// # Examples
262
    ///
263
    /// ```
264
    /// use conjure_cp_core::ast::{DeclarationPtr,Name,DeclarationKind,Domain,Range};
265
    ///
266
    /// // given n: int(1..5)
267
    /// let declaration = DeclarationPtr::new_given(
268
    ///     Name::User("n".into()),
269
    ///     Domain::int(vec![Range::Bounded(1,5)]));
270
    ///
271
    /// ```
272
243481
    pub fn new_given(name: Name, domain: DomainPtr) -> DeclarationPtr {
273
243481
        let kind = DeclarationKind::Given(domain);
274
243481
        DeclarationPtr::new(name, kind)
275
243481
    }
276

            
277
    /// Creates a new quantified declaration for local comprehension scopes.
278
    ///
279
    /// Used when creating the quantified variable in a generator.
280
534623
    pub fn new_quantified(name: Name, domain: DomainPtr) -> DeclarationPtr {
281
534623
        DeclarationPtr::new(
282
534623
            name,
283
534623
            DeclarationKind::Quantified(Quantified {
284
534623
                domain,
285
534623
                generator: None,
286
534623
            }),
287
534623
        )
288
534623
    }
289

            
290
    /// Creates a quantified declaration backed by a generator declaration.
291
    ///
292
    /// This is used in comprehensions to refer to a quantified variable that is already defined using a generator.
293
    pub fn new_quantified_from_generator(decl: &DeclarationPtr) -> Option<DeclarationPtr> {
294
        let kind = DeclarationKind::Quantified(Quantified {
295
            domain: decl.domain()?,
296
            generator: Some(decl.clone()),
297
        });
298
        Some(DeclarationPtr::new(decl.name().clone(), kind))
299
    }
300

            
301
323463
    pub fn new_quantified_expr(name: Name, expr: Expression) -> DeclarationPtr {
302
323463
        let kind = DeclarationKind::QuantifiedExpr(expr);
303
323463
        DeclarationPtr::new(name, kind)
304
323463
    }
305

            
306
    /// Creates a new value letting declaration.
307
    ///
308
    /// # Examples
309
    ///
310
    /// ```
311
    /// use conjure_cp_core::ast::{DeclarationPtr,Name,DeclarationKind,Domain,Range, Expression,
312
    /// Literal,Atom,Moo};
313
    /// use conjure_cp_core::{matrix_expr,ast::Metadata};
314
    ///
315
    /// // letting n be 10 + 10
316
    /// let ten = Expression::Atomic(Metadata::new(),Atom::Literal(Literal::Int(10)));
317
    /// let expression = Expression::Sum(Metadata::new(),Moo::new(matrix_expr![ten.clone(),ten]));
318
    /// let declaration = DeclarationPtr::new_value_letting(
319
    ///     Name::User("n".into()),
320
    ///     expression);
321
    ///
322
    /// ```
323
595231
    pub fn new_value_letting(name: Name, expression: Expression) -> DeclarationPtr {
324
595231
        let kind = DeclarationKind::ValueLetting(expression, None);
325
595231
        DeclarationPtr::new(name, kind)
326
595231
    }
327

            
328
    /// Creates a new value letting declaration with domain.
329
    ///
330
    /// # Examples
331
    ///
332
    /// ```
333
    /// use conjure_cp_core::ast::{DeclarationPtr,Name,DeclarationKind,Domain,Range, Expression,
334
    /// Literal,Atom,Moo,DomainPtr,Metadata};
335
    /// use conjure_cp_core::{matrix_expr};
336
    ///
337
    /// // letting n be 10 + 10
338
    /// let ten = Expression::Atomic(Metadata::new(),Atom::Literal(Literal::Int(10)));
339
    /// let expression = Expression::Sum(Metadata::new(),Moo::new(matrix_expr![ten.clone(),ten]));
340
    /// let domain = Domain::bool();
341
    /// let declaration = DeclarationPtr::new_value_letting_with_domain(
342
    ///     Name::User("n".into()),
343
    ///     expression,
344
    ///     domain,
345
    /// );
346
    /// ```
347
406562
    pub fn new_value_letting_with_domain(
348
406562
        name: Name,
349
406562
        expression: Expression,
350
406562
        domain: DomainPtr,
351
406562
    ) -> DeclarationPtr {
352
406562
        let kind = DeclarationKind::ValueLetting(expression, Some(domain));
353
406562
        DeclarationPtr::new(name, kind)
354
406562
    }
355

            
356
    /// Creates a new domain letting declaration.
357
    ///
358
    /// # Examples
359
    ///
360
    /// ```
361
    /// use conjure_cp_core::ast::{DeclarationPtr,Name,DeclarationKind,Domain,Range};
362
    ///
363
    /// // letting MyDomain be int(1..5)
364
    /// let declaration = DeclarationPtr::new_domain_letting(
365
    ///     Name::User("MyDomain".into()),
366
    ///     Domain::int(vec![Range::Bounded(1,5)]));
367
    ///
368
    /// ```
369
79437
    pub fn new_domain_letting(name: Name, domain: DomainPtr) -> DeclarationPtr {
370
79437
        let kind = DeclarationKind::DomainLetting(domain);
371
79437
        DeclarationPtr::new(name, kind)
372
79437
    }
373

            
374
    /// Creates a new enumerated type declaration
375
    /// TODO: Example
376
20
    pub fn new_enumerated(name: Name, ty: Moo<EnumeratedType>) -> DeclarationPtr {
377
20
        let kind = DeclarationKind::EnumeratedType(ty);
378
20
        DeclarationPtr::new(name, kind)
379
20
    }
380

            
381
    /// Creates a new unnamed type declaration
382
    /// TODO: Example
383
24
    pub fn new_unnamed(name: Name, size: u32) -> DeclarationPtr {
384
24
        let kind = DeclarationKind::UnnamedType(size);
385
24
        DeclarationPtr::new(name, kind)
386
24
    }
387

            
388
    /**********************************************/
389
    /*        Declaration accessor methods        */
390
    /**********************************************/
391

            
392
    /// Gets the domain of the declaration, if it has one.
393
    ///
394
    /// # Examples
395
    ///
396
    /// ```
397
    /// use conjure_cp_core::ast::{DeclarationPtr, Name, Domain, Range, GroundDomain};
398
    ///
399
    /// // find a: int(1..5)
400
    /// let declaration = DeclarationPtr::new_find(Name::User("a".into()),Domain::int(vec![Range::Bounded(1,5)]));
401
    ///
402
    /// assert!(declaration.domain().is_some_and(|x| x.as_ground().unwrap() == &GroundDomain::Int(vec![Range::Bounded(1,5)], None)))
403
    ///
404
    /// ```
405
14971456445
    pub fn domain(&self) -> Option<DomainPtr> {
406
14971456445
        let declaration = self.read();
407
        // Expressions stored inside a declaration (as opposed to the constraint tree the rewrite
408
        // engine walks) can be mutated in place by substitution utilities that never touch
409
        // the constraint-tree metadata cache, so `domain_of`'s cache would go stale silently for
410
        // them. Use the uncached path here.
411
14971456445
        match &declaration.kind {
412
            DeclarationKind::Find(var) | DeclarationKind::FindAuxiliary(var) => {
413
14917619249
                Some(var.domain_of())
414
            }
415
            DeclarationKind::ValueLetting(e, domain) => {
416
22961323
                domain.clone().or_else(|| e.domain_of_uncached())
417
            }
418
10132
            DeclarationKind::TemporaryValueLetting(e) => e.domain_of_uncached(),
419
13040313
            DeclarationKind::DomainLetting(domain) => Some(domain.clone()),
420
1385890
            DeclarationKind::Given(domain) => Some(domain.clone()),
421
16183489
            DeclarationKind::Quantified(inner) => Some(inner.domain.clone()),
422
255889
            DeclarationKind::QuantifiedExpr(expr) => expr.domain_of_uncached()?.element_domain(),
423
56
            DeclarationKind::EnumeratedType(et) => Some(et.to_domain()),
424
104
            DeclarationKind::UnnamedType(size) => Some(
425
104
                Moo::new(crate::ast::GroundDomain::UnnamedType(Moo::new(
426
104
                    crate::ast::unnamed::UnnamedType {
427
104
                        name: declaration.name.clone(),
428
104
                        size: *size,
429
104
                    },
430
104
                )))
431
104
                .into(),
432
104
            ),
433
        }
434
14971456445
    }
435

            
436
    /// Returns true if this declaration is an auxiliary find.
437
    ///
438
    /// Auxiliary finds are solver variables that must not be included in the search/branching
439
    /// order (see [`DeclarationKind::FindAuxiliary`]).
440
75533860
    pub fn is_find_auxiliary(&self) -> bool {
441
75533860
        matches!(
442
75533860
            &self.kind() as &DeclarationKind,
443
            DeclarationKind::FindAuxiliary(_)
444
        )
445
75533860
    }
446

            
447
    /// Gets the domain of the declaration and fully resolve it
448
3505020287
    pub fn resolved_domain(&self) -> Option<Moo<GroundDomain>> {
449
3505020287
        self.domain()?.resolve().ok()
450
3505020287
    }
451

            
452
    /// Gets the kind of the declaration.
453
    ///
454
    /// # Examples
455
    ///
456
    /// ```
457
    /// use conjure_cp_core::ast::{DeclarationPtr,DeclarationKind,Name,Domain,Range};
458
    ///
459
    /// // find a: int(1..5)
460
    /// let declaration = DeclarationPtr::new_find(Name::User("a".into()),Domain::int(vec![Range::Bounded(1,5)]));
461
    /// assert!(matches!(&declaration.kind() as &DeclarationKind, DeclarationKind::Find(_)))
462
    /// ```
463
8950261049
    pub fn kind(&self) -> MappedRwLockReadGuard<'_, DeclarationKind> {
464
8950261049
        self.map(|x| &x.kind)
465
8950261049
    }
466

            
467
    /// Gets the name of the declaration.
468
    ///
469
    /// # Examples
470
    ///
471
    /// ```
472
    /// use conjure_cp_core::ast::{DeclarationPtr,Name,Domain,Range};
473
    ///
474
    /// // find a: int(1..5)
475
    /// let declaration = DeclarationPtr::new_find(Name::User("a".into()),Domain::int(vec![Range::Bounded(1,5)]));
476
    ///
477
    /// assert_eq!(&declaration.name() as &Name, &Name::User("a".into()))
478
    /// ```
479
6200790638
    pub fn name(&self) -> MappedRwLockReadGuard<'_, Name> {
480
6200790638
        self.map(|x| &x.name)
481
6200790638
    }
482

            
483
    /// This declaration as a decision variable, if it is one.
484
    ///
485
    /// Both user [`DeclarationKind::Find`] and rewriter-introduced
486
    /// [`DeclarationKind::FindAuxiliary`] declarations are treated as decision variables.
487
5329537665
    pub fn as_find(&self) -> Option<MappedRwLockReadGuard<'_, DecisionVariable>> {
488
5329537665
        RwLockReadGuard::try_map(self.read(), |x| match &x.kind {
489
5317126578
            DeclarationKind::Find(var) | DeclarationKind::FindAuxiliary(var) => Some(var),
490
12411087
            _ => None,
491
5329537665
        })
492
        .ok()
493
5329537665
    }
494

            
495
    /// This declaration as a mutable decision variable, if it is one.
496
    ///
497
    /// Both user [`DeclarationKind::Find`] and rewriter-introduced
498
    /// [`DeclarationKind::FindAuxiliary`] declarations are treated as decision variables.
499
535666
    pub fn as_find_mut(&mut self) -> Option<DeclarationMutGuard<'_, DecisionVariable>> {
500
535666
        RwLockWriteGuard::try_map(self.write(), |x| match &mut x.kind {
501
246447
            DeclarationKind::Find(var) | DeclarationKind::FindAuxiliary(var) => Some(var),
502
289219
            _ => None,
503
535666
        })
504
        .ok()
505
535666
        .map(DeclarationMutGuard::new)
506
535666
    }
507

            
508
    /// This declaration as a domain letting, if it is one.
509
29621101
    pub fn as_domain_letting(&self) -> Option<MappedRwLockReadGuard<'_, DomainPtr>> {
510
29621101
        RwLockReadGuard::try_map(self.read(), |x| {
511
29621101
            if let DeclarationKind::DomainLetting(domain) = &x.kind {
512
29621072
                Some(domain)
513
            } else {
514
29
                None
515
            }
516
29621101
        })
517
        .ok()
518
29621101
    }
519

            
520
    /// This declaration as a mutable domain letting, if it is one.
521
    pub fn as_domain_letting_mut(&mut self) -> Option<DeclarationMutGuard<'_, DomainPtr>> {
522
        RwLockWriteGuard::try_map(self.write(), |x| {
523
            if let DeclarationKind::DomainLetting(domain) = &mut x.kind {
524
                Some(domain)
525
            } else {
526
                None
527
            }
528
        })
529
        .ok()
530
        .map(DeclarationMutGuard::new)
531
    }
532

            
533
    /// This declaration as a value letting, if it is one.
534
4672402097
    pub fn as_value_letting(&self) -> Option<MappedRwLockReadGuard<'_, Expression>> {
535
4672402097
        RwLockReadGuard::try_map(self.read(), |x| {
536
4672402097
            if let DeclarationKind::ValueLetting(expression, _)
537
4672402097
            | DeclarationKind::TemporaryValueLetting(expression) = &x.kind
538
            {
539
68376525
                Some(expression)
540
            } else {
541
4604025572
                None
542
            }
543
4672402097
        })
544
        .ok()
545
4672402097
    }
546

            
547
    /// This declaration as a mutable value letting, if it is one.
548
2060452
    pub fn as_value_letting_mut(&mut self) -> Option<DeclarationMutGuard<'_, Expression>> {
549
2060452
        RwLockWriteGuard::try_map(self.write(), |x| {
550
2060452
            if let DeclarationKind::ValueLetting(expression, _)
551
2060452
            | DeclarationKind::TemporaryValueLetting(expression) = &mut x.kind
552
            {
553
2060452
                Some(expression)
554
            } else {
555
                None
556
            }
557
2060452
        })
558
        .ok()
559
2060452
        .map(DeclarationMutGuard::new)
560
2060452
    }
561

            
562
    /// This declaration as a given statement, if it is one.
563
778481
    pub fn as_given(&self) -> Option<MappedRwLockReadGuard<'_, DomainPtr>> {
564
778481
        RwLockReadGuard::try_map(self.read(), |x| {
565
778481
            if let DeclarationKind::Given(domain) = &x.kind {
566
485576
                Some(domain)
567
            } else {
568
292905
                None
569
            }
570
778481
        })
571
        .ok()
572
778481
    }
573

            
574
    /// This declaration as a mutable given statement, if it is one.
575
    pub fn as_given_mut(&mut self) -> Option<DeclarationMutGuard<'_, DomainPtr>> {
576
        RwLockWriteGuard::try_map(self.write(), |x| {
577
            if let DeclarationKind::Given(domain) = &mut x.kind {
578
                Some(domain)
579
            } else {
580
                None
581
            }
582
        })
583
        .ok()
584
        .map(DeclarationMutGuard::new)
585
    }
586

            
587
    /// This declaration as a quantified expression, if it is one.
588
4496097
    pub fn as_quantified_expr(&self) -> Option<MappedRwLockReadGuard<'_, Expression>> {
589
4496097
        RwLockReadGuard::try_map(self.read(), |x| {
590
4496097
            if let DeclarationKind::QuantifiedExpr(expr) = &x.kind {
591
4496097
                Some(expr)
592
            } else {
593
                None
594
            }
595
4496097
        })
596
        .ok()
597
4496097
    }
598

            
599
    /// This declaration as a mutable quantified expression, if it is one.
600
    pub fn as_quantified_expr_mut(&mut self) -> Option<DeclarationMutGuard<'_, Expression>> {
601
        RwLockWriteGuard::try_map(self.write(), |x| {
602
            if let DeclarationKind::QuantifiedExpr(expr) = &mut x.kind {
603
                Some(expr)
604
            } else {
605
                None
606
            }
607
        })
608
        .ok()
609
        .map(DeclarationMutGuard::new)
610
    }
611

            
612
    /// This declaration as an enumerated type, if it is one.
613
192580
    pub fn as_enumerated_type(&self) -> Option<MappedRwLockReadGuard<'_, Moo<EnumeratedType>>> {
614
192580
        RwLockReadGuard::try_map(self.read(), |x| {
615
192580
            if let DeclarationKind::EnumeratedType(e) = &x.kind {
616
8
                Some(e)
617
            } else {
618
192572
                None
619
            }
620
192580
        })
621
        .ok()
622
192580
    }
623

            
624
    /// This declaration as a mutable enumerated type, if it is one.
625
    pub fn as_enumerated_type_mut(
626
        &mut self,
627
    ) -> Option<DeclarationMutGuard<'_, Moo<EnumeratedType>>> {
628
        RwLockWriteGuard::try_map(self.write(), |x| {
629
            if let DeclarationKind::EnumeratedType(e) = &mut x.kind {
630
                Some(e)
631
            } else {
632
                None
633
            }
634
        })
635
        .ok()
636
        .map(DeclarationMutGuard::new)
637
    }
638

            
639
    /// This declaration as an unnamed type, if it is one.
640
192604
    pub fn as_unnamed_type(&self) -> Option<MappedRwLockReadGuard<'_, u32>> {
641
192604
        RwLockReadGuard::try_map(self.read(), |x| {
642
192604
            if let DeclarationKind::UnnamedType(e) = &x.kind {
643
28
                Some(e)
644
            } else {
645
192576
                None
646
            }
647
192604
        })
648
        .ok()
649
192604
    }
650

            
651
    /// This declaration as a mutable unnamed type, if it is one.
652
    pub fn as_unnamed_type_mut(&mut self) -> Option<DeclarationMutGuard<'_, u32>> {
653
        RwLockWriteGuard::try_map(self.write(), |x| {
654
            if let DeclarationKind::UnnamedType(e) = &mut x.kind {
655
                Some(e)
656
            } else {
657
                None
658
            }
659
        })
660
        .ok()
661
        .map(DeclarationMutGuard::new)
662
    }
663

            
664
    /// Changes the name in this declaration, returning the old one.
665
    ///
666
    /// # Examples
667
    ///
668
    /// ```
669
    /// use conjure_cp_core::ast::{DeclarationPtr, Domain, Range, Name};
670
    ///
671
    /// // find a: int(1..5)
672
    /// let mut declaration = DeclarationPtr::new_find(Name::User("a".into()),Domain::int(vec![Range::Bounded(1,5)]));
673
    ///
674
    /// let old_name = declaration.replace_name(Name::User("b".into()));
675
    /// assert_eq!(old_name,Name::User("a".into()));
676
    /// assert_eq!(&declaration.name() as &Name,&Name::User("b".into()));
677
    /// ```
678
87
    pub fn replace_name(&mut self, name: Name) -> Name {
679
87
        let mut current_name = self.map_mut(|decl| &mut decl.name);
680
87
        std::mem::replace(&mut *current_name, name)
681
87
    }
682

            
683
    /// Replaces the underlying declaration kind and returns the previous kind.
684
    /// Note: this affects all cloned `DeclarationPtr`s pointing to the same declaration.
685
40630249
    pub fn replace_kind(&mut self, kind: DeclarationKind) -> DeclarationKind {
686
40630249
        let mut current_kind = self.map_mut(|decl| &mut decl.kind);
687
40630249
        std::mem::replace(&mut *current_kind, kind)
688
40630249
    }
689

            
690
    /*****************************************/
691
    /*        Pointer utility methods        */
692
    /*****************************************/
693

            
694
    // These are mostly wrappers over RefCell, Ref, and RefMut methods, re-exported here for
695
    // convenience.
696

            
697
    /// Read the underlying [Declaration].
698
    ///
699
    /// Will block the current thread until no other thread has a write lock.
700
    /// Attempting to get a read lock if the current thread already has one
701
    /// **will** cause it to deadlock.
702
    /// The lock is released when the returned guard goes out of scope.
703
43828910947
    fn read(&self) -> RwLockReadGuard<'_, Declaration> {
704
43828910947
        self.inner.value.read()
705
43828910947
    }
706

            
707
    /// Write the underlying [Declaration].
708
    ///
709
    /// Will block the current thread until no other thread has a read or write lock.
710
    /// The lock is released when the returned guard goes out of scope.
711
44319775
    fn write(&mut self) -> RwLockWriteGuard<'_, Declaration> {
712
44319775
        self.inner.value.write()
713
44319775
    }
714

            
715
    /// Creates a new declaration pointer with the same contents as `self` that is not shared with
716
    /// anyone else.
717
    ///
718
    /// As the resulting pointer is unshared, it will have a new id.
719
    ///
720
    /// # Examples
721
    ///
722
    /// ```
723
    /// use conjure_cp_core::ast::{DeclarationPtr,Name,Domain,Range};
724
    ///
725
    /// // find a: int(1..5)
726
    /// let declaration = DeclarationPtr::new_find(Name::User("a".into()),Domain::int(vec![Range::Bounded(1,5)]));
727
    ///
728
    /// let mut declaration2 = declaration.clone();
729
    ///
730
    /// declaration2.replace_name(Name::User("b".into()));
731
    ///
732
    /// assert_eq!(&declaration.name() as &Name, &Name::User("b".into()));
733
    /// assert_eq!(&declaration2.name() as &Name, &Name::User("b".into()));
734
    ///
735
    /// declaration2 = declaration2.detach();
736
    ///
737
    /// assert_eq!(&declaration2.name() as &Name, &Name::User("b".into()));
738
    ///
739
    /// declaration2.replace_name(Name::User("c".into()));
740
    ///
741
    /// assert_eq!(&declaration.name() as &Name, &Name::User("b".into()));
742
    /// assert_eq!(&declaration2.name() as &Name, &Name::User("c".into()));
743
    /// ```
744
67998405
    pub fn detach(self) -> DeclarationPtr {
745
        // despite having the same contents, the new declaration pointer is unshared, so it should
746
        // get a new id.
747
67998405
        let value = self.inner.value.read().clone();
748
67998405
        let representations = self.inner.representations.read().clone();
749
67998405
        let source = self.inner.source.read().clone();
750
67998405
        let detached = DeclarationPtr {
751
67998405
            inner: DeclarationPtrInner::new(RwLock::new(value)),
752
67998405
        };
753
67998405
        *detached.inner.representations.write() = representations;
754
67998405
        *detached.inner.source.write() = source;
755
67998405
        detached
756
67998405
    }
757

            
758
    /// Applies `f` to the declaration, returning the result as a reference.
759
15151051687
    fn map<U>(&self, f: impl FnOnce(&Declaration) -> &U) -> MappedRwLockReadGuard<'_, U> {
760
15151051687
        RwLockReadGuard::map(self.read(), f)
761
15151051687
    }
762

            
763
    /// Applies mutable function `f` to the declaration, returning the result as a mutable reference.
764
40630336
    fn map_mut<U>(
765
40630336
        &mut self,
766
40630336
        f: impl FnOnce(&mut Declaration) -> &mut U,
767
40630336
    ) -> DeclarationMutGuard<'_, U> {
768
40630336
        DeclarationMutGuard::new(RwLockWriteGuard::map(self.write(), f))
769
40630336
    }
770

            
771
    /// Replaces the declaration with a new one, returning the old value, without deinitialising
772
    /// either one.
773
1093321
    pub fn replace(&mut self, declaration: Declaration) -> Declaration {
774
1093321
        let mut guard = self.write();
775
1093321
        let ans = mem::replace(&mut *guard, declaration);
776
1093321
        drop(guard);
777
1093321
        mark_declaration_content_changed();
778
1093321
        ans
779
1093321
    }
780

            
781
    /// Hashes the declaration contents rather than the stable declaration pointer id.
782
    ///
783
    /// Pointer hashing intentionally remains id-based for map/set invariants. This helper is for
784
    /// rewrite caches that need to be invalidated when the declaration value behind a reference
785
    /// changes.
786
2988875775
    pub(crate) fn content_hash(&self) -> u64 {
787
2988875775
        let mut hasher = DefaultHasher::new();
788
2988875775
        let mut seen = BTreeSet::new();
789
2988875775
        self.hash_content(&mut hasher, &mut seen);
790
2988875775
        hasher.finish()
791
2988875775
    }
792

            
793
    /// Compares current declaration contents without considering pointer identity.
794
7618007728
    pub(crate) fn content_eq(&self, other: &Self) -> bool {
795
7618007728
        if self.id() == other.id() {
796
7618007728
            return true;
797
        }
798
        let this = self.read().clone();
799
        let other = other.read().clone();
800
        this == other
801
7618007728
    }
802

            
803
    /// Hashes this declaration's value into `state`, guarding against declaration-reference cycles.
804
2988875775
    fn hash_content<H: Hasher>(&self, state: &mut H, seen: &mut BTreeSet<ObjId>) {
805
2988875775
        let id = self.id();
806
2988875775
        if !seen.insert(id.clone()) {
807
            "recursive-declaration".hash(state);
808
            return;
809
2988875775
        }
810

            
811
2988875775
        let declaration = self.read();
812
2988875775
        declaration.name.hash(state);
813
2988875775
        declaration.kind.hash_content(state, seen);
814
2988875775
        seen.remove(&id);
815
2988875775
    }
816
}
817

            
818
impl CategoryOf for DeclarationPtr {
819
23649692
    fn category_of(&self) -> Category {
820
23649692
        match &self.kind() as &DeclarationKind {
821
            DeclarationKind::Find(decision_variable)
822
23512499
            | DeclarationKind::FindAuxiliary(decision_variable) => decision_variable.category_of(),
823
            DeclarationKind::ValueLetting(expression, _)
824
58877
            | DeclarationKind::TemporaryValueLetting(expression) => expression.category_of(),
825
            DeclarationKind::DomainLetting(_) => Category::Constant,
826
            DeclarationKind::Given(_) => Category::Parameter,
827
77156
            DeclarationKind::Quantified(..) => Category::Quantified,
828
1160
            DeclarationKind::QuantifiedExpr(..) => Category::Quantified,
829
            DeclarationKind::EnumeratedType(_) | DeclarationKind::UnnamedType(_) => {
830
                Category::Constant
831
            }
832
        }
833
23649692
    }
834
}
835
impl HasId for DeclarationPtr {
836
    const TYPE_NAME: &'static str = "DeclarationPtrInner";
837
18295468812
    fn id(&self) -> ObjId {
838
18295468812
        self.inner.id.clone()
839
18295468812
    }
840
}
841

            
842
impl DefaultWithId for DeclarationPtr {
843
    fn default_with_id(id: ObjId) -> Self {
844
        DeclarationPtr {
845
            inner: DeclarationPtrInner::new_with_id_unchecked(
846
                RwLock::new(Declaration {
847
                    name: Name::User("_UNKNOWN".into()),
848
                    kind: DeclarationKind::ValueLetting(false.into(), None),
849
                }),
850
                id,
851
            ),
852
        }
853
    }
854
}
855

            
856
impl Typeable for DeclarationPtr {
857
    fn return_type(&self) -> ReturnType {
858
        let declaration = self.read();
859
        match &declaration.kind {
860
            DeclarationKind::Find(var) | DeclarationKind::FindAuxiliary(var) => var.return_type(),
861
            DeclarationKind::ValueLetting(expression, _)
862
            | DeclarationKind::TemporaryValueLetting(expression) => expression.return_type(),
863
            DeclarationKind::DomainLetting(domain) => domain.return_type(),
864
            DeclarationKind::Given(domain) => domain.return_type(),
865
            DeclarationKind::Quantified(inner) => inner.domain.return_type(),
866
            DeclarationKind::QuantifiedExpr(expr) => expr.return_type(),
867
            DeclarationKind::EnumeratedType(ty) => ReturnType::EnumeratedType(ty.clone()),
868
            DeclarationKind::UnnamedType(size) => {
869
                ReturnType::UnnamedType(Moo::new(crate::ast::unnamed::UnnamedType {
870
                    name: declaration.name.clone(),
871
                    size: *size,
872
                }))
873
            }
874
        }
875
    }
876
}
877

            
878
impl Uniplate for DeclarationPtr {
879
12640992
    fn uniplate(&self) -> (Tree<Self>, Box<dyn Fn(Tree<Self>) -> Self>) {
880
12640992
        let decl = self.read();
881
12640992
        let (tree, recons) = Biplate::<DeclarationPtr>::biplate(&decl as &Declaration);
882

            
883
12640992
        let self2 = self.clone();
884
        (
885
12640992
            tree,
886
12640992
            Box::new(move |x| {
887
755486
                let mut self3 = self2.clone();
888
755486
                let inner = recons(x);
889
755486
                let _ = self3.replace(inner);
890
755486
                self3
891
755486
            }),
892
        )
893
12640992
    }
894
}
895

            
896
impl<To> Biplate<To> for DeclarationPtr
897
where
898
    Declaration: Biplate<To>,
899
    To: Uniplate,
900
{
901
680301267
    fn biplate(&self) -> (Tree<To>, Box<dyn Fn(Tree<To>) -> Self>) {
902
680301267
        if TypeId::of::<To>() == TypeId::of::<Self>() {
903
            unsafe {
904
12640992
                let self_as_to = std::mem::transmute::<&Self, &To>(self).clone();
905
                (
906
12640992
                    Tree::One(self_as_to),
907
12640992
                    Box::new(move |x| {
908
536412
                        let Tree::One(x) = x else { panic!() };
909

            
910
536412
                        let x_as_self = std::mem::transmute::<&To, &Self>(&x);
911
536412
                        x_as_self.clone()
912
536412
                    }),
913
                )
914
            }
915
        } else {
916
            // call biplate on the enclosed declaration
917
667660275
            let decl = self.read();
918
667660275
            let (tree, recons) = Biplate::<To>::biplate(&decl as &Declaration);
919

            
920
667660275
            let self2 = self.clone();
921
            (
922
667660275
                tree,
923
667660275
                Box::new(move |x| {
924
95121
                    let mut self3 = self2.clone();
925
95121
                    let inner = recons(x);
926
95121
                    let _ = self3.replace(inner);
927
95121
                    self3
928
95121
                }),
929
            )
930
        }
931
680301267
    }
932
}
933

            
934
type ReferenceTree = Tree<Reference>;
935
type ReferenceReconstructor<T> = Box<dyn Fn(ReferenceTree) -> T>;
936

            
937
impl Biplate<Reference> for DeclarationPtr {
938
1939400629
    fn biplate(&self) -> (ReferenceTree, ReferenceReconstructor<Self>) {
939
1939400629
        let (tree, recons_kind) = biplate_declaration_kind_references(self.kind().clone());
940

            
941
1939400629
        let self2 = self.clone();
942
        (
943
1939400629
            tree,
944
1939400629
            Box::new(move |x| {
945
103965
                let mut self3 = self2.clone();
946
103965
                let _ = self3.replace_kind(recons_kind(x));
947
103965
                self3
948
103965
            }),
949
        )
950
1939400629
    }
951
}
952

            
953
1939052343
fn biplate_domain_ptr_references(
954
1939052343
    domain: DomainPtr,
955
1939052343
) -> (ReferenceTree, ReferenceReconstructor<DomainPtr>) {
956
1939052343
    let domain_inner = domain.as_ref().clone();
957
1939052343
    let (tree, recons_domain) = Biplate::<Reference>::biplate(&domain_inner);
958
1939052343
    (tree, Box::new(move |x| Moo::new(recons_domain(x))))
959
1939052343
}
960

            
961
1939400629
fn biplate_declaration_kind_references(
962
1939400629
    kind: DeclarationKind,
963
1939400629
) -> (ReferenceTree, ReferenceReconstructor<DeclarationKind>) {
964
1939400629
    match kind {
965
        DeclarationKind::Find(var) => {
966
125356616
            let (tree, recons_domain) = biplate_domain_ptr_references(var.domain.clone());
967
            (
968
125356616
                tree,
969
125356616
                Box::new(move |x| {
970
47763
                    let mut var2 = var.clone();
971
47763
                    var2.domain = recons_domain(x);
972
47763
                    DeclarationKind::Find(var2)
973
47763
                }),
974
            )
975
        }
976
        DeclarationKind::FindAuxiliary(var) => {
977
1812950980
            let (tree, recons_domain) = biplate_domain_ptr_references(var.domain.clone());
978
            (
979
1812950980
                tree,
980
1812950980
                Box::new(move |x| {
981
56202
                    let mut var2 = var.clone();
982
56202
                    var2.domain = recons_domain(x);
983
56202
                    DeclarationKind::FindAuxiliary(var2)
984
56202
                }),
985
            )
986
        }
987
        DeclarationKind::Given(domain) => {
988
174608
            let (tree, recons_domain) = biplate_domain_ptr_references(domain);
989
            (
990
174608
                tree,
991
174608
                Box::new(move |x| DeclarationKind::Given(recons_domain(x))),
992
            )
993
        }
994
        DeclarationKind::DomainLetting(domain) => {
995
570139
            let (tree, recons_domain) = biplate_domain_ptr_references(domain);
996
            (
997
570139
                tree,
998
570139
                Box::new(move |x| DeclarationKind::DomainLetting(recons_domain(x))),
999
            )
        }
        DeclarationKind::ValueLetting(expression, domain) => {
348286
            let (tree, recons_expr) = Biplate::<Reference>::biplate(&expression);
            (
348286
                tree,
348286
                Box::new(move |x| DeclarationKind::ValueLetting(recons_expr(x), domain.clone())),
            )
        }
        DeclarationKind::TemporaryValueLetting(expression) => {
            let (tree, recons_expr) = Biplate::<Reference>::biplate(&expression);
            (
                tree,
                Box::new(move |x| DeclarationKind::TemporaryValueLetting(recons_expr(x))),
            )
        }
        DeclarationKind::Quantified(quantified) => {
            let (domain_tree, recons_domain) =
                biplate_domain_ptr_references(quantified.domain.clone());
            let (generator_tree, recons_generator) = if let Some(generator) = quantified.generator()
            {
                let generator = generator.clone();
                let (tree, recons_declaration) = Biplate::<Reference>::biplate(&generator);
                (
                    tree,
                    Box::new(move |x| Some(recons_declaration(x)))
                        as ReferenceReconstructor<Option<DeclarationPtr>>,
                )
            } else {
                (
                    Tree::Zero,
                    Box::new(|_| None) as ReferenceReconstructor<Option<DeclarationPtr>>,
                )
            };
            (
                Tree::Many(VecDeque::from([domain_tree, generator_tree])),
                Box::new(move |x| {
                    let Tree::Many(mut children) = x else {
                        panic!("unexpected biplate tree shape for quantified declaration")
                    };
                    let domain = children.pop_front().unwrap_or(Tree::Zero);
                    let generator = children.pop_front().unwrap_or(Tree::Zero);
                    let mut quantified2 = quantified.clone();
                    quantified2.domain = recons_domain(domain);
                    quantified2.generator = recons_generator(generator);
                    DeclarationKind::Quantified(quantified2)
                }),
            )
        }
        DeclarationKind::QuantifiedExpr(expr) => {
            let (tree, recons_expr) = Biplate::<Reference>::biplate(&expr);
            (
                tree,
                Box::new(move |x| DeclarationKind::QuantifiedExpr(recons_expr(x))),
            )
        }
        kind @ (DeclarationKind::EnumeratedType(_) | DeclarationKind::UnnamedType(_)) => {
            (Tree::Zero, Box::new(move |_| kind.clone()))
        }
    }
1939400629
}
impl IdPtr for DeclarationPtr {
    type Data = Declaration;
5148
    fn get_data(&self) -> Self::Data {
5148
        self.read().clone()
5148
    }
    fn with_id_and_data(id: ObjId, data: Self::Data) -> Self {
        Self {
            inner: DeclarationPtrInner::new_with_id_unchecked(RwLock::new(data), id),
        }
    }
}
impl Ord for DeclarationPtr {
    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
        self.inner.id.cmp(&other.inner.id)
    }
}
impl PartialOrd for DeclarationPtr {
    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
        Some(self.cmp(other))
    }
}
impl PartialEq for DeclarationPtr {
115723195
    fn eq(&self, other: &Self) -> bool {
115723195
        self.inner.id == other.inner.id
115723195
    }
}
impl Eq for DeclarationPtr {}
impl std::hash::Hash for DeclarationPtr {
7184217
    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
        // invariant: x == y -> hash(x) == hash(y)
7184217
        self.inner.id.hash(state);
7184217
    }
}
impl Display for DeclarationPtr {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        let value: &Declaration = &self.read();
        value.fmt(f)
    }
}
#[derive(Clone, PartialEq, Debug, Serialize, Deserialize, Eq, Uniplate)]
#[biplate(to=Expression)]
#[biplate(to=DeclarationPtr)]
#[biplate(to=Name)]
/// The contents of a declaration
pub struct Declaration {
    /// The name of the declared symbol.
    name: Name,
    /// The kind of the declaration.
    kind: DeclarationKind,
}
impl Declaration {
    /// Creates a new declaration.
655067006
    pub fn new(name: Name, kind: DeclarationKind) -> Declaration {
655067006
        Declaration { name, kind }
655067006
    }
}
/// A specific kind of declaration.
#[non_exhaustive]
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Uniplate)]
#[biplate(to=Expression)]
#[biplate(to=DeclarationPtr)]
#[biplate(to=Declaration)]
pub enum DeclarationKind {
    Find(DecisionVariable),
    /// A rewriter-introduced or `findAux`-declared decision variable that must not be branched on
    /// during search.
    ///
    /// Used for auxiliaries such as those created when rewriting `exists` into constraints.
    FindAuxiliary(DecisionVariable),
    Given(DomainPtr),
    Quantified(Quantified),
    QuantifiedExpr(Expression),
    /// Carries an optional domain so instantiated `given`s can retain their declared domain.
    ValueLetting(Expression, Option<DomainPtr>),
    DomainLetting(DomainPtr),
    /// A short-lived value binding used internally during rewrites (e.g. comprehension unrolling).
    ///
    /// Unlike `ValueLetting`, this is not intended to represent a user-visible top-level `letting`.
    TemporaryValueLetting(Expression),
    /// An enumerated type.
    EnumeratedType(Moo<EnumeratedType>),
    /// An unnamed type.
    UnnamedType(u32),
}
impl DeclarationKind {
    /// Hashes declaration-kind contents without using declaration pointer identity.
2988875775
    fn hash_content<H: Hasher>(&self, state: &mut H, seen: &mut BTreeSet<ObjId>) {
2988875775
        mem::discriminant(self).hash(state);
2988875775
        match self {
            DeclarationKind::Find(var) | DeclarationKind::FindAuxiliary(var) => {
2970123353
                var.domain.hash(state);
2970123353
                for representation in &var.representations {
                    for repr in representation {
                        repr.repr_name().hash(state);
                        if let Ok(declarations) = repr.declaration_down() {
                            for declaration in declarations {
                                declaration.hash_content(state, seen);
                            }
                        } else {
                            "unavailable-representation-declarations".hash(state);
                        }
                    }
                }
            }
            DeclarationKind::Given(domain) | DeclarationKind::DomainLetting(domain) => {
1281684
                domain.hash(state);
            }
            DeclarationKind::Quantified(quantified) => {
634950
                quantified.domain.hash(state);
634950
                if let Some(generator) = quantified.generator() {
                    generator.hash_content(state, seen);
634950
                }
            }
            DeclarationKind::QuantifiedExpr(expr)
            | DeclarationKind::TemporaryValueLetting(expr) => {
707880
                expr.cached_content_hash().hash(state);
707880
                expr.to_string().hash(state);
            }
64
            DeclarationKind::EnumeratedType(ty) => ty.hash(state),
56
            DeclarationKind::UnnamedType(size) => size.hash(state),
            DeclarationKind::ValueLetting(expr, domain) => {
16127788
                expr.cached_content_hash().hash(state);
16127788
                expr.to_string().hash(state);
16127788
                domain.hash(state);
            }
        }
2988875775
    }
}
#[serde_as]
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Uniplate)]
pub struct Quantified {
    domain: DomainPtr,
    #[serde_as(as = "Option<PtrAsInner>")]
    generator: Option<DeclarationPtr>,
}
impl Quantified {
21692
    pub fn domain(&self) -> &DomainPtr {
21692
        &self.domain
21692
    }
20476945
    pub fn generator(&self) -> Option<&DeclarationPtr> {
20476945
        self.generator.as_ref()
20476945
    }
}