mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-28 14:24:45 +00:00
implement
This commit is contained in:
parent
ad12e1e509
commit
efab1ef2ca
8 changed files with 271 additions and 160 deletions
|
@ -15,7 +15,7 @@ use roc_module::symbol::{IdentIds, ModuleId, Symbol};
|
||||||
use roc_problem::can::RuntimeError;
|
use roc_problem::can::RuntimeError;
|
||||||
use roc_region::all::{Located, Region};
|
use roc_region::all::{Located, Region};
|
||||||
use roc_types::solved_types::SolvedType;
|
use roc_types::solved_types::SolvedType;
|
||||||
use roc_types::subs::{Content, FlatType, Subs, Variable};
|
use roc_types::subs::{Content, FlatType, Subs, SubsSlice, Variable};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use ven_pretty::{BoxAllocator, DocAllocator, DocBuilder};
|
use ven_pretty::{BoxAllocator, DocAllocator, DocBuilder};
|
||||||
|
|
||||||
|
@ -3039,11 +3039,11 @@ pub fn with_hole<'a>(
|
||||||
|
|
||||||
if let Content::Structure(FlatType::Func(arg_vars, _, ret_var)) = content {
|
if let Content::Structure(FlatType::Func(arg_vars, _, ret_var)) = content {
|
||||||
let ret_var = *ret_var;
|
let ret_var = *ret_var;
|
||||||
let arg_vars = arg_vars.clone();
|
let arg_vars = *arg_vars;
|
||||||
|
|
||||||
tag_union_to_function(
|
tag_union_to_function(
|
||||||
env,
|
env,
|
||||||
&arg_vars,
|
arg_vars,
|
||||||
ret_var,
|
ret_var,
|
||||||
tag_name,
|
tag_name,
|
||||||
closure_name,
|
closure_name,
|
||||||
|
@ -4346,7 +4346,7 @@ fn convert_tag_union<'a>(
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
fn tag_union_to_function<'a>(
|
fn tag_union_to_function<'a>(
|
||||||
env: &mut Env<'a, '_>,
|
env: &mut Env<'a, '_>,
|
||||||
argument_variables: &[Variable],
|
argument_variables: SubsSlice<Variable>,
|
||||||
return_variable: Variable,
|
return_variable: Variable,
|
||||||
tag_name: TagName,
|
tag_name: TagName,
|
||||||
proc_symbol: Symbol,
|
proc_symbol: Symbol,
|
||||||
|
@ -4360,15 +4360,17 @@ fn tag_union_to_function<'a>(
|
||||||
let mut loc_pattern_args = vec![];
|
let mut loc_pattern_args = vec![];
|
||||||
let mut loc_expr_args = vec![];
|
let mut loc_expr_args = vec![];
|
||||||
|
|
||||||
for arg_var in argument_variables {
|
for index in argument_variables {
|
||||||
|
let arg_var = env.subs[index];
|
||||||
|
|
||||||
let arg_symbol = env.unique_symbol();
|
let arg_symbol = env.unique_symbol();
|
||||||
|
|
||||||
let loc_pattern = Located::at_zero(roc_can::pattern::Pattern::Identifier(arg_symbol));
|
let loc_pattern = Located::at_zero(roc_can::pattern::Pattern::Identifier(arg_symbol));
|
||||||
|
|
||||||
let loc_expr = Located::at_zero(roc_can::expr::Expr::Var(arg_symbol));
|
let loc_expr = Located::at_zero(roc_can::expr::Expr::Var(arg_symbol));
|
||||||
|
|
||||||
loc_pattern_args.push((*arg_var, loc_pattern));
|
loc_pattern_args.push((arg_var, loc_pattern));
|
||||||
loc_expr_args.push((*arg_var, loc_expr));
|
loc_expr_args.push((arg_var, loc_expr));
|
||||||
}
|
}
|
||||||
|
|
||||||
let loc_body = Located::at_zero(roc_can::expr::Expr::Tag {
|
let loc_body = Located::at_zero(roc_can::expr::Expr::Tag {
|
||||||
|
|
|
@ -1193,7 +1193,8 @@ fn layout_from_flat_type<'a>(
|
||||||
Func(args, closure_var, ret_var) => {
|
Func(args, closure_var, ret_var) => {
|
||||||
let mut fn_args = Vec::with_capacity_in(args.len(), arena);
|
let mut fn_args = Vec::with_capacity_in(args.len(), arena);
|
||||||
|
|
||||||
for arg_var in args {
|
for index in args.into_iter() {
|
||||||
|
let arg_var = env.subs[index];
|
||||||
fn_args.push(Layout::from_var(env, arg_var)?);
|
fn_args.push(Layout::from_var(env, arg_var)?);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,9 @@ use roc_collections::all::{default_hasher, MutMap};
|
||||||
use roc_module::symbol::Symbol;
|
use roc_module::symbol::Symbol;
|
||||||
use roc_region::all::{Located, Region};
|
use roc_region::all::{Located, Region};
|
||||||
use roc_types::solved_types::Solved;
|
use roc_types::solved_types::Solved;
|
||||||
use roc_types::subs::{Content, Descriptor, FlatType, Mark, OptVariable, Rank, Subs, Variable};
|
use roc_types::subs::{
|
||||||
|
Content, Descriptor, FlatType, Mark, OptVariable, Rank, Subs, SubsSlice, Variable,
|
||||||
|
};
|
||||||
use roc_types::types::Type::{self, *};
|
use roc_types::types::Type::{self, *};
|
||||||
use roc_types::types::{Alias, Category, ErrorType, PatternCategory};
|
use roc_types::types::{Alias, Category, ErrorType, PatternCategory};
|
||||||
use roc_unify::unify::unify;
|
use roc_unify::unify::unify;
|
||||||
|
@ -656,13 +658,20 @@ fn type_to_variable(
|
||||||
EmptyTagUnion => Variable::EMPTY_TAG_UNION,
|
EmptyTagUnion => Variable::EMPTY_TAG_UNION,
|
||||||
|
|
||||||
// This case is important for the rank of boolean variables
|
// This case is important for the rank of boolean variables
|
||||||
Function(args, closure_type, ret_type) => {
|
Function(arg_vars, closure_type, ret_type) => {
|
||||||
let mut arg_vars = Vec::with_capacity(args.len());
|
let mut new_arg_vars = Vec::with_capacity(arg_vars.len());
|
||||||
|
|
||||||
for arg in args {
|
for arg in arg_vars {
|
||||||
arg_vars.push(type_to_variable(subs, rank, pools, cached, arg))
|
let var = type_to_variable(subs, rank, pools, cached, arg);
|
||||||
|
new_arg_vars.push(var);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let start = subs.variables.len() as u32;
|
||||||
|
let length = arg_vars.len() as u16;
|
||||||
|
let arg_vars = SubsSlice::new(start, length);
|
||||||
|
|
||||||
|
subs.variables.extend(new_arg_vars);
|
||||||
|
|
||||||
let ret_var = type_to_variable(subs, rank, pools, cached, ret_type);
|
let ret_var = type_to_variable(subs, rank, pools, cached, ret_type);
|
||||||
let closure_var = type_to_variable(subs, rank, pools, cached, closure_type);
|
let closure_var = type_to_variable(subs, rank, pools, cached, closure_type);
|
||||||
let content = Content::Structure(FlatType::Func(arg_vars, closure_var, ret_var));
|
let content = Content::Structure(FlatType::Func(arg_vars, closure_var, ret_var));
|
||||||
|
@ -1062,9 +1071,9 @@ fn adjust_rank_content(
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
for var in arg_vars {
|
for index in arg_vars.into_iter() {
|
||||||
rank =
|
let var = subs[index];
|
||||||
rank.max(adjust_rank(subs, young_mark, visit_mark, group_rank, *var));
|
rank = rank.max(adjust_rank(subs, young_mark, visit_mark, group_rank, var));
|
||||||
}
|
}
|
||||||
|
|
||||||
rank
|
rank
|
||||||
|
@ -1221,7 +1230,8 @@ fn instantiate_rigids_help(
|
||||||
instantiate_rigids_help(subs, max_rank, pools, ret_var);
|
instantiate_rigids_help(subs, max_rank, pools, ret_var);
|
||||||
instantiate_rigids_help(subs, max_rank, pools, closure_var);
|
instantiate_rigids_help(subs, max_rank, pools, closure_var);
|
||||||
|
|
||||||
for var in arg_vars.into_iter() {
|
for index in arg_vars.into_iter() {
|
||||||
|
let var = subs[index];
|
||||||
instantiate_rigids_help(subs, max_rank, pools, var);
|
instantiate_rigids_help(subs, max_rank, pools, var);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1356,10 +1366,20 @@ fn deep_copy_var_help(
|
||||||
Func(arg_vars, closure_var, ret_var) => {
|
Func(arg_vars, closure_var, ret_var) => {
|
||||||
let new_ret_var = deep_copy_var_help(subs, max_rank, pools, ret_var);
|
let new_ret_var = deep_copy_var_help(subs, max_rank, pools, ret_var);
|
||||||
let new_closure_var = deep_copy_var_help(subs, max_rank, pools, closure_var);
|
let new_closure_var = deep_copy_var_help(subs, max_rank, pools, closure_var);
|
||||||
let arg_vars = arg_vars
|
|
||||||
.into_iter()
|
let mut new_arg_vars = Vec::with_capacity(arg_vars.len());
|
||||||
.map(|var| deep_copy_var_help(subs, max_rank, pools, var))
|
|
||||||
.collect();
|
for index in arg_vars.into_iter() {
|
||||||
|
let var = subs[index];
|
||||||
|
let copy_var = deep_copy_var_help(subs, max_rank, pools, var);
|
||||||
|
new_arg_vars.push(copy_var);
|
||||||
|
}
|
||||||
|
|
||||||
|
let start = subs.variables.len() as u32;
|
||||||
|
let length = arg_vars.len() as u16;
|
||||||
|
let arg_vars = SubsSlice::new(start, length);
|
||||||
|
|
||||||
|
subs.variables.extend(new_arg_vars);
|
||||||
|
|
||||||
Func(arg_vars, new_closure_var, new_ret_var)
|
Func(arg_vars, new_closure_var, new_ret_var)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::subs::{Content, FlatType, Subs, Variable};
|
use crate::subs::{Content, FlatType, GetSubsSlice, Subs, Variable};
|
||||||
use crate::types::{name_type_var, RecordField};
|
use crate::types::{name_type_var, RecordField};
|
||||||
use roc_collections::all::{MutMap, MutSet};
|
use roc_collections::all::{MutMap, MutSet};
|
||||||
use roc_module::ident::{Lowercase, TagName};
|
use roc_module::ident::{Lowercase, TagName};
|
||||||
|
@ -146,8 +146,9 @@ fn find_names_needed(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Structure(Func(arg_vars, _closure_var, ret_var)) => {
|
Structure(Func(arg_vars, _closure_var, ret_var)) => {
|
||||||
for var in arg_vars {
|
for index in arg_vars.into_iter() {
|
||||||
find_names_needed(*var, subs, roots, root_appearances, names_taken);
|
let var = subs[index];
|
||||||
|
find_names_needed(var, subs, roots, root_appearances, names_taken);
|
||||||
}
|
}
|
||||||
|
|
||||||
find_names_needed(*ret_var, subs, roots, root_appearances, names_taken);
|
find_names_needed(*ret_var, subs, roots, root_appearances, names_taken);
|
||||||
|
@ -407,7 +408,9 @@ fn write_flat_type(env: &Env, flat_type: &FlatType, subs: &Subs, buf: &mut Strin
|
||||||
Apply(symbol, args) => write_apply(env, *symbol, args, subs, buf, parens),
|
Apply(symbol, args) => write_apply(env, *symbol, args, subs, buf, parens),
|
||||||
EmptyRecord => buf.push_str(EMPTY_RECORD),
|
EmptyRecord => buf.push_str(EMPTY_RECORD),
|
||||||
EmptyTagUnion => buf.push_str(EMPTY_TAG_UNION),
|
EmptyTagUnion => buf.push_str(EMPTY_TAG_UNION),
|
||||||
Func(args, _closure, ret) => write_fn(env, args, *ret, subs, buf, parens),
|
Func(args, _closure, ret) => {
|
||||||
|
write_fn(env, subs.get_subs_slice(*args), *ret, subs, buf, parens)
|
||||||
|
}
|
||||||
Record(fields, ext_var) => {
|
Record(fields, ext_var) => {
|
||||||
use crate::types::{gather_fields, RecordStructure};
|
use crate::types::{gather_fields, RecordStructure};
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::subs::{FlatType, Subs, VarId, VarStore, Variable};
|
use crate::subs::{FlatType, GetSubsSlice, Subs, VarId, VarStore, Variable};
|
||||||
use crate::types::{Problem, RecordField, Type};
|
use crate::types::{Problem, RecordField, Type};
|
||||||
use roc_collections::all::{ImMap, MutSet, SendMap};
|
use roc_collections::all::{ImMap, MutSet, SendMap};
|
||||||
use roc_module::ident::{Lowercase, TagName};
|
use roc_module::ident::{Lowercase, TagName};
|
||||||
|
@ -387,7 +387,7 @@ impl SolvedType {
|
||||||
Func(args, closure, ret) => {
|
Func(args, closure, ret) => {
|
||||||
let mut new_args = Vec::with_capacity(args.len());
|
let mut new_args = Vec::with_capacity(args.len());
|
||||||
|
|
||||||
for var in args {
|
for var in subs.get_subs_slice(*args) {
|
||||||
new_args.push(Self::from_var_help(subs, recursion_vars, *var));
|
new_args.push(Self::from_var_help(subs, recursion_vars, *var));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -53,19 +53,58 @@ struct ErrorTypeState {
|
||||||
#[derive(Default, Clone)]
|
#[derive(Default, Clone)]
|
||||||
pub struct Subs {
|
pub struct Subs {
|
||||||
utable: UnificationTable<InPlace<Variable>>,
|
utable: UnificationTable<InPlace<Variable>>,
|
||||||
variables: Vec<Variable>,
|
pub variables: Vec<Variable>,
|
||||||
tag_names: Vec<TagName>,
|
tag_names: Vec<TagName>,
|
||||||
field_names: Vec<Lowercase>,
|
field_names: Vec<Lowercase>,
|
||||||
record_fields: Vec<RecordField<()>>,
|
record_fields: Vec<RecordField<()>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(packed(2))]
|
|
||||||
pub struct SubsSlice<T> {
|
pub struct SubsSlice<T> {
|
||||||
start: u32,
|
start: u32,
|
||||||
length: u16,
|
length: u16,
|
||||||
_marker: std::marker::PhantomData<T>,
|
_marker: std::marker::PhantomData<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct SubsIndex<T> {
|
||||||
|
start: u32,
|
||||||
|
_marker: std::marker::PhantomData<T>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::ops::Index<SubsIndex<Variable>> for Subs {
|
||||||
|
type Output = Variable;
|
||||||
|
|
||||||
|
fn index(&self, index: SubsIndex<Variable>) -> &Self::Output {
|
||||||
|
&self.variables[index.start as usize]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::ops::IndexMut<SubsIndex<Variable>> for Subs {
|
||||||
|
fn index_mut(&mut self, index: SubsIndex<Variable>) -> &mut Self::Output {
|
||||||
|
&mut self.variables[index.start as usize]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> std::fmt::Debug for SubsSlice<T> {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"SubsSlice {{ start: {}, length: {} }}",
|
||||||
|
self.start, self.length
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Copy for SubsIndex<T> {}
|
||||||
|
|
||||||
|
impl<T> Clone for SubsIndex<T> {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
Self {
|
||||||
|
start: self.start,
|
||||||
|
_marker: self._marker,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T> Copy for SubsSlice<T> {}
|
impl<T> Copy for SubsSlice<T> {}
|
||||||
|
|
||||||
impl<T> Clone for SubsSlice<T> {
|
impl<T> Clone for SubsSlice<T> {
|
||||||
|
@ -90,19 +129,61 @@ impl<T> Default for SubsSlice<T> {
|
||||||
|
|
||||||
impl<T> SubsSlice<T> {
|
impl<T> SubsSlice<T> {
|
||||||
pub fn get_slice<'a>(&self, slice: &'a [T]) -> &'a [T] {
|
pub fn get_slice<'a>(&self, slice: &'a [T]) -> &'a [T] {
|
||||||
&slice[..self.start as usize][..self.length as usize]
|
&slice[self.start as usize..][..self.length as usize]
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_slice_mut<'a>(&self, slice: &'a mut [T]) -> &'a mut [T] {
|
||||||
|
&mut slice[self.start as usize..][..self.length as usize]
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn len(&self) -> usize {
|
||||||
|
self.length as usize
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_empty(&self) -> bool {
|
||||||
|
self.len() == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new(start: u32, length: u16) -> Self {
|
||||||
|
Self {
|
||||||
|
start,
|
||||||
|
length,
|
||||||
|
_marker: std::marker::PhantomData,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait GetSubsSlice {
|
impl<T> IntoIterator for SubsSlice<T> {
|
||||||
fn get_subs_slice(subs: &Subs, subs_slice: SubsSlice<Self>) -> &[Self]
|
type Item = SubsIndex<T>;
|
||||||
where
|
|
||||||
Self: Sized;
|
#[allow(clippy::type_complexity)]
|
||||||
|
type IntoIter = Map<std::ops::Range<u32>, fn(u32) -> Self::Item>;
|
||||||
|
|
||||||
|
fn into_iter(self) -> Self::IntoIter {
|
||||||
|
(self.start..(self.start + self.length as u32)).map(u32_to_index)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GetSubsSlice for Variable {
|
fn u32_to_index<T>(i: u32) -> SubsIndex<T> {
|
||||||
fn get_subs_slice(subs: &Subs, subs_slice: SubsSlice<Self>) -> &[Self] {
|
SubsIndex {
|
||||||
subs_slice.get_slice(&subs.variables)
|
start: i,
|
||||||
|
_marker: std::marker::PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait GetSubsSlice<T> {
|
||||||
|
fn get_subs_slice(&self, subs_slice: SubsSlice<T>) -> &[T];
|
||||||
|
|
||||||
|
fn get_subs_slice_mut(&mut self, subs_slice: SubsSlice<T>) -> &mut [T];
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GetSubsSlice<Variable> for Subs {
|
||||||
|
fn get_subs_slice(&self, subs_slice: SubsSlice<Variable>) -> &[Variable] {
|
||||||
|
subs_slice.get_slice(&self.variables)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_subs_slice_mut(&mut self, subs_slice: SubsSlice<Variable>) -> &mut [Variable] {
|
||||||
|
subs_slice.get_slice_mut(&mut self.variables)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -683,7 +764,7 @@ impl Content {
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum FlatType {
|
pub enum FlatType {
|
||||||
Apply(Symbol, Vec<Variable>),
|
Apply(Symbol, Vec<Variable>),
|
||||||
Func(Vec<Variable>, Variable, Variable),
|
Func(SubsSlice<Variable>, Variable, Variable),
|
||||||
Record(RecordFields, Variable),
|
Record(RecordFields, Variable),
|
||||||
TagUnion(MutMap<TagName, Vec<Variable>>, Variable),
|
TagUnion(MutMap<TagName, Vec<Variable>>, Variable),
|
||||||
FunctionOrTagUnion(Box<TagName>, Symbol, Variable),
|
FunctionOrTagUnion(Box<TagName>, Symbol, Variable),
|
||||||
|
@ -953,7 +1034,7 @@ fn occurs(
|
||||||
Func(arg_vars, closure_var, ret_var) => {
|
Func(arg_vars, closure_var, ret_var) => {
|
||||||
let it = once(ret_var)
|
let it = once(ret_var)
|
||||||
.chain(once(closure_var))
|
.chain(once(closure_var))
|
||||||
.chain(arg_vars.iter());
|
.chain(subs.get_subs_slice(*arg_vars).iter());
|
||||||
short_circuit(subs, root_var, &new_seen, it)
|
short_circuit(subs, root_var, &new_seen, it)
|
||||||
}
|
}
|
||||||
Record(vars_by_field, ext_var) => {
|
Record(vars_by_field, ext_var) => {
|
||||||
|
@ -1036,17 +1117,19 @@ fn explicit_substitute(
|
||||||
subs.set_content(in_var, Structure(Apply(symbol, new_args)));
|
subs.set_content(in_var, Structure(Apply(symbol, new_args)));
|
||||||
}
|
}
|
||||||
Func(arg_vars, closure_var, ret_var) => {
|
Func(arg_vars, closure_var, ret_var) => {
|
||||||
let new_arg_vars = arg_vars
|
for var_index in arg_vars.into_iter() {
|
||||||
.iter()
|
let var = subs[var_index];
|
||||||
.map(|var| explicit_substitute(subs, from, to, *var, seen))
|
let answer = explicit_substitute(subs, from, to, var, seen);
|
||||||
.collect();
|
subs[var_index] = answer;
|
||||||
|
}
|
||||||
|
|
||||||
let new_ret_var = explicit_substitute(subs, from, to, ret_var, seen);
|
let new_ret_var = explicit_substitute(subs, from, to, ret_var, seen);
|
||||||
let new_closure_var =
|
let new_closure_var =
|
||||||
explicit_substitute(subs, from, to, closure_var, seen);
|
explicit_substitute(subs, from, to, closure_var, seen);
|
||||||
|
|
||||||
subs.set_content(
|
subs.set_content(
|
||||||
in_var,
|
in_var,
|
||||||
Structure(Func(new_arg_vars, new_closure_var, new_ret_var)),
|
Structure(Func(arg_vars, new_closure_var, new_ret_var)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
TagUnion(mut tags, ext_var) => {
|
TagUnion(mut tags, ext_var) => {
|
||||||
|
@ -1163,9 +1246,15 @@ fn get_var_names(
|
||||||
let taken_names = get_var_names(subs, ret_var, taken_names);
|
let taken_names = get_var_names(subs, ret_var, taken_names);
|
||||||
let taken_names = get_var_names(subs, closure_var, taken_names);
|
let taken_names = get_var_names(subs, closure_var, taken_names);
|
||||||
|
|
||||||
arg_vars.into_iter().fold(taken_names, |answer, arg_var| {
|
let mut accum = taken_names;
|
||||||
get_var_names(subs, arg_var, answer)
|
|
||||||
})
|
for var_index in arg_vars.into_iter() {
|
||||||
|
let arg_var = subs[var_index];
|
||||||
|
|
||||||
|
accum = get_var_names(subs, arg_var, accum)
|
||||||
|
}
|
||||||
|
|
||||||
|
accum
|
||||||
}
|
}
|
||||||
|
|
||||||
FlatType::EmptyRecord | FlatType::EmptyTagUnion | FlatType::Erroneous(_) => {
|
FlatType::EmptyRecord | FlatType::EmptyTagUnion | FlatType::Erroneous(_) => {
|
||||||
|
@ -1370,8 +1459,12 @@ fn flat_type_to_err_type(
|
||||||
Func(arg_vars, closure_var, ret_var) => {
|
Func(arg_vars, closure_var, ret_var) => {
|
||||||
let args = arg_vars
|
let args = arg_vars
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|arg_var| var_to_err_type(subs, state, arg_var))
|
.map(|index| {
|
||||||
|
let arg_var = subs[index];
|
||||||
|
var_to_err_type(subs, state, arg_var)
|
||||||
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let ret = var_to_err_type(subs, state, ret_var);
|
let ret = var_to_err_type(subs, state, ret_var);
|
||||||
let closure = var_to_err_type(subs, state, closure_var);
|
let closure = var_to_err_type(subs, state, closure_var);
|
||||||
|
|
||||||
|
@ -1545,7 +1638,8 @@ fn restore_content(subs: &mut Subs, content: &Content) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Func(arg_vars, closure_var, ret_var) => {
|
Func(arg_vars, closure_var, ret_var) => {
|
||||||
for &var in arg_vars {
|
for index in arg_vars.into_iter() {
|
||||||
|
let var = subs[index];
|
||||||
subs.restore(var);
|
subs.restore(var);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,9 @@ use roc_collections::all::{default_hasher, get_shared, relative_complement, unio
|
||||||
use roc_module::ident::{Lowercase, TagName};
|
use roc_module::ident::{Lowercase, TagName};
|
||||||
use roc_module::symbol::Symbol;
|
use roc_module::symbol::Symbol;
|
||||||
use roc_types::subs::Content::{self, *};
|
use roc_types::subs::Content::{self, *};
|
||||||
use roc_types::subs::{Descriptor, FlatType, Mark, OptVariable, RecordFields, Subs, Variable};
|
use roc_types::subs::{
|
||||||
|
Descriptor, FlatType, GetSubsSlice, Mark, OptVariable, RecordFields, Subs, SubsSlice, Variable,
|
||||||
|
};
|
||||||
use roc_types::types::{gather_fields_ref, ErrorType, Mismatch, RecordField, RecordStructure};
|
use roc_types::types::{gather_fields_ref, ErrorType, Mismatch, RecordField, RecordStructure};
|
||||||
|
|
||||||
macro_rules! mismatch {
|
macro_rules! mismatch {
|
||||||
|
@ -1064,16 +1066,12 @@ fn unify_flat_type(
|
||||||
(Func(l_args, l_closure, l_ret), Func(r_args, r_closure, r_ret))
|
(Func(l_args, l_closure, l_ret), Func(r_args, r_closure, r_ret))
|
||||||
if l_args.len() == r_args.len() =>
|
if l_args.len() == r_args.len() =>
|
||||||
{
|
{
|
||||||
let arg_problems = unify_zip(subs, pool, l_args.iter(), r_args.iter());
|
let arg_problems = unify_zip_slices(subs, pool, *l_args, *r_args);
|
||||||
let ret_problems = unify_pool(subs, pool, *l_ret, *r_ret);
|
let ret_problems = unify_pool(subs, pool, *l_ret, *r_ret);
|
||||||
let closure_problems = unify_pool(subs, pool, *l_closure, *r_closure);
|
let closure_problems = unify_pool(subs, pool, *l_closure, *r_closure);
|
||||||
|
|
||||||
if arg_problems.is_empty() && closure_problems.is_empty() && ret_problems.is_empty() {
|
if arg_problems.is_empty() && closure_problems.is_empty() && ret_problems.is_empty() {
|
||||||
merge(
|
merge(subs, ctx, Structure(Func(*r_args, *r_closure, *r_ret)))
|
||||||
subs,
|
|
||||||
ctx,
|
|
||||||
Structure(Func((*r_args).clone(), *r_closure, *r_ret)),
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
let mut problems = ret_problems;
|
let mut problems = ret_problems;
|
||||||
|
|
||||||
|
@ -1091,7 +1089,7 @@ fn unify_flat_type(
|
||||||
tag_name,
|
tag_name,
|
||||||
*tag_symbol,
|
*tag_symbol,
|
||||||
*ext,
|
*ext,
|
||||||
args,
|
*args,
|
||||||
*ret,
|
*ret,
|
||||||
*closure,
|
*closure,
|
||||||
true,
|
true,
|
||||||
|
@ -1105,7 +1103,7 @@ fn unify_flat_type(
|
||||||
tag_name,
|
tag_name,
|
||||||
*tag_symbol,
|
*tag_symbol,
|
||||||
*ext,
|
*ext,
|
||||||
args,
|
*args,
|
||||||
*ret,
|
*ret,
|
||||||
*closure,
|
*closure,
|
||||||
false,
|
false,
|
||||||
|
@ -1191,6 +1189,26 @@ fn unify_flat_type(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn unify_zip_slices(
|
||||||
|
subs: &mut Subs,
|
||||||
|
pool: &mut Pool,
|
||||||
|
left: SubsSlice<Variable>,
|
||||||
|
right: SubsSlice<Variable>,
|
||||||
|
) -> Outcome {
|
||||||
|
let mut problems = Vec::new();
|
||||||
|
|
||||||
|
let it = left.into_iter().zip(right.into_iter());
|
||||||
|
|
||||||
|
for (l_index, r_index) in it {
|
||||||
|
let l_var = subs[l_index];
|
||||||
|
let r_var = subs[r_index];
|
||||||
|
|
||||||
|
problems.extend(unify_pool(subs, pool, l_var, r_var));
|
||||||
|
}
|
||||||
|
|
||||||
|
problems
|
||||||
|
}
|
||||||
|
|
||||||
fn unify_zip<'a, I>(subs: &mut Subs, pool: &mut Pool, left_iter: I, right_iter: I) -> Outcome
|
fn unify_zip<'a, I>(subs: &mut Subs, pool: &mut Pool, left_iter: I, right_iter: I) -> Outcome
|
||||||
where
|
where
|
||||||
I: Iterator<Item = &'a Variable>,
|
I: Iterator<Item = &'a Variable>,
|
||||||
|
@ -1379,7 +1397,7 @@ fn unify_function_or_tag_union_and_func(
|
||||||
tag_name: &TagName,
|
tag_name: &TagName,
|
||||||
tag_symbol: Symbol,
|
tag_symbol: Symbol,
|
||||||
tag_ext: Variable,
|
tag_ext: Variable,
|
||||||
function_arguments: &[Variable],
|
function_arguments: SubsSlice<Variable>,
|
||||||
function_return: Variable,
|
function_return: Variable,
|
||||||
function_lambda_set: Variable,
|
function_lambda_set: Variable,
|
||||||
left: bool,
|
left: bool,
|
||||||
|
@ -1388,7 +1406,10 @@ fn unify_function_or_tag_union_and_func(
|
||||||
|
|
||||||
let mut new_tags = MutMap::with_capacity_and_hasher(1, default_hasher());
|
let mut new_tags = MutMap::with_capacity_and_hasher(1, default_hasher());
|
||||||
|
|
||||||
new_tags.insert(tag_name.clone(), function_arguments.to_owned());
|
new_tags.insert(
|
||||||
|
tag_name.clone(),
|
||||||
|
subs.get_subs_slice(function_arguments).to_owned(),
|
||||||
|
);
|
||||||
|
|
||||||
let content = Structure(TagUnion(new_tags, tag_ext));
|
let content = Structure(TagUnion(new_tags, tag_ext));
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,9 @@ use roc_collections::all::{BumpMap, BumpMapDefault, MutMap};
|
||||||
use roc_module::symbol::Symbol;
|
use roc_module::symbol::Symbol;
|
||||||
use roc_region::all::{Located, Region};
|
use roc_region::all::{Located, Region};
|
||||||
use roc_types::solved_types::Solved;
|
use roc_types::solved_types::Solved;
|
||||||
use roc_types::subs::{Content, Descriptor, FlatType, Mark, OptVariable, Rank, Subs, Variable};
|
use roc_types::subs::{
|
||||||
|
Content, Descriptor, FlatType, Mark, OptVariable, Rank, Subs, SubsSlice, Variable,
|
||||||
|
};
|
||||||
use roc_types::types::{Alias, Category, ErrorType, PatternCategory, RecordField};
|
use roc_types::types::{Alias, Category, ErrorType, PatternCategory, RecordField};
|
||||||
use roc_unify::unify::unify;
|
use roc_unify::unify::unify;
|
||||||
use roc_unify::unify::Unified::*;
|
use roc_unify::unify::Unified::*;
|
||||||
|
@ -857,20 +859,24 @@ fn type_to_variable<'a>(
|
||||||
register(subs, rank, pools, content)
|
register(subs, rank, pools, content)
|
||||||
}
|
}
|
||||||
// This case is important for the rank of boolean variables
|
// This case is important for the rank of boolean variables
|
||||||
Function(args, closure_type_id, ret_type_id) => {
|
Function(arg_vars, closure_type_id, ret_type_id) => {
|
||||||
let mut arg_vars = Vec::with_capacity(args.len());
|
|
||||||
|
|
||||||
let closure_type = mempool.get(*closure_type_id);
|
let closure_type = mempool.get(*closure_type_id);
|
||||||
let ret_type = mempool.get(*ret_type_id);
|
let ret_type = mempool.get(*ret_type_id);
|
||||||
|
|
||||||
for arg_id in args.iter_node_ids() {
|
let mut new_arg_vars = Vec::with_capacity(arg_vars.len());
|
||||||
let arg = mempool.get(arg_id);
|
|
||||||
|
|
||||||
arg_vars.push(type_to_variable(
|
for var_id in arg_vars.iter_node_ids() {
|
||||||
arena, mempool, subs, rank, pools, cached, arg,
|
let arg = mempool.get(var_id);
|
||||||
))
|
let var = type_to_variable(arena, mempool, subs, rank, pools, cached, arg);
|
||||||
|
new_arg_vars.push(var)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let start = subs.variables.len() as u32;
|
||||||
|
let length = arg_vars.len() as u16;
|
||||||
|
let arg_vars = SubsSlice::new(start, length);
|
||||||
|
|
||||||
|
subs.variables.extend(new_arg_vars);
|
||||||
|
|
||||||
let ret_var = type_to_variable(arena, mempool, subs, rank, pools, cached, ret_type);
|
let ret_var = type_to_variable(arena, mempool, subs, rank, pools, cached, ret_type);
|
||||||
let closure_var =
|
let closure_var =
|
||||||
type_to_variable(arena, mempool, subs, rank, pools, cached, closure_type);
|
type_to_variable(arena, mempool, subs, rank, pools, cached, closure_type);
|
||||||
|
@ -1196,9 +1202,9 @@ fn adjust_rank_content(
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
for var in arg_vars {
|
for index in arg_vars.into_iter() {
|
||||||
rank =
|
let var = subs[index];
|
||||||
rank.max(adjust_rank(subs, young_mark, visit_mark, group_rank, *var));
|
rank = rank.max(adjust_rank(subs, young_mark, visit_mark, group_rank, var));
|
||||||
}
|
}
|
||||||
|
|
||||||
rank
|
rank
|
||||||
|
@ -1344,128 +1350,82 @@ fn instantiate_rigids_help(
|
||||||
// will not repeat this work or crawl this variable again.
|
// will not repeat this work or crawl this variable again.
|
||||||
match content {
|
match content {
|
||||||
Structure(flat_type) => {
|
Structure(flat_type) => {
|
||||||
let new_flat_type = match flat_type {
|
match flat_type {
|
||||||
Apply(symbol, args) => {
|
Apply(_, args) => {
|
||||||
let args = args
|
for var in args.into_iter() {
|
||||||
.into_iter()
|
instantiate_rigids_help(subs, max_rank, pools, var);
|
||||||
.map(|var| instantiate_rigids_help(subs, max_rank, pools, var))
|
}
|
||||||
.collect();
|
|
||||||
|
|
||||||
Apply(symbol, args)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Func(arg_vars, closure_var, ret_var) => {
|
Func(arg_vars, closure_var, ret_var) => {
|
||||||
let new_ret_var = instantiate_rigids_help(subs, max_rank, pools, ret_var);
|
instantiate_rigids_help(subs, max_rank, pools, ret_var);
|
||||||
let new_closure_var =
|
instantiate_rigids_help(subs, max_rank, pools, closure_var);
|
||||||
instantiate_rigids_help(subs, max_rank, pools, closure_var);
|
|
||||||
let arg_vars = arg_vars
|
|
||||||
.into_iter()
|
|
||||||
.map(|var| instantiate_rigids_help(subs, max_rank, pools, var))
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
Func(arg_vars, new_closure_var, new_ret_var)
|
for index in arg_vars.into_iter() {
|
||||||
|
let var = subs[index];
|
||||||
|
instantiate_rigids_help(subs, max_rank, pools, var);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
same @ EmptyRecord | same @ EmptyTagUnion | same @ Erroneous(_) => same,
|
EmptyRecord | EmptyTagUnion | Erroneous(_) => {}
|
||||||
|
|
||||||
Record(fields, ext_var) => {
|
Record(fields, ext_var) => {
|
||||||
for var in fields.iter_variables() {
|
for var in fields.iter_variables() {
|
||||||
instantiate_rigids_help(subs, max_rank, pools, *var);
|
instantiate_rigids_help(subs, max_rank, pools, *var);
|
||||||
}
|
}
|
||||||
|
|
||||||
Record(
|
instantiate_rigids_help(subs, max_rank, pools, ext_var);
|
||||||
fields,
|
|
||||||
instantiate_rigids_help(subs, max_rank, pools, ext_var),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TagUnion(tags, ext_var) => {
|
TagUnion(tags, ext_var) => {
|
||||||
let mut new_tags = MutMap::default();
|
for (_, vars) in tags {
|
||||||
|
for var in vars.into_iter() {
|
||||||
for (tag, vars) in tags {
|
instantiate_rigids_help(subs, max_rank, pools, var);
|
||||||
let new_vars: Vec<Variable> = vars
|
}
|
||||||
.into_iter()
|
|
||||||
.map(|var| instantiate_rigids_help(subs, max_rank, pools, var))
|
|
||||||
.collect();
|
|
||||||
new_tags.insert(tag, new_vars);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TagUnion(
|
instantiate_rigids_help(subs, max_rank, pools, ext_var);
|
||||||
new_tags,
|
|
||||||
instantiate_rigids_help(subs, max_rank, pools, ext_var),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FunctionOrTagUnion(tag_name, symbol, ext_var) => FunctionOrTagUnion(
|
FunctionOrTagUnion(_tag_name, _symbol, ext_var) => {
|
||||||
tag_name,
|
instantiate_rigids_help(subs, max_rank, pools, ext_var);
|
||||||
symbol,
|
}
|
||||||
instantiate_rigids_help(subs, max_rank, pools, ext_var),
|
|
||||||
),
|
|
||||||
|
|
||||||
RecursiveTagUnion(rec_var, tags, ext_var) => {
|
RecursiveTagUnion(rec_var, tags, ext_var) => {
|
||||||
let mut new_tags = MutMap::default();
|
instantiate_rigids_help(subs, max_rank, pools, rec_var);
|
||||||
|
|
||||||
let new_rec_var = instantiate_rigids_help(subs, max_rank, pools, rec_var);
|
for (_, vars) in tags {
|
||||||
|
for var in vars.into_iter() {
|
||||||
for (tag, vars) in tags {
|
instantiate_rigids_help(subs, max_rank, pools, var);
|
||||||
let new_vars: Vec<Variable> = vars
|
}
|
||||||
.into_iter()
|
|
||||||
.map(|var| instantiate_rigids_help(subs, max_rank, pools, var))
|
|
||||||
.collect();
|
|
||||||
new_tags.insert(tag, new_vars);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RecursiveTagUnion(
|
instantiate_rigids_help(subs, max_rank, pools, ext_var);
|
||||||
new_rec_var,
|
|
||||||
new_tags,
|
|
||||||
instantiate_rigids_help(subs, max_rank, pools, ext_var),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
subs.set(copy, make_descriptor(Structure(new_flat_type)));
|
|
||||||
|
|
||||||
copy
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FlexVar(_) | Error => copy,
|
FlexVar(_) | Error => {}
|
||||||
|
|
||||||
RecursionVar {
|
RecursionVar { structure, .. } => {
|
||||||
opt_name,
|
instantiate_rigids_help(subs, max_rank, pools, structure);
|
||||||
structure,
|
|
||||||
} => {
|
|
||||||
let new_structure = instantiate_rigids_help(subs, max_rank, pools, structure);
|
|
||||||
|
|
||||||
subs.set(
|
|
||||||
copy,
|
|
||||||
make_descriptor(RecursionVar {
|
|
||||||
opt_name,
|
|
||||||
structure: new_structure,
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
copy
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RigidVar(name) => {
|
RigidVar(name) => {
|
||||||
|
// what it's all about: convert the rigid var into a flex var
|
||||||
subs.set(copy, make_descriptor(FlexVar(Some(name))));
|
subs.set(copy, make_descriptor(FlexVar(Some(name))));
|
||||||
|
|
||||||
copy
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Alias(symbol, args, real_type_var) => {
|
Alias(_, args, real_type_var) => {
|
||||||
let new_args = args
|
for (_, var) in args.into_iter() {
|
||||||
.into_iter()
|
instantiate_rigids_help(subs, max_rank, pools, var);
|
||||||
.map(|(name, var)| (name, instantiate_rigids_help(subs, max_rank, pools, var)))
|
}
|
||||||
.collect();
|
|
||||||
let new_real_type_var = instantiate_rigids_help(subs, max_rank, pools, real_type_var);
|
|
||||||
let new_content = Alias(symbol, new_args, new_real_type_var);
|
|
||||||
|
|
||||||
subs.set(copy, make_descriptor(new_content));
|
instantiate_rigids_help(subs, max_rank, pools, real_type_var);
|
||||||
|
|
||||||
copy
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deep_copy_var(subs: &mut Subs, rank: Rank, pools: &mut Pools, var: Variable) -> Variable {
|
fn deep_copy_var(subs: &mut Subs, rank: Rank, pools: &mut Pools, var: Variable) -> Variable {
|
||||||
|
@ -1537,10 +1497,20 @@ fn deep_copy_var_help(
|
||||||
Func(arg_vars, closure_var, ret_var) => {
|
Func(arg_vars, closure_var, ret_var) => {
|
||||||
let new_ret_var = deep_copy_var_help(subs, max_rank, pools, ret_var);
|
let new_ret_var = deep_copy_var_help(subs, max_rank, pools, ret_var);
|
||||||
let new_closure_var = deep_copy_var_help(subs, max_rank, pools, closure_var);
|
let new_closure_var = deep_copy_var_help(subs, max_rank, pools, closure_var);
|
||||||
let arg_vars = arg_vars
|
|
||||||
.into_iter()
|
let mut new_arg_vars = Vec::with_capacity(arg_vars.len());
|
||||||
.map(|var| deep_copy_var_help(subs, max_rank, pools, var))
|
|
||||||
.collect();
|
for index in arg_vars.into_iter() {
|
||||||
|
let var = subs[index];
|
||||||
|
let copy_var = deep_copy_var_help(subs, max_rank, pools, var);
|
||||||
|
new_arg_vars.push(copy_var);
|
||||||
|
}
|
||||||
|
|
||||||
|
let start = subs.variables.len() as u32;
|
||||||
|
let length = arg_vars.len() as u16;
|
||||||
|
let arg_vars = SubsSlice::new(start, length);
|
||||||
|
|
||||||
|
subs.variables.extend(new_arg_vars);
|
||||||
|
|
||||||
Func(arg_vars, new_closure_var, new_ret_var)
|
Func(arg_vars, new_closure_var, new_ret_var)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue