mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-03 16:44:33 +00:00
Don't drop defs that would be shadowed
This commit is contained in:
parent
e38ae00c65
commit
daa87093ca
3 changed files with 2 additions and 162 deletions
|
@ -3,7 +3,6 @@
|
||||||
#![allow(clippy::large_enum_variant)]
|
#![allow(clippy::large_enum_variant)]
|
||||||
|
|
||||||
pub mod all;
|
pub mod all;
|
||||||
pub mod linked_list_extra;
|
|
||||||
mod reference_matrix;
|
mod reference_matrix;
|
||||||
mod small_string_interner;
|
mod small_string_interner;
|
||||||
pub mod soa;
|
pub mod soa;
|
||||||
|
|
|
@ -1,142 +0,0 @@
|
||||||
// This is just to get the nightly drain_iter API for LinkedList.
|
|
||||||
// TODO delete this module and use normal drain_iter once it has stabilized!
|
|
||||||
|
|
||||||
use std::{collections::LinkedList, fmt, marker::PhantomData, ptr::NonNull};
|
|
||||||
|
|
||||||
/// The internal representation of std::collections::linked_list::LinkedList
|
|
||||||
struct InternalLinkedList<T> {
|
|
||||||
head: Option<NonNull<Node<T>>>,
|
|
||||||
tail: Option<NonNull<Node<T>>>,
|
|
||||||
len: usize,
|
|
||||||
marker: PhantomData<Box<Node<T>>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> InternalLinkedList<T> {
|
|
||||||
unsafe fn unlink_node(&mut self, mut node: NonNull<Node<T>>) {
|
|
||||||
let node = node.as_mut(); // this one is ours now, we can create an &mut.
|
|
||||||
|
|
||||||
// Not creating new mutable (unique!) references overlapping `element`.
|
|
||||||
match node.prev {
|
|
||||||
Some(prev) => (*prev.as_ptr()).next = node.next,
|
|
||||||
// this node is the head node
|
|
||||||
None => self.head = node.next,
|
|
||||||
};
|
|
||||||
|
|
||||||
match node.next {
|
|
||||||
Some(next) => (*next.as_ptr()).prev = node.prev,
|
|
||||||
// this node is the tail node
|
|
||||||
None => self.tail = node.prev,
|
|
||||||
};
|
|
||||||
|
|
||||||
self.len -= 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Node<T> {
|
|
||||||
next: Option<NonNull<Node<T>>>,
|
|
||||||
prev: Option<NonNull<Node<T>>>,
|
|
||||||
element: T,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Implementation of the nightly DrainFilter API, Apache2 licensed:
|
|
||||||
// https://doc.rust-lang.org/std/collections/struct.LinkedList.html#method.drain_filter
|
|
||||||
// TODO replace this with normal drain_iter once it's stabilized.
|
|
||||||
pub fn drain_filter<'a, T, F>(list: &'a mut LinkedList<T>, filter: F) -> DrainFilter<'a, T, F>
|
|
||||||
where
|
|
||||||
F: FnMut(&mut T) -> bool,
|
|
||||||
{
|
|
||||||
// This is the internal representation of std::collections::linked_list::LinkedList;
|
|
||||||
let list = unsafe {
|
|
||||||
std::mem::transmute::<&'a mut LinkedList<T>, &'a mut InternalLinkedList<T>>(list)
|
|
||||||
};
|
|
||||||
|
|
||||||
// avoid borrow issues.
|
|
||||||
let it = list.head;
|
|
||||||
let old_len = list.len;
|
|
||||||
|
|
||||||
DrainFilter {
|
|
||||||
list,
|
|
||||||
it,
|
|
||||||
pred: filter,
|
|
||||||
idx: 0,
|
|
||||||
old_len,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct DrainFilter<'a, T: 'a, F: 'a>
|
|
||||||
where
|
|
||||||
F: FnMut(&mut T) -> bool,
|
|
||||||
{
|
|
||||||
list: &'a mut InternalLinkedList<T>,
|
|
||||||
it: Option<NonNull<Node<T>>>,
|
|
||||||
pred: F,
|
|
||||||
idx: usize,
|
|
||||||
old_len: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T, F> Iterator for DrainFilter<'_, T, F>
|
|
||||||
where
|
|
||||||
F: FnMut(&mut T) -> bool,
|
|
||||||
{
|
|
||||||
type Item = T;
|
|
||||||
|
|
||||||
fn next(&mut self) -> Option<T> {
|
|
||||||
while let Some(mut node) = self.it {
|
|
||||||
unsafe {
|
|
||||||
self.it = node.as_ref().next;
|
|
||||||
self.idx += 1;
|
|
||||||
|
|
||||||
if (self.pred)(&mut node.as_mut().element) {
|
|
||||||
// `unlink_node` is okay with aliasing `element` references.
|
|
||||||
self.list.unlink_node(node);
|
|
||||||
return Some(Box::from_raw(node.as_ptr()).element);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
|
||||||
(0, Some(self.old_len - self.idx))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T, F> Drop for DrainFilter<'_, T, F>
|
|
||||||
where
|
|
||||||
F: FnMut(&mut T) -> bool,
|
|
||||||
{
|
|
||||||
fn drop(&mut self) {
|
|
||||||
struct DropGuard<'r, 'a, T, F>(&'r mut DrainFilter<'a, T, F>)
|
|
||||||
where
|
|
||||||
F: FnMut(&mut T) -> bool;
|
|
||||||
|
|
||||||
impl<'r, 'a, T, F> Drop for DropGuard<'r, 'a, T, F>
|
|
||||||
where
|
|
||||||
F: FnMut(&mut T) -> bool,
|
|
||||||
{
|
|
||||||
fn drop(&mut self) {
|
|
||||||
self.0.for_each(drop);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
while let Some(item) = self.next() {
|
|
||||||
let guard = DropGuard(self);
|
|
||||||
drop(item);
|
|
||||||
std::mem::forget(guard);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: fmt::Debug, F> fmt::Debug for DrainFilter<'_, T, F>
|
|
||||||
where
|
|
||||||
F: FnMut(&mut T) -> bool,
|
|
||||||
{
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
// This is the internal representation of std::collections::linked_list::LinkedList;
|
|
||||||
let list =
|
|
||||||
unsafe { std::mem::transmute::<&InternalLinkedList<T>, &LinkedList<T>>(&*self.list) };
|
|
||||||
|
|
||||||
f.debug_tuple("DrainFilter").field(list).finish()
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -2,7 +2,6 @@ use crate::cli_gen::gen_and_eval_llvm;
|
||||||
use crate::colors::{BLUE, END_COL, GREEN, PINK};
|
use crate::colors::{BLUE, END_COL, GREEN, PINK};
|
||||||
use bumpalo::Bump;
|
use bumpalo::Bump;
|
||||||
use const_format::concatcp;
|
use const_format::concatcp;
|
||||||
use roc_collections::linked_list_extra::drain_filter;
|
|
||||||
use roc_collections::MutSet;
|
use roc_collections::MutSet;
|
||||||
use roc_mono::ir::OptLevel;
|
use roc_mono::ir::OptLevel;
|
||||||
use roc_parse::ast::{Expr, Pattern, TypeDef, ValueDef};
|
use roc_parse::ast::{Expr, Pattern, TypeDef, ValueDef};
|
||||||
|
@ -16,7 +15,6 @@ use rustyline::highlight::{Highlighter, PromptInfo};
|
||||||
use rustyline::validate::{self, ValidationContext, ValidationResult, Validator};
|
use rustyline::validate::{self, ValidationContext, ValidationResult, Validator};
|
||||||
use rustyline_derive::{Completer, Helper, Hinter};
|
use rustyline_derive::{Completer, Helper, Hinter};
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::collections::LinkedList;
|
|
||||||
use target_lexicon::Triple;
|
use target_lexicon::Triple;
|
||||||
|
|
||||||
pub const PROMPT: &str = concatcp!("\n", BLUE, "»", END_COL, " ");
|
pub const PROMPT: &str = concatcp!("\n", BLUE, "»", END_COL, " ");
|
||||||
|
@ -58,7 +56,7 @@ struct PastDef {
|
||||||
#[derive(Completer, Helper, Hinter)]
|
#[derive(Completer, Helper, Hinter)]
|
||||||
pub struct ReplState {
|
pub struct ReplState {
|
||||||
validator: InputValidator,
|
validator: InputValidator,
|
||||||
past_defs: LinkedList<PastDef>,
|
past_defs: Vec<PastDef>,
|
||||||
past_def_idents: MutSet<String>,
|
past_def_idents: MutSet<String>,
|
||||||
last_auto_ident: u64,
|
last_auto_ident: u64,
|
||||||
}
|
}
|
||||||
|
@ -235,22 +233,7 @@ impl ReplState {
|
||||||
|
|
||||||
existing_idents.insert(ident.clone());
|
existing_idents.insert(ident.clone());
|
||||||
|
|
||||||
// Override any defs that would be shadowed
|
self.past_defs.push(PastDef { ident, src });
|
||||||
if !self.past_defs.is_empty() {
|
|
||||||
drain_filter(&mut self.past_defs, |PastDef { ident, .. }| {
|
|
||||||
if existing_idents.contains(ident) {
|
|
||||||
// We already have a newer def for this ident, so drop the old one.
|
|
||||||
false
|
|
||||||
} else {
|
|
||||||
// We've never seen this def, so record it!
|
|
||||||
existing_idents.insert(ident.clone());
|
|
||||||
|
|
||||||
true
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
self.past_defs.push_front(PastDef { ident, src });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Wrap the given expresssion in the appropriate past defs
|
/// Wrap the given expresssion in the appropriate past defs
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue