diff --git a/compiler/mono/src/ir.rs b/compiler/mono/src/ir.rs index 41bf2609c9..3536bf1cdb 100644 --- a/compiler/mono/src/ir.rs +++ b/compiler/mono/src/ir.rs @@ -15,7 +15,7 @@ use roc_module::symbol::{IdentIds, ModuleId, Symbol}; use roc_problem::can::RuntimeError; use roc_region::all::{Located, Region}; 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 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 { let ret_var = *ret_var; - let arg_vars = arg_vars.clone(); + let arg_vars = *arg_vars; tag_union_to_function( env, - &arg_vars, + arg_vars, ret_var, tag_name, closure_name, @@ -4346,7 +4346,7 @@ fn convert_tag_union<'a>( #[allow(clippy::too_many_arguments)] fn tag_union_to_function<'a>( env: &mut Env<'a, '_>, - argument_variables: &[Variable], + argument_variables: SubsSlice, return_variable: Variable, tag_name: TagName, proc_symbol: Symbol, @@ -4360,15 +4360,17 @@ fn tag_union_to_function<'a>( let mut loc_pattern_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 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)); - loc_pattern_args.push((*arg_var, loc_pattern)); - loc_expr_args.push((*arg_var, loc_expr)); + loc_pattern_args.push((arg_var, loc_pattern)); + loc_expr_args.push((arg_var, loc_expr)); } let loc_body = Located::at_zero(roc_can::expr::Expr::Tag { diff --git a/compiler/mono/src/layout.rs b/compiler/mono/src/layout.rs index fba158ec6c..fc6dc45ac4 100644 --- a/compiler/mono/src/layout.rs +++ b/compiler/mono/src/layout.rs @@ -1193,7 +1193,8 @@ fn layout_from_flat_type<'a>( Func(args, closure_var, ret_var) => { 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)?); } diff --git a/compiler/solve/src/solve.rs b/compiler/solve/src/solve.rs index a4def825d0..471727d077 100644 --- a/compiler/solve/src/solve.rs +++ b/compiler/solve/src/solve.rs @@ -4,7 +4,9 @@ use roc_collections::all::{default_hasher, MutMap}; use roc_module::symbol::Symbol; use roc_region::all::{Located, Region}; 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::{Alias, Category, ErrorType, PatternCategory}; use roc_unify::unify::unify; @@ -656,13 +658,20 @@ fn type_to_variable( EmptyTagUnion => Variable::EMPTY_TAG_UNION, // This case is important for the rank of boolean variables - Function(args, closure_type, ret_type) => { - let mut arg_vars = Vec::with_capacity(args.len()); + Function(arg_vars, closure_type, ret_type) => { + let mut new_arg_vars = Vec::with_capacity(arg_vars.len()); - for arg in args { - arg_vars.push(type_to_variable(subs, rank, pools, cached, arg)) + for arg in arg_vars { + 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 closure_var = type_to_variable(subs, rank, pools, cached, closure_type); 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 { - rank = - rank.max(adjust_rank(subs, young_mark, visit_mark, group_rank, *var)); + for index in arg_vars.into_iter() { + let var = subs[index]; + rank = rank.max(adjust_rank(subs, young_mark, visit_mark, group_rank, var)); } 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, 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); } } @@ -1356,10 +1366,20 @@ fn deep_copy_var_help( Func(arg_vars, closure_var, 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 arg_vars = arg_vars - .into_iter() - .map(|var| deep_copy_var_help(subs, max_rank, pools, var)) - .collect(); + + let mut new_arg_vars = Vec::with_capacity(arg_vars.len()); + + 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) } diff --git a/compiler/types/src/pretty_print.rs b/compiler/types/src/pretty_print.rs index e3dd11e984..5f4710b039 100644 --- a/compiler/types/src/pretty_print.rs +++ b/compiler/types/src/pretty_print.rs @@ -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 roc_collections::all::{MutMap, MutSet}; use roc_module::ident::{Lowercase, TagName}; @@ -146,8 +146,9 @@ fn find_names_needed( } } Structure(Func(arg_vars, _closure_var, ret_var)) => { - for var in arg_vars { - find_names_needed(*var, subs, roots, root_appearances, names_taken); + for index in arg_vars.into_iter() { + 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); @@ -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), EmptyRecord => buf.push_str(EMPTY_RECORD), 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) => { use crate::types::{gather_fields, RecordStructure}; diff --git a/compiler/types/src/solved_types.rs b/compiler/types/src/solved_types.rs index a21e4c1600..3304124b72 100644 --- a/compiler/types/src/solved_types.rs +++ b/compiler/types/src/solved_types.rs @@ -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 roc_collections::all::{ImMap, MutSet, SendMap}; use roc_module::ident::{Lowercase, TagName}; @@ -387,7 +387,7 @@ impl SolvedType { Func(args, closure, ret) => { 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)); } diff --git a/compiler/types/src/subs.rs b/compiler/types/src/subs.rs index 1e1fd40e09..c9982d3757 100644 --- a/compiler/types/src/subs.rs +++ b/compiler/types/src/subs.rs @@ -53,19 +53,58 @@ struct ErrorTypeState { #[derive(Default, Clone)] pub struct Subs { utable: UnificationTable>, - variables: Vec, + pub variables: Vec, tag_names: Vec, field_names: Vec, record_fields: Vec>, } -#[repr(packed(2))] pub struct SubsSlice { start: u32, length: u16, _marker: std::marker::PhantomData, } +pub struct SubsIndex { + start: u32, + _marker: std::marker::PhantomData, +} + +impl std::ops::Index> for Subs { + type Output = Variable; + + fn index(&self, index: SubsIndex) -> &Self::Output { + &self.variables[index.start as usize] + } +} + +impl std::ops::IndexMut> for Subs { + fn index_mut(&mut self, index: SubsIndex) -> &mut Self::Output { + &mut self.variables[index.start as usize] + } +} + +impl std::fmt::Debug for SubsSlice { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "SubsSlice {{ start: {}, length: {} }}", + self.start, self.length + ) + } +} + +impl Copy for SubsIndex {} + +impl Clone for SubsIndex { + fn clone(&self) -> Self { + Self { + start: self.start, + _marker: self._marker, + } + } +} + impl Copy for SubsSlice {} impl Clone for SubsSlice { @@ -90,19 +129,61 @@ impl Default for SubsSlice { impl SubsSlice { 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 { - fn get_subs_slice(subs: &Subs, subs_slice: SubsSlice) -> &[Self] - where - Self: Sized; +impl IntoIterator for SubsSlice { + type Item = SubsIndex; + + #[allow(clippy::type_complexity)] + type IntoIter = Map, 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 get_subs_slice(subs: &Subs, subs_slice: SubsSlice) -> &[Self] { - subs_slice.get_slice(&subs.variables) +fn u32_to_index(i: u32) -> SubsIndex { + SubsIndex { + start: i, + _marker: std::marker::PhantomData, + } +} + +pub trait GetSubsSlice { + fn get_subs_slice(&self, subs_slice: SubsSlice) -> &[T]; + + fn get_subs_slice_mut(&mut self, subs_slice: SubsSlice) -> &mut [T]; +} + +impl GetSubsSlice for Subs { + fn get_subs_slice(&self, subs_slice: SubsSlice) -> &[Variable] { + subs_slice.get_slice(&self.variables) + } + + fn get_subs_slice_mut(&mut self, subs_slice: SubsSlice) -> &mut [Variable] { + subs_slice.get_slice_mut(&mut self.variables) } } @@ -683,7 +764,7 @@ impl Content { #[derive(Clone, Debug)] pub enum FlatType { Apply(Symbol, Vec), - Func(Vec, Variable, Variable), + Func(SubsSlice, Variable, Variable), Record(RecordFields, Variable), TagUnion(MutMap>, Variable), FunctionOrTagUnion(Box, Symbol, Variable), @@ -953,7 +1034,7 @@ fn occurs( Func(arg_vars, closure_var, ret_var) => { let it = once(ret_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) } Record(vars_by_field, ext_var) => { @@ -1036,17 +1117,19 @@ fn explicit_substitute( subs.set_content(in_var, Structure(Apply(symbol, new_args))); } Func(arg_vars, closure_var, ret_var) => { - let new_arg_vars = arg_vars - .iter() - .map(|var| explicit_substitute(subs, from, to, *var, seen)) - .collect(); + for var_index in arg_vars.into_iter() { + let var = subs[var_index]; + let answer = explicit_substitute(subs, from, to, var, seen); + subs[var_index] = answer; + } + let new_ret_var = explicit_substitute(subs, from, to, ret_var, seen); let new_closure_var = explicit_substitute(subs, from, to, closure_var, seen); subs.set_content( 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) => { @@ -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, closure_var, taken_names); - arg_vars.into_iter().fold(taken_names, |answer, arg_var| { - get_var_names(subs, arg_var, answer) - }) + let mut accum = taken_names; + + 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(_) => { @@ -1370,8 +1459,12 @@ fn flat_type_to_err_type( Func(arg_vars, closure_var, ret_var) => { let args = arg_vars .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(); + let ret = var_to_err_type(subs, state, ret_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) => { - for &var in arg_vars { + for index in arg_vars.into_iter() { + let var = subs[index]; subs.restore(var); } diff --git a/compiler/unify/src/unify.rs b/compiler/unify/src/unify.rs index ca915e69a9..6889eaf40a 100644 --- a/compiler/unify/src/unify.rs +++ b/compiler/unify/src/unify.rs @@ -2,7 +2,9 @@ use roc_collections::all::{default_hasher, get_shared, relative_complement, unio use roc_module::ident::{Lowercase, TagName}; use roc_module::symbol::Symbol; 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}; 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)) 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 closure_problems = unify_pool(subs, pool, *l_closure, *r_closure); if arg_problems.is_empty() && closure_problems.is_empty() && ret_problems.is_empty() { - merge( - subs, - ctx, - Structure(Func((*r_args).clone(), *r_closure, *r_ret)), - ) + merge(subs, ctx, Structure(Func(*r_args, *r_closure, *r_ret))) } else { let mut problems = ret_problems; @@ -1091,7 +1089,7 @@ fn unify_flat_type( tag_name, *tag_symbol, *ext, - args, + *args, *ret, *closure, true, @@ -1105,7 +1103,7 @@ fn unify_flat_type( tag_name, *tag_symbol, *ext, - args, + *args, *ret, *closure, false, @@ -1191,6 +1189,26 @@ fn unify_flat_type( } } +fn unify_zip_slices( + subs: &mut Subs, + pool: &mut Pool, + left: SubsSlice, + right: SubsSlice, +) -> 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 where I: Iterator, @@ -1379,7 +1397,7 @@ fn unify_function_or_tag_union_and_func( tag_name: &TagName, tag_symbol: Symbol, tag_ext: Variable, - function_arguments: &[Variable], + function_arguments: SubsSlice, function_return: Variable, function_lambda_set: Variable, 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()); - 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)); diff --git a/editor/src/lang/solve.rs b/editor/src/lang/solve.rs index 5d44b4f2be..800c39c8e8 100644 --- a/editor/src/lang/solve.rs +++ b/editor/src/lang/solve.rs @@ -9,7 +9,9 @@ use roc_collections::all::{BumpMap, BumpMapDefault, MutMap}; use roc_module::symbol::Symbol; use roc_region::all::{Located, Region}; 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_unify::unify::unify; use roc_unify::unify::Unified::*; @@ -857,20 +859,24 @@ fn type_to_variable<'a>( register(subs, rank, pools, content) } // This case is important for the rank of boolean variables - Function(args, closure_type_id, ret_type_id) => { - let mut arg_vars = Vec::with_capacity(args.len()); - + Function(arg_vars, closure_type_id, ret_type_id) => { let closure_type = mempool.get(*closure_type_id); let ret_type = mempool.get(*ret_type_id); - for arg_id in args.iter_node_ids() { - let arg = mempool.get(arg_id); + let mut new_arg_vars = Vec::with_capacity(arg_vars.len()); - arg_vars.push(type_to_variable( - arena, mempool, subs, rank, pools, cached, arg, - )) + for var_id in arg_vars.iter_node_ids() { + 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 closure_var = type_to_variable(arena, mempool, subs, rank, pools, cached, closure_type); @@ -1196,9 +1202,9 @@ fn adjust_rank_content( )); } - for var in arg_vars { - rank = - rank.max(adjust_rank(subs, young_mark, visit_mark, group_rank, *var)); + for index in arg_vars.into_iter() { + let var = subs[index]; + rank = rank.max(adjust_rank(subs, young_mark, visit_mark, group_rank, var)); } rank @@ -1344,128 +1350,82 @@ fn instantiate_rigids_help( // will not repeat this work or crawl this variable again. match content { Structure(flat_type) => { - let new_flat_type = match flat_type { - Apply(symbol, args) => { - let args = args - .into_iter() - .map(|var| instantiate_rigids_help(subs, max_rank, pools, var)) - .collect(); - - Apply(symbol, args) + match flat_type { + Apply(_, args) => { + for var in args.into_iter() { + instantiate_rigids_help(subs, max_rank, pools, var); + } } Func(arg_vars, closure_var, ret_var) => { - let new_ret_var = instantiate_rigids_help(subs, max_rank, pools, ret_var); - let new_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(); + instantiate_rigids_help(subs, max_rank, pools, ret_var); + instantiate_rigids_help(subs, max_rank, pools, closure_var); - 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) => { for var in fields.iter_variables() { instantiate_rigids_help(subs, max_rank, pools, *var); } - Record( - fields, - instantiate_rigids_help(subs, max_rank, pools, ext_var), - ) + instantiate_rigids_help(subs, max_rank, pools, ext_var); } TagUnion(tags, ext_var) => { - let mut new_tags = MutMap::default(); - - for (tag, vars) in tags { - let new_vars: Vec = vars - .into_iter() - .map(|var| instantiate_rigids_help(subs, max_rank, pools, var)) - .collect(); - new_tags.insert(tag, new_vars); + for (_, vars) in tags { + for var in vars.into_iter() { + instantiate_rigids_help(subs, max_rank, pools, var); + } } - TagUnion( - new_tags, - instantiate_rigids_help(subs, max_rank, pools, ext_var), - ) + instantiate_rigids_help(subs, max_rank, pools, ext_var); } - FunctionOrTagUnion(tag_name, symbol, ext_var) => FunctionOrTagUnion( - tag_name, - symbol, - instantiate_rigids_help(subs, max_rank, pools, ext_var), - ), + FunctionOrTagUnion(_tag_name, _symbol, ext_var) => { + instantiate_rigids_help(subs, max_rank, pools, 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 (tag, vars) in tags { - let new_vars: Vec = vars - .into_iter() - .map(|var| instantiate_rigids_help(subs, max_rank, pools, var)) - .collect(); - new_tags.insert(tag, new_vars); + for (_, vars) in tags { + for var in vars.into_iter() { + instantiate_rigids_help(subs, max_rank, pools, var); + } } - RecursiveTagUnion( - new_rec_var, - new_tags, - instantiate_rigids_help(subs, max_rank, pools, ext_var), - ) + 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 { - opt_name, - structure, - } => { - let new_structure = instantiate_rigids_help(subs, max_rank, pools, structure); - - subs.set( - copy, - make_descriptor(RecursionVar { - opt_name, - structure: new_structure, - }), - ); - - copy + RecursionVar { structure, .. } => { + instantiate_rigids_help(subs, max_rank, pools, structure); } RigidVar(name) => { + // what it's all about: convert the rigid var into a flex var subs.set(copy, make_descriptor(FlexVar(Some(name)))); - - copy } - Alias(symbol, args, real_type_var) => { - let new_args = args - .into_iter() - .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); + Alias(_, args, real_type_var) => { + for (_, var) in args.into_iter() { + instantiate_rigids_help(subs, max_rank, pools, var); + } - subs.set(copy, make_descriptor(new_content)); - - copy + instantiate_rigids_help(subs, max_rank, pools, real_type_var); } } + + var } 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) => { 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 arg_vars = arg_vars - .into_iter() - .map(|var| deep_copy_var_help(subs, max_rank, pools, var)) - .collect(); + + let mut new_arg_vars = Vec::with_capacity(arg_vars.len()); + + 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) }