Merge pull request #4398 from roc-lang/emplace-type-variables

Leave variables behind when converting `Type`s to variables
This commit is contained in:
Ayaz 2022-10-26 12:41:55 -05:00 committed by GitHub
commit 316ae7d30b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 158 additions and 73 deletions

View file

@ -11,7 +11,7 @@ use crate::specialize::{
use bumpalo::Bump;
use roc_can::abilities::{AbilitiesStore, MemberSpecializationInfo};
use roc_can::constraint::Constraint::{self, *};
use roc_can::constraint::{Constraints, Cycle, LetConstraint, OpportunisticResolve};
use roc_can::constraint::{Constraints, Cycle, LetConstraint, OpportunisticResolve, TypeOrVar};
use roc_can::expected::{Expected, PExpected};
use roc_can::expr::PendingDerives;
use roc_can::module::ExposedByModule;
@ -911,7 +911,7 @@ fn solve(
);
let expectation = &constraints.expectations[expectation_index.index()];
let expected = type_to_var(
let expected = type_cell_to_var(
subs,
rank,
problems,
@ -961,7 +961,7 @@ fn solve(
*region,
category.clone(),
actual_type,
expectation.clone().replace(expected_type),
expectation.replace_ref(expected_type),
);
problems.push(problem);
@ -1023,7 +1023,7 @@ fn solve(
let actual = deep_copy_var_in(subs, rank, pools, var, arena);
let expectation = &constraints.expectations[expectation_index.index()];
let expected = type_to_var(
let expected = type_cell_to_var(
subs,
rank,
problems,
@ -1078,7 +1078,7 @@ fn solve(
*region,
Category::Lookup(*symbol),
actual_type,
expectation.clone().replace(expected_type),
expectation.replace_ref(expected_type),
);
problems.push(problem);
@ -1130,7 +1130,7 @@ fn solve(
);
let expectation = &constraints.pattern_expectations[expectation_index.index()];
let expected = type_to_var(
let expected = type_cell_to_var(
subs,
rank,
problems,
@ -1185,7 +1185,7 @@ fn solve(
*region,
category.clone(),
actual_type,
expectation.clone().replace(expected_type),
expectation.replace_ref(expected_type),
);
problems.push(problem);
@ -1323,11 +1323,11 @@ fn solve(
region,
} = includes_tag;
let typ = &constraints.types[type_index.index()];
let tys = &constraints.types[types.indices()];
let typ_cell = &constraints.types[type_index.index()];
let tys_cells = &constraints.types[types.indices()];
let pattern_category = &constraints.pattern_categories[pattern_category.index()];
let actual = type_to_var(
let actual = type_cell_to_var(
subs,
rank,
problems,
@ -1335,12 +1335,28 @@ fn solve(
obligation_cache,
pools,
aliases,
typ,
);
let tag_ty = Type::TagUnion(
vec![(tag_name.clone(), tys.to_vec())],
TypeExtension::Closed,
typ_cell,
);
let tys = {
let mut tys = Vec::with_capacity(tys_cells.len());
for cell in tys_cells {
let actual = type_cell_to_var(
subs,
rank,
problems,
abilities_store,
obligation_cache,
pools,
aliases,
cell,
);
tys.push(Type::Variable(actual));
}
tys
};
let tag_ty = Type::TagUnion(vec![(tag_name.clone(), tys)], TypeExtension::Closed);
let includes = type_to_var(
subs,
rank,
@ -1463,7 +1479,7 @@ fn solve(
real_var,
);
let branches_var = type_to_var(
let branches_var = type_cell_to_var(
subs,
rank,
problems,
@ -2033,8 +2049,8 @@ impl LocalDefVarsVec<(Symbol, Loc<Variable>)> {
let mut local_def_vars = Self::with_length(types_slice.len());
for (&(symbol, region), typ) in (loc_symbols_slice.iter()).zip(types_slice) {
let var = type_to_var(
for (&(symbol, region), typ_cell) in (loc_symbols_slice.iter()).zip(types_slice) {
let var = type_cell_to_var(
subs,
rank,
problems,
@ -2042,7 +2058,7 @@ impl LocalDefVarsVec<(Symbol, Loc<Variable>)> {
obligation_cache,
pools,
aliases,
typ,
typ_cell,
);
local_def_vars.push((symbol, Loc { value: var, region }));
@ -2052,7 +2068,7 @@ impl LocalDefVarsVec<(Symbol, Loc<Variable>)> {
}
}
use std::cell::RefCell;
use std::cell::{Cell, RefCell};
use std::ops::ControlFlow;
std::thread_local! {
/// Scratchpad arena so we don't need to allocate a new one all the time
@ -2078,13 +2094,13 @@ fn either_type_index_to_var(
abilities_store: &mut AbilitiesStore,
obligation_cache: &mut ObligationCache,
aliases: &mut Aliases,
either_type_index: roc_collections::soa::EitherIndex<Type, Variable>,
either_type_index: TypeOrVar,
) -> Variable {
match either_type_index.split() {
Ok(type_index) => {
let typ = &constraints.types[type_index.index()];
let typ_cell = &constraints.types[type_index.index()];
type_to_var(
type_cell_to_var(
subs,
rank,
problems,
@ -2092,7 +2108,7 @@ fn either_type_index_to_var(
obligation_cache,
pools,
aliases,
typ,
typ_cell,
)
}
Err(var_index) => {
@ -2102,6 +2118,32 @@ fn either_type_index_to_var(
}
}
/// Converts a type in a cell to a variable, leaving the converted variable behind for re-use.
fn type_cell_to_var(
subs: &mut Subs,
rank: Rank,
problems: &mut Vec<TypeError>,
abilities_store: &mut AbilitiesStore,
obligation_cache: &mut ObligationCache,
pools: &mut Pools,
aliases: &mut Aliases,
typ_cell: &Cell<Type>,
) -> Variable {
let typ = typ_cell.replace(Type::EmptyTagUnion);
let var = type_to_var(
subs,
rank,
problems,
abilities_store,
obligation_cache,
pools,
aliases,
&typ,
);
typ_cell.replace(Type::Variable(var));
var
}
pub(crate) fn type_to_var(
subs: &mut Subs,
rank: Rank,