Skip to content

Commit 9212b39

Browse files
committed
types: introduce helper type to hold token alongside slab
In the next couple commits we will replace the mutexes in the union-bound algorithm with GhostCells. Happily, we can reuse the existing GhostToken in types::Context as an access-control token. However, to do this we need to refactor a couple algorithms so that we can fish the token recursively through unify() and bind(), which naively would require the union-bound algorithm to know about our ContextInner type. To avoid this abstraction violation, we introduce the generic WithContextToken wrapper, so the union-bound algorithm can work with "a token and some arbitrary data" without knowing or understanding anything about the arbitrary data.
1 parent 7dce5f0 commit 9212b39

File tree

3 files changed

+35
-8
lines changed

3 files changed

+35
-8
lines changed

src/types/context.rs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use ghost_cell::GhostToken;
2222

2323
use crate::dag::{Dag, DagLike};
2424

25-
use super::{Bound, CompleteBound, Error, Final, Incomplete, Type, TypeInner};
25+
use super::{Bound, CompleteBound, Error, Final, Incomplete, Type, TypeInner, WithGhostToken};
2626

2727
// Copied from ghost_cell source. See
2828
// https://arhan.sh/blog/the-generativity-pattern-in-rust/
@@ -41,12 +41,11 @@ type InvariantLifetime<'brand> = PhantomData<fn(&'brand ()) -> &'brand ()>;
4141
/// please file an issue.
4242
#[derive(Clone)]
4343
pub struct Context<'brand> {
44-
inner: Arc<Mutex<ContextInner<'brand>>>,
44+
inner: Arc<Mutex<WithGhostToken<'brand, ContextInner<'brand>>>>,
4545
}
4646

4747
struct ContextInner<'brand> {
4848
slab: Vec<Bound<'brand>>,
49-
_token: GhostToken<'brand>,
5049
}
5150

5251
impl fmt::Debug for Context<'_> {
@@ -78,9 +77,9 @@ impl<'brand> Context<'brand> {
7877
/// Creates a new empty type inference context.
7978
pub fn new(token: GhostToken<'brand>) -> Self {
8079
Context {
81-
inner: Arc::new(Mutex::new(ContextInner {
82-
slab: vec![],
80+
inner: Arc::new(Mutex::new(WithGhostToken {
8381
_token: token,
82+
inner: ContextInner { slab: vec![] },
8483
})),
8584
}
8685
}
@@ -285,7 +284,7 @@ struct BindError<'brand> {
285284
/// This type is never exposed outside of this module and should only exist
286285
/// ephemerally within function calls into this module.
287286
struct LockedContext<'ctx, 'brand> {
288-
inner: MutexGuard<'ctx, ContextInner<'brand>>,
287+
inner: MutexGuard<'ctx, WithGhostToken<'brand, ContextInner<'brand>>>,
289288
}
290289

291290
impl<'brand> LockedContext<'_, 'brand> {

src/types/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@
7171
// or a sum or product of other types.
7272
//
7373

74-
use self::union_bound::{PointerLike, UbElement};
74+
use self::union_bound::{PointerLike, UbElement, WithGhostToken};
7575
use crate::dag::{DagLike, NoSharing};
7676
use crate::Tmr;
7777

src/types/union_bound.rs

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,9 @@
3030
//!
3131
3232
use std::sync::{Arc, Mutex};
33-
use std::{cmp, fmt, mem};
33+
use std::{cmp, fmt, mem, ops};
34+
35+
use ghost_cell::GhostToken;
3436

3537
/// Trait describing objects that can be stored and manipulated by the union-bound
3638
/// algorithm.
@@ -56,6 +58,32 @@ impl<T> PointerLike for Arc<T> {
5658
}
5759
}
5860

61+
/// Container which associates a ghost token with some arbitrary other data.
62+
///
63+
/// This allows the union-bound algorithm to work with a token (which is used
64+
/// by the algorithm) while passing data (which is -not- used by the algorithm)
65+
/// everywhere that needs it, without offending the borrow checker or forcing
66+
/// callers to manually destructure their types to separate out tokens.
67+
///
68+
/// If Rust had view types, this structure wouldn't be necessary.
69+
pub struct WithGhostToken<'brand, T> {
70+
pub _token: GhostToken<'brand>,
71+
pub inner: T,
72+
}
73+
74+
impl<'brand, T> ops::Deref for WithGhostToken<'brand, T> {
75+
type Target = T;
76+
fn deref(&self) -> &T {
77+
&self.inner
78+
}
79+
}
80+
81+
impl<'brand, T> ops::DerefMut for WithGhostToken<'brand, T> {
82+
fn deref_mut(&mut self) -> &mut T {
83+
&mut self.inner
84+
}
85+
}
86+
5987
pub struct UbElement<T> {
6088
inner: Arc<Mutex<UbInner<T>>>,
6189
}

0 commit comments

Comments
 (0)