scopegraphs/resolve/
params.rs

1use crate::resolve::EdgeOrData;
2
3/// Unary predicate over `DATA`.
4///
5/// Used to select declarations that a query can resolve to.
6///
7/// `O` is the output of applying the function to some data.
8/// When executing the query, needs to be compatible with
9/// the completeness strategy for the underlying scope graph.
10pub trait DataWellformedness<'sg, DATA> {
11    /// Type of the well-formedness result. Should be a wrapper around a boolean.
12    type Output;
13    /// returns true if the data is well-formed.
14    fn data_wf(&self, data: &'sg DATA) -> Self::Output;
15}
16
17impl<'sg, DATA: 'sg, T, O: 'sg> DataWellformedness<'sg, DATA> for T
18where
19    T: Fn(&'sg DATA) -> O,
20{
21    type Output = O;
22
23    fn data_wf(&self, data: &'sg DATA) -> O {
24        self(data)
25    }
26}
27
28/// Default Data wellformedness implementation
29///
30/// Matches all data by default.
31#[derive(Default)]
32pub struct DefaultDataWellformedness {}
33
34impl<'sg, DATA> DataWellformedness<'sg, DATA> for DefaultDataWellformedness {
35    type Output = bool;
36
37    fn data_wf(&self, _data: &'sg DATA) -> bool {
38        true // match all data by default
39    }
40}
41
42/// Strict partial order on labels. Used to perform shadowing. Lower is more important.
43///
44/// Defaults to [`DefaultLabelOrder`],
45/// and should be constructed using the [`label_order`](crate::label_order) macro.
46///
47/// For example, suppose that in some scope `s`,
48/// declarations for some query are reachable via an `Lex` edge and an `Imp` edge
49/// (for lexical parent and import, respectively).
50///
51/// When the label order indicates `Lex < Imp`
52/// (i.e., declarations from a lexically enclosing scope have higher priority),
53/// the declaration over the `Imp` edge is shadowed,
54/// and will thus not be included in the environment.
55///
56/// If `Imp < Lex`, imports have higher priority, and that one will be included.
57/// Otherwise, paths to both declarations are included in the environment.
58pub trait LabelOrder<LABEL> {
59    /// Defines the strict partial ordering. Lower is more important
60    fn less_than(&self, l1: &EdgeOrData<LABEL>, l2: &EdgeOrData<LABEL>) -> bool;
61}
62
63impl<LABEL, T> LabelOrder<LABEL> for T
64where
65    T: for<'a, 'b> Fn(&'a EdgeOrData<LABEL>, &'b EdgeOrData<LABEL>) -> bool,
66{
67    fn less_than(&self, l1: &EdgeOrData<LABEL>, l2: &EdgeOrData<LABEL>) -> bool {
68        self(l1, l2)
69    }
70}
71
72/// Default label ordering: no label is more important than any other.
73#[derive(Default)]
74pub struct DefaultLabelOrder {}
75
76impl<LABEL> LabelOrder<LABEL> for DefaultLabelOrder {
77    fn less_than(&self, _l1: &EdgeOrData<LABEL>, _l2: &EdgeOrData<LABEL>) -> bool {
78        false // no shadowing by default
79    }
80}
81
82/// Data equivalence relation.
83///
84/// Defaults to [`DefaultDataEquivalence`].
85///
86/// Defines equivalence classes of declarations. Shadowing will only be applied with respect to
87/// declarations in the same equivalence class. That is, the shadowing explained in [`LabelOrder`]
88/// will only be applied if the declarations are equivalent.
89pub trait DataEquivalence<'sg, DATA> {
90    /// Output of the data equivalence function; should something that contains a [bool].
91    type Output;
92
93    /// Returns true if d1 is equivalent to d2
94    fn data_equiv(&self, d1: &'sg DATA, d2: &'sg DATA) -> Self::Output;
95
96    /// Returns if for this data equivalence, any data is always equivalent to any other data.
97    fn always_equivalent(&self) -> bool {
98        false
99    }
100}
101
102impl<'sg, DATA: 'sg, T, O: 'sg> DataEquivalence<'sg, DATA> for T
103where
104    T: Fn(&'sg DATA, &'sg DATA) -> O,
105{
106    type Output = O;
107
108    fn data_equiv(&self, d1: &'sg DATA, d2: &'sg DATA) -> Self::Output {
109        self(d1, d2)
110    }
111}
112
113/// Default data equivalence: data is always equivalent.
114#[derive(Default)]
115pub struct DefaultDataEquivalence {}
116
117impl<'sg, DATA> DataEquivalence<'sg, DATA> for DefaultDataEquivalence {
118    type Output = bool;
119
120    fn data_equiv(&self, _d1: &'sg DATA, _d2: &'sg DATA) -> bool {
121        true // all data in same equivalence class by default
122    }
123
124    fn always_equivalent(&self) -> bool {
125        true
126    }
127}