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}