diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/access/screen.rs | 28 |
1 files changed, 19 insertions, 9 deletions
diff --git a/src/access/screen.rs b/src/access/screen.rs index 68e4db7..3a516e3 100644 --- a/src/access/screen.rs +++ b/src/access/screen.rs @@ -375,7 +375,7 @@ pub(crate) fn apply( } // The changes of the document each accepted one, not applied yet, builds on. - let mut frontier: HashMap<ChangeHash, Vec<ChangeHash>> = HashMap::new(); + let mut frontier: HashMap<ChangeHash, std::rc::Rc<[ChangeHash]>> = HashMap::new(); // Refused in this batch, each with the change that broke a rule. let mut refused: HashMap<ChangeHash, ChangeHash> = HashMap::new(); let mut unsigned: HashSet<ChangeHash> = HashSet::new(); @@ -458,16 +458,26 @@ pub(crate) fn apply( unapplied.clear(); signed = None; } - let mut seen_at: BTreeSet<ChangeHash> = BTreeSet::new(); - for dep in change.deps() { - match frontier.get(dep) { - Some(heads) => seen_at.extend(heads.iter().copied()), - None => { - seen_at.insert(*dep); + // Shared with what it builds on, if it builds on one alone (most do): the same + // heads, not a copy each. + let seen_at: std::rc::Rc<[ChangeHash]> = match change.deps() { + [dep] => frontier + .get(dep) + .cloned() + .unwrap_or_else(|| std::rc::Rc::from([*dep])), + deps => { + let mut seen_at: BTreeSet<ChangeHash> = BTreeSet::new(); + for dep in deps { + match frontier.get(dep) { + Some(heads) => seen_at.extend(heads.iter().copied()), + None => { + seen_at.insert(*dep); + } + } } + seen_at.into_iter().collect() } - } - let seen_at: Vec<ChangeHash> = seen_at.into_iter().collect(); + }; let root = change.deps().is_empty(); let judged = if judging || root { rules::judge_reading( |
