use vecs more

This commit is contained in:
Folkert 2022-04-24 00:16:26 +02:00
parent a556cccb1e
commit f7010336bb
No known key found for this signature in database
GPG key ID: 1F17F6FFD112B97C

View file

@ -1902,15 +1902,25 @@ fn to_pending_value_def<'a>(
/// Make aliases recursive /// Make aliases recursive
fn correct_mutual_recursive_type_alias<'a>( fn correct_mutual_recursive_type_alias<'a>(
env: &mut Env<'a>, env: &mut Env<'a>,
mut original_aliases: SendMap<Symbol, Alias>, original_aliases: SendMap<Symbol, Alias>,
var_store: &mut VarStore, var_store: &mut VarStore,
) -> ImMap<Symbol, Alias> { ) -> ImMap<Symbol, Alias> {
let symbols_introduced: Vec<Symbol> = original_aliases.keys().copied().collect(); let capacity = original_aliases.len();
let mut matrix = ReferenceMatrix::new(capacity);
let mut matrix = ReferenceMatrix::new(original_aliases.len()); let (symbols_introduced, mut aliases): (Vec<_>, Vec<_>) = original_aliases
.into_iter()
.map(|(k, v)| (k, Some(v)))
.unzip();
for (index, (_, alias)) in original_aliases.iter().enumerate() { for (index, alias) in aliases.iter().enumerate() {
for referenced in alias.typ.symbols() { let it = alias
.as_ref()
.map(|a| a.typ.symbols().into_iter())
.into_iter()
.flatten();
for referenced in it {
match symbols_introduced.iter().position(|k| referenced == *k) { match symbols_introduced.iter().position(|k| referenced == *k) {
None => { /* ignore */ } None => { /* ignore */ }
Some(ref_id) => matrix.set_row_col(index, ref_id, true), Some(ref_id) => matrix.set_row_col(index, ref_id, true),
@ -1918,26 +1928,23 @@ fn correct_mutual_recursive_type_alias<'a>(
} }
} }
let all_successors_with_self = |symbol: &Symbol| -> Vec<Symbol> {
match symbols_introduced.iter().position(|k| symbol == k) {
Some(index) => matrix
.references_for(index)
.map(|r| symbols_introduced[r])
.collect(),
None => vec![],
}
};
let cycles =
ven_graph::strongly_connected_components(&symbols_introduced, all_successors_with_self);
let mut solved_aliases = ImMap::default(); let mut solved_aliases = ImMap::default();
let group: Vec<_> = (0u32..capacity as u32).collect();
let cycles = matrix.strongly_connected_components(&group);
for cycle in cycles { for cycle in cycles {
debug_assert!(!cycle.is_empty()); debug_assert!(!cycle.is_empty());
let mut pending_aliases: ImMap<_, _> = cycle let mut pending_aliases: ImMap<_, _> = cycle
.iter() .iter()
.map(|&sym| (sym, original_aliases.remove(&sym).unwrap())) .map(|index| {
(
symbols_introduced[*index as usize],
aliases[*index as usize].take().unwrap(),
)
})
.collect(); .collect();
// Make sure we report only one error for the cycle, not an error for every // Make sure we report only one error for the cycle, not an error for every
@ -1952,7 +1959,9 @@ fn correct_mutual_recursive_type_alias<'a>(
// NB: ImMap::clone is O(1): https://docs.rs/im/latest/src/im/hash/map.rs.html#1527-1544 // NB: ImMap::clone is O(1): https://docs.rs/im/latest/src/im/hash/map.rs.html#1527-1544
let mut to_instantiate = solved_aliases.clone().union(pending_aliases.clone()); let mut to_instantiate = solved_aliases.clone().union(pending_aliases.clone());
for &rec in cycle.iter() { for index in cycle.iter() {
let rec = symbols_introduced[*index as usize];
let alias = pending_aliases.get_mut(&rec).unwrap(); let alias = pending_aliases.get_mut(&rec).unwrap();
// Don't try to instantiate the alias itself in its definition. // Don't try to instantiate the alias itself in its definition.
let original_alias_def = to_instantiate.remove(&rec).unwrap(); let original_alias_def = to_instantiate.remove(&rec).unwrap();
@ -1992,14 +2001,18 @@ fn correct_mutual_recursive_type_alias<'a>(
// The cycle we just instantiated and marked recursive may still be an illegal cycle, if // The cycle we just instantiated and marked recursive may still be an illegal cycle, if
// all the types in the cycle are narrow newtypes. We can't figure this out until now, // all the types in the cycle are narrow newtypes. We can't figure this out until now,
// because we need all the types to be deeply instantiated. // because we need all the types to be deeply instantiated.
let all_are_narrow = cycle.iter().all(|sym| { let all_are_narrow = cycle.iter().all(|index| {
let sym = &symbols_introduced[*index as usize];
let typ = &pending_aliases.get(sym).unwrap().typ; let typ = &pending_aliases.get(sym).unwrap().typ;
matches!(typ, Type::RecursiveTagUnion(..)) && typ.is_narrow() matches!(typ, Type::RecursiveTagUnion(..)) && typ.is_narrow()
}); });
if all_are_narrow { if all_are_narrow {
// This cycle is illegal! // This cycle is illegal!
let mut rest = cycle; let mut rest: Vec<Symbol> = cycle
.into_iter()
.map(|i| symbols_introduced[i as usize])
.collect();
let alias_name = rest.pop().unwrap(); let alias_name = rest.pop().unwrap();
let alias = pending_aliases.get_mut(&alias_name).unwrap(); let alias = pending_aliases.get_mut(&alias_name).unwrap();