Skip to content

Commit e9e5166

Browse files
committed
redefine Tree::Children as a GAT
1 parent 6461392 commit e9e5166

File tree

5 files changed

+61
-64
lines changed

5 files changed

+61
-64
lines changed

benches/diff.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,19 @@ struct TreeNode {
1010
children: Vec<Self>,
1111
}
1212

13-
impl<'n> Node<'n> for TreeNode {
13+
impl Node for TreeNode {
1414
type Kind = ();
15-
fn kind(&'n self) -> Self::Kind {}
15+
fn kind(&self) -> Self::Kind {}
1616

1717
type Weight = u32;
18-
fn weight(&'n self) -> Self::Weight {
18+
fn weight(&self) -> Self::Weight {
1919
self.weight.into()
2020
}
2121
}
2222

23-
impl<'t> Tree<'t> for TreeNode {
24-
type Children = &'t [Self];
25-
fn children(&'t self) -> Self::Children {
23+
impl Tree for TreeNode {
24+
type Children<'c> = &'c [Self];
25+
fn children(&self) -> Self::Children<'_> {
2626
&self.children
2727
}
2828
}

src/diff.rs

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,9 @@ impl<T: Default + Eq + Add<Output = T>> Zero for WholeNumber<T> {
1818
}
1919
}
2020

21-
fn levenshtein<'t, T, W>(a: &'t [T], b: &'t [T]) -> (Box<[Edit]>, W)
21+
fn levenshtein<'c, T>(a: &'c [T], b: &'c [T]) -> (Box<[Edit]>, T::Weight)
2222
where
23-
T: Tree<'t, Weight = W, Children = &'t [T]> + Cost<Output = W>,
24-
W: Default + Copy + Ord + Add<Output = W>,
23+
T: Tree<Children<'c> = &'c [T]> + Cost<Output = T::Weight>,
2524
{
2625
let mut edges = HashMap::new();
2726

@@ -89,11 +88,7 @@ where
8988
///
9089
/// The sequence of [Edit]s is understood to apply to the left-hand side so it becomes the
9190
/// right-hand side.
92-
pub fn diff<T, W>(a: &T, b: &T) -> (Box<[Edit]>, W)
93-
where
94-
T: for<'t> Tree<'t, Weight = W>,
95-
W: Default + Copy + Ord + Add<Output = W>,
96-
{
91+
pub fn diff<T: Tree>(a: &T, b: &T) -> (Box<[Edit]>, T::Weight) {
9792
levenshtein(&[memoize(a)], &[memoize(b)])
9893
}
9994

@@ -105,10 +100,10 @@ mod tests {
105100
use proptest::collection::size_range;
106101
use test_strategy::{proptest, Arbitrary};
107102

108-
#[derive(Debug, Default, Clone, Eq, PartialEq, Arbitrary)]
103+
#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Arbitrary)]
109104
struct Eq;
110105

111-
#[derive(Debug, Default, Clone, Arbitrary)]
106+
#[derive(Debug, Default, Copy, Clone, Arbitrary)]
112107
struct NotEq;
113108

114109
impl PartialEq for NotEq {

src/lib.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
//! Map(Vec<(String, Json)>),
2525
//! }
2626
//!
27-
//! impl<'n> Node<'n> for Json {
27+
//! impl Node for Json {
2828
//! type Kind = Discriminant<Json>;
2929
//! fn kind(&self) -> Self::Kind {
3030
//! discriminant(self)
@@ -36,9 +36,12 @@
3636
//! }
3737
//! }
3838
//!
39-
//! impl<'t> Tree<'t> for Json {
40-
//! type Children = Box<dyn Iterator<Item = &'t Self> + 't>;
41-
//! fn children(&'t self) -> Self::Children {
39+
//! impl Tree for Json {
40+
//! type Children<'c> = Box<dyn Iterator<Item = &'c Self> + 'c>
41+
//! where
42+
//! Self: 'c;
43+
//!
44+
//! fn children(&self) -> Self::Children<'_> {
4245
//! match self {
4346
//! Json::Array(a) => Box::new(a.iter()),
4447
//! Json::Map(m) => Box::new(m.iter().map(|(_, v)| v)),

src/memoize.rs

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,49 @@
11
use crate::{Cost, Node, Tree};
2-
use std::ops::Add;
32

43
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
5-
pub(crate) struct Memoized<'t, T: Tree<'t>> {
4+
pub(crate) struct Memoized<'t, T: 't + Tree> {
65
tree: &'t T,
76
cost: T::Weight,
87
children: Box<[Self]>,
98
}
109

11-
impl<'t, T: 't + Tree<'t>> Node<'t> for Memoized<'t, T> {
10+
impl<'t, T: 't + Tree> Node for Memoized<'t, T> {
1211
type Kind = T::Kind;
1312

1413
#[inline]
15-
fn kind(&'t self) -> Self::Kind {
14+
fn kind(&self) -> Self::Kind {
1615
T::kind(self.tree)
1716
}
1817

1918
type Weight = T::Weight;
2019

2120
#[inline]
22-
fn weight(&'t self) -> Self::Weight {
21+
fn weight(&self) -> Self::Weight {
2322
T::weight(self.tree)
2423
}
2524
}
2625

27-
impl<'t, T: 't + Tree<'t>> Tree<'t> for Memoized<'t, T> {
28-
type Children = &'t [Self];
26+
impl<'t, T: 't + Tree> Tree for Memoized<'t, T> {
27+
type Children<'c> = &'c [Self]
28+
where
29+
Self: 'c;
2930

3031
#[inline]
31-
fn children(&'t self) -> Self::Children {
32+
fn children(&self) -> Self::Children<'_> {
3233
&self.children
3334
}
3435
}
3536

36-
impl<'t, T: Tree<'t, Weight = W>, W: Copy + Default + Add<Output = W>> Cost for Memoized<'t, T> {
37-
type Output = W;
37+
impl<'t, T: 't + Tree> Cost for Memoized<'t, T> {
38+
type Output = T::Weight;
3839

3940
#[inline]
4041
fn cost(&self) -> Self::Output {
4142
self.cost
4243
}
4344
}
4445

45-
pub(crate) fn memoize<T, W>(t: &T) -> Memoized<T>
46-
where
47-
T: for<'t> Tree<'t, Weight = W>,
48-
W: Copy + Default + Add<Output = W>,
49-
{
46+
pub(crate) fn memoize<T: Tree>(t: &T) -> Memoized<T> {
5047
let children: Box<[_]> = t.children().into_iter().map(memoize).collect();
5148

5249
Memoized {
@@ -63,17 +60,17 @@ mod tests {
6360
use test_strategy::proptest;
6461

6562
#[proptest]
66-
fn kind_is_preserved(t: MockTree<()>) {
63+
fn kind_is_preserved(t: MockTree<u8>) {
6764
assert_eq!(memoize(&t).kind(), t.kind());
6865
}
6966

7067
#[proptest]
71-
fn weight_is_preserved(t: MockTree<()>) {
68+
fn weight_is_preserved(t: MockTree<u8>) {
7269
assert_eq!(memoize(&t).weight(), t.weight());
7370
}
7471

7572
#[proptest]
76-
fn cost_is_memoized(t: MockTree<()>) {
73+
fn cost_is_memoized(t: MockTree<u8>) {
7774
let u = memoize(&t);
7875
assert_eq!(u.cost, t.cost());
7976
assert_eq!(u.cost, u.cost());

src/tree.rs

Lines changed: 28 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
use std::ops::Add;
22

33
/// An abstraction for a generic tree node.
4-
pub trait Node<'n> {
4+
pub trait Node {
55
/// The type of this [Node]'s [kind][Node::kind].
66
///
77
/// Only [Node]s of the equal _kind_ can replace each other.
88
type Kind: PartialEq;
99

1010
/// Returns this [Node]'s _kind_.
11-
fn kind(&'n self) -> Self::Kind;
11+
fn kind(&self) -> Self::Kind;
1212

1313
/// The type of this [Node]'s [weight][Node::weight].
1414
///
@@ -18,16 +18,18 @@ pub trait Node<'n> {
1818
/// Returns the cost of inserting or deleting this [Node].
1919
///
2020
/// A [Node]'s weight should be independent of the weight of its children.
21-
fn weight(&'n self) -> Self::Weight;
21+
fn weight(&self) -> Self::Weight;
2222
}
2323

2424
/// An abstraction for a recursive tree.
25-
pub trait Tree<'t>: 't + Node<'t> {
25+
pub trait Tree: Node {
2626
/// A type that can iterate over this [Tree]'s [children][Tree::children].
27-
type Children: IntoIterator<Item = &'t Self>;
27+
type Children<'c>: 'c + IntoIterator<Item = &'c Self>
28+
where
29+
Self: 'c;
2830

2931
/// Returns this [Tree]'s immediate children.
30-
fn children(&'t self) -> Self::Children;
32+
fn children(&self) -> Self::Children<'_>;
3133
}
3234

3335
#[cfg(test)]
@@ -58,7 +60,10 @@ mod tests {
5860
}
5961
}
6062

61-
fn tree<K: 'static + PartialEq + Arbitrary>(size: Size) -> impl Strategy<Value = MockTree<K>> {
63+
fn tree<K>(size: Size) -> impl Strategy<Value = MockTree<K>>
64+
where
65+
K: 'static + Copy + PartialEq + Arbitrary,
66+
{
6267
let depth = size.depth as u32;
6368
let breadth = size.breadth as u32;
6469
let size = (breadth.pow(depth + 1) - 1) / (breadth - 1) / 2; // half the maximum number of nodes
@@ -71,13 +76,13 @@ mod tests {
7176
}
7277

7378
#[derive(Debug, Default, Clone, PartialEq, Eq, Hash, From)]
74-
pub(crate) struct MockTree<K: PartialEq> {
79+
pub(crate) struct MockTree<K: Copy + PartialEq> {
7580
kind: K,
7681
weight: u8,
7782
children: Vec<Self>,
7883
}
7984

80-
impl<K: 'static + PartialEq + Arbitrary> Arbitrary for MockTree<K> {
85+
impl<K: 'static + Copy + PartialEq + Arbitrary> Arbitrary for MockTree<K> {
8186
type Parameters = Size;
8287
type Strategy = BoxedStrategy<Self>;
8388

@@ -86,39 +91,36 @@ mod tests {
8691
}
8792
}
8893

89-
impl<'n, K: 'n + PartialEq> Node<'n> for MockTree<K> {
90-
type Kind = &'n K;
91-
fn kind(&'n self) -> Self::Kind {
92-
&self.kind
94+
impl<K: Copy + PartialEq> Node for MockTree<K> {
95+
type Kind = K;
96+
fn kind(&self) -> Self::Kind {
97+
self.kind
9398
}
9499

95100
type Weight = u64;
96-
fn weight(&'n self) -> Self::Weight {
101+
fn weight(&self) -> Self::Weight {
97102
self.weight.into()
98103
}
99104
}
100105

101-
impl<'t, K: 't + PartialEq> Tree<'t> for MockTree<K> {
102-
type Children = &'t [Self];
103-
fn children(&'t self) -> Self::Children {
106+
impl<K: Copy + PartialEq> Tree for MockTree<K> {
107+
type Children<'c> = &'c [Self]
108+
where
109+
Self: 'c;
110+
111+
fn children(&self) -> Self::Children<'_> {
104112
&self.children
105113
}
106114
}
107115

108-
impl<K: PartialEq> Fold for MockTree<K>
109-
where
110-
Self: for<'t> Tree<'t, Children = &'t [Self]>,
111-
{
116+
impl<K: Copy + PartialEq> Fold for MockTree<K> {
112117
fn fold<R, Fn: FnMut(R, &Self) -> R>(&self, init: R, f: &mut Fn) -> R {
113118
self.children().fold(f(init, self), f)
114119
}
115120
}
116121

117-
impl<K: PartialEq, W: Default + Copy + Add<Output = W>> Cost for MockTree<K>
118-
where
119-
Self: for<'t> Tree<'t, Weight = W, Children = &'t [Self]>,
120-
{
121-
type Output = W;
122+
impl<K: Copy + PartialEq> Cost for MockTree<K> {
123+
type Output = <Self as Node>::Weight;
122124

123125
#[inline]
124126
fn cost(&self) -> Self::Output {

0 commit comments

Comments
 (0)