mirror of
https://github.com/martinvonz/jj.git
synced 2025-01-05 20:55:05 +00:00
revset: store RevWalk factory function in RevWalkRevset
The returned iterator is boxed by caller due to the limitation of the type system. There's a workaround, but it's super ugly. https://users.rust-lang.org/t/hrtb-on-multiple-generics/34255/3
This commit is contained in:
parent
575d3dc7bf
commit
a9a7de4a5e
1 changed files with 61 additions and 26 deletions
|
@ -219,28 +219,47 @@ impl ToPredicateFn for EagerRevset {
|
|||
}
|
||||
}
|
||||
|
||||
struct RevWalkRevset<T> {
|
||||
walk: T,
|
||||
struct RevWalkRevset<F> {
|
||||
walk: F,
|
||||
}
|
||||
|
||||
impl<T> fmt::Debug for RevWalkRevset<T> {
|
||||
impl<F> RevWalkRevset<F>
|
||||
where
|
||||
// Returns trait object because we can't express the following constraints
|
||||
// without using named lifetime and type parameter:
|
||||
//
|
||||
// for<'index>
|
||||
// F: Fn(CompositeIndex<'index>) -> _,
|
||||
// F::Output: Iterator<Item = IndexEntry<'index>> + 'index
|
||||
//
|
||||
// There's a workaround, but it doesn't help infer closure types.
|
||||
// https://github.com/rust-lang/rust/issues/47815
|
||||
// https://users.rust-lang.org/t/hrtb-on-multiple-generics/34255
|
||||
F: Fn(CompositeIndex<'_>) -> Box<dyn Iterator<Item = IndexEntry<'_>> + '_>,
|
||||
{
|
||||
fn new(walk: F) -> Self {
|
||||
RevWalkRevset { walk }
|
||||
}
|
||||
}
|
||||
|
||||
impl<F> fmt::Debug for RevWalkRevset<F> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("RevWalkRevset").finish_non_exhaustive()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'index, T> InternalRevset<'index> for RevWalkRevset<T>
|
||||
impl<'index, F> InternalRevset<'index> for RevWalkRevset<F>
|
||||
where
|
||||
T: Iterator<Item = IndexEntry<'index>> + Clone,
|
||||
F: Fn(CompositeIndex<'_>) -> Box<dyn Iterator<Item = IndexEntry<'_>> + '_>,
|
||||
{
|
||||
fn iter<'a>(
|
||||
&'a self,
|
||||
_index: CompositeIndex<'index>,
|
||||
index: CompositeIndex<'index>,
|
||||
) -> Box<dyn Iterator<Item = IndexEntry<'index>> + 'a>
|
||||
where
|
||||
'index: 'a,
|
||||
{
|
||||
Box::new(self.walk.clone())
|
||||
(self.walk)(index)
|
||||
}
|
||||
|
||||
fn into_predicate<'a>(self: Box<Self>) -> Box<dyn ToPredicateFn + 'a>
|
||||
|
@ -251,16 +270,15 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<'index, T> ToPredicateFn for RevWalkRevset<T>
|
||||
impl<F> ToPredicateFn for RevWalkRevset<F>
|
||||
where
|
||||
T: Iterator<Item = IndexEntry<'index>> + Clone,
|
||||
F: Fn(CompositeIndex<'_>) -> Box<dyn Iterator<Item = IndexEntry<'_>> + '_>,
|
||||
{
|
||||
// TODO: remove 'index from RevWalkRevset<'index, F>
|
||||
fn to_predicate_fn<'a, 'index2: 'a>(
|
||||
fn to_predicate_fn<'a, 'index: 'a>(
|
||||
&'a self,
|
||||
_index: CompositeIndex<'index2>,
|
||||
index: CompositeIndex<'index>,
|
||||
) -> Box<dyn FnMut(&IndexEntry<'_>) -> bool + 'a> {
|
||||
predicate_fn_from_entries(self.walk.clone())
|
||||
predicate_fn_from_entries(self.iter(index))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -627,12 +645,19 @@ impl<'index> EvaluationContext<'index> {
|
|||
.iter(index)
|
||||
.map(|entry| entry.position())
|
||||
.collect_vec();
|
||||
let walk = self.index.walk_revs(&head_positions, &[]);
|
||||
if generation == &GENERATION_RANGE_FULL {
|
||||
Ok(Box::new(RevWalkRevset { walk }))
|
||||
Ok(Box::new(RevWalkRevset::new(move |index| {
|
||||
Box::new(index.walk_revs(&head_positions, &[]))
|
||||
})))
|
||||
} else {
|
||||
let walk = walk.filter_by_generation(to_u32_generation_range(generation)?);
|
||||
Ok(Box::new(RevWalkRevset { walk }))
|
||||
let generation = to_u32_generation_range(generation)?;
|
||||
Ok(Box::new(RevWalkRevset::new(move |index| {
|
||||
Box::new(
|
||||
index
|
||||
.walk_revs(&head_positions, &[])
|
||||
.filter_by_generation(generation.clone()),
|
||||
)
|
||||
})))
|
||||
}
|
||||
}
|
||||
ResolvedExpression::Range {
|
||||
|
@ -650,12 +675,19 @@ impl<'index> EvaluationContext<'index> {
|
|||
.iter(index)
|
||||
.map(|entry| entry.position())
|
||||
.collect_vec();
|
||||
let walk = self.index.walk_revs(&head_positions, &root_positions);
|
||||
if generation == &GENERATION_RANGE_FULL {
|
||||
Ok(Box::new(RevWalkRevset { walk }))
|
||||
Ok(Box::new(RevWalkRevset::new(move |index| {
|
||||
Box::new(index.walk_revs(&head_positions, &root_positions))
|
||||
})))
|
||||
} else {
|
||||
let walk = walk.filter_by_generation(to_u32_generation_range(generation)?);
|
||||
Ok(Box::new(RevWalkRevset { walk }))
|
||||
let generation = to_u32_generation_range(generation)?;
|
||||
Ok(Box::new(RevWalkRevset::new(move |index| {
|
||||
Box::new(
|
||||
index
|
||||
.walk_revs(&head_positions, &root_positions)
|
||||
.filter_by_generation(generation.clone()),
|
||||
)
|
||||
})))
|
||||
}
|
||||
}
|
||||
ResolvedExpression::DagRange {
|
||||
|
@ -674,11 +706,14 @@ impl<'index> EvaluationContext<'index> {
|
|||
.map(|entry| entry.position())
|
||||
.collect_vec();
|
||||
if generation_from_roots == &(1..2) {
|
||||
let walk = index
|
||||
.walk_revs(&head_positions, &[])
|
||||
.take_until_roots(&root_positions);
|
||||
let root_positions_set: HashSet<_> = root_positions.into_iter().collect();
|
||||
let candidates = Box::new(RevWalkRevset { walk });
|
||||
let root_positions_set: HashSet<_> = root_positions.iter().copied().collect();
|
||||
let candidates = Box::new(RevWalkRevset::new(move |index| {
|
||||
Box::new(
|
||||
index
|
||||
.walk_revs(&head_positions, &[])
|
||||
.take_until_roots(&root_positions),
|
||||
)
|
||||
}));
|
||||
let predicate = PurePredicateFn(move |entry: &IndexEntry| {
|
||||
entry
|
||||
.parent_positions()
|
||||
|
|
Loading…
Reference in a new issue