scopegraphs_lib/completeness/
mod.rs

1//! This module contains several utilities to guarantee query stability.
2//! Query stability means that the result of a query, once resolved, will remain valid after future
3//! additions to the scope graph.
4//! This allows safe interleaving of name resolution and scope graph construction.
5//!
6//! The main trait of this module is [`Completeness`]. An instance of this trait should be passed
7//! to [`super::ScopeGraph::new`] to obtain a correct scope graph instance.
8//!
9//! Currently the module contains two safe implementations.
10//! [`ImplicitClose`] is the easiest to use, and most likely the preferred choice for simple
11//! sequential type checkers.
12//! [`ExplicitClose`] requires some manual bookkeeping, but allows more flexible handling of
13//! queries. This is the most suitable choice for type checkers that need to do dynamic scheduling.
14
15use crate::{InnerScopeGraph, Scope};
16
17mod future;
18pub use future::*;
19
20mod critical_edge;
21pub use critical_edge::*;
22mod explicit;
23pub use explicit::*;
24mod implicit;
25pub use implicit::*;
26mod unchecked;
27pub use unchecked::*;
28
29mod private {
30    pub trait Sealed {}
31}
32
33use private::Sealed;
34
35/*** Completeness trait ***/
36
37/// Types implementing this trait have the responsibility to guarantee query stability.
38///
39/// This means that the result of a query, once computed, may not be invalidated by later extensions
40/// of the scope graph.
41///
42/// A [`super::ScopeGraph`] will call the handlers of its completeness on each operation.
43/// For scope addition and data access, it can update some internal state.
44/// For edge addition and retrieval, it can override/augment the default result as well.
45///
46/// The way query stability is guaranteed is very flexible. Current implementations use
47/// - critical edges, explicitly closed by the client ([`ExplicitClose`]).
48/// - critical edges, implicitly closed when retrieved ([`ImplicitClose`]).
49///
50/// Future implementations may also:
51/// - delay retrieval of edges until it is closed (by returning a future).
52/// - guarantee stability by retaining residual queries, and checking those do not return any
53///   results for later additions.
54/// - ...
55///
56/// This trait is sealed to ensure only verified implementations are available.
57pub trait Completeness<LABEL, DATA>: Sealed {
58    fn cmpl_new_scope(&self, inner_scope_graph: &InnerScopeGraph<LABEL, DATA>, scope: Scope);
59
60    /// Should initialize a scope without possibility to extend it with edges
61    fn cmpl_new_complete_scope(
62        &self,
63        inner_scope_graph: &InnerScopeGraph<LABEL, DATA>,
64        scope: Scope,
65    ) {
66        self.cmpl_new_scope(inner_scope_graph, scope)
67    }
68
69    type NewEdgeResult;
70    fn cmpl_new_edge(
71        &self,
72        inner_scope_graph: &InnerScopeGraph<LABEL, DATA>,
73        src: Scope,
74        lbl: LABEL,
75        dst: Scope,
76    ) -> Self::NewEdgeResult;
77
78    // type GetDataResult;
79    // fn get_data(&mut self, inner_scope_graph: &InnerScopeGraph<LABEL, DATA>, scope: Scope) -> Self::GetDataResult;
80
81    type GetEdgesResult<'rslv>
82    where
83        Self: 'rslv,
84        LABEL: 'rslv,
85        DATA: 'rslv;
86    fn cmpl_get_edges<'rslv>(
87        &'rslv self,
88        inner_scope_graph: &'rslv InnerScopeGraph<LABEL, DATA>,
89        src: Scope,
90        lbl: LABEL,
91    ) -> Self::GetEdgesResult<'rslv>
92    where
93        LABEL: 'rslv,
94        DATA: 'rslv;
95}
96
97// TODO: Asynchronous Completeness can be a wrapper around the ExplicitClose impl
98
99// TODO: Residual-query-based Completeness requires access to query resolution