scopegraphs/
label.rs

1use std::array;
2
3pub(crate) trait ArrayInit<T> {
4    fn init_from_fn(init: impl FnMut() -> T) -> Self;
5}
6
7impl<T, const N: usize> ArrayInit<T> for [T; N] {
8    fn init_from_fn(mut init: impl FnMut() -> T) -> Self {
9        array::from_fn(|_| init())
10    }
11}
12
13unsafe impl Label for () {
14    type Array<T> = [T; 1];
15
16    fn to_usize(&self) -> usize {
17        0
18    }
19
20    fn iter() -> impl Iterator<Item = Self>
21    where
22        Self: Sized,
23    {
24        [()].into_iter()
25    }
26
27    fn iter_ref() -> impl Iterator<Item = &'static Self>
28    where
29        Self: Sized + 'static,
30    {
31        [&()].into_iter()
32    }
33}
34
35/// Represents types that can be used as labels on [`scopegraph edges`](crate::concepts::edges).
36///
37/// Can, and should, be derived using the [`Label`](scopegraphs_macros::Label) derive macro.
38///
39/// # Safety
40///
41/// This trait is unsafe to implement by yourself, as code in this library depends on the fact
42/// that [`to_usize`](Label::to_usize) returns a list of consecutive indices from 0 to [`NUM_LABELS`](Label::NUM_LABELS) - 1
43pub unsafe trait Label: Eq + Copy {
44    /// The type of an array of these labels, with one slot for each label type.
45    /// NOTE: using an associated const doesn't work without full const generics
46    #[allow(private_bounds)]
47    type Array<T>: AsRef<[T]> + AsMut<[T]> + ArrayInit<T>;
48
49    /// Convert any label to a unique usize, which m
50    fn to_usize(&self) -> usize;
51
52    /// Iterate over all possible labels that this label type could be.
53    fn iter() -> impl Iterator<Item = Self>
54    where
55        Self: Sized;
56
57    /// Iterate over all possible labels that this label type could be, by reference.
58    fn iter_ref() -> impl Iterator<Item = &'static Self>
59    where
60        Self: Sized + 'static;
61}
62
63/// `query_regex` is a wrapper around [`compile_regex`](crate::compile_regex) that should be used
64/// when you're using the resulting regex only once, inline. This is often the case in
65/// [scope graph queries](crate::resolve::Query).
66///
67/// [`compile_regex`](crate::compile_regex) generates a type, which when instantiated can match
68/// a string. This macro avoids the need to instantiate, and combines the compiling and instantiation.
69#[macro_export]
70macro_rules! query_regex {
71    ($label_type:path: $($regex:tt)*) => {
72        {
73            $crate::compile_regex!(type QueryRegex<$label_type> = $($regex)*);
74            QueryRegex::new()
75        }
76    };
77}