diff --git a/compiler/mono/src/ir.rs b/compiler/mono/src/ir.rs index 3536bf1cdb..cbb009956a 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, SubsSlice, Variable}; +use roc_types::subs::{Content, FlatType, Subs, Variable, VariableSubsSlice}; use std::collections::HashMap; use ven_pretty::{BoxAllocator, DocAllocator, DocBuilder}; @@ -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: SubsSlice, + argument_variables: VariableSubsSlice, return_variable: Variable, tag_name: TagName, proc_symbol: Symbol, diff --git a/compiler/solve/src/solve.rs b/compiler/solve/src/solve.rs index ee3f57c90c..bc96ccc4db 100644 --- a/compiler/solve/src/solve.rs +++ b/compiler/solve/src/solve.rs @@ -5,7 +5,8 @@ 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, RecordFields, Subs, SubsSlice, Variable, + Content, Descriptor, FlatType, Mark, OptVariable, Rank, RecordFields, Subs, Variable, + VariableSubsSlice, }; use roc_types::types::Type::{self, *}; use roc_types::types::{Alias, Category, ErrorType, PatternCategory}; @@ -666,11 +667,7 @@ fn type_to_variable( 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 arg_vars = VariableSubsSlice::insert_into_subs(subs, 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); @@ -1380,11 +1377,7 @@ fn deep_copy_var_help( 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); + let arg_vars = VariableSubsSlice::insert_into_subs(subs, 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 40eaac4913..c0a41a8748 100644 --- a/compiler/types/src/pretty_print.rs +++ b/compiler/types/src/pretty_print.rs @@ -409,9 +409,14 @@ 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, subs.get_subs_slice(*args), *ret, subs, buf, parens) - } + Func(args, _closure, ret) => write_fn( + env, + subs.get_subs_slice(*args.as_subs_slice()), + *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 b3b1a10d86..e3b81b9b0e 100644 --- a/compiler/types/src/solved_types.rs +++ b/compiler/types/src/solved_types.rs @@ -387,7 +387,7 @@ impl SolvedType { Func(args, closure, ret) => { let mut new_args = Vec::with_capacity(args.len()); - for var in subs.get_subs_slice(*args) { + for var in subs.get_subs_slice(*args.as_subs_slice()) { 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 861d5a8f3e..4e078323bf 100644 --- a/compiler/types/src/subs.rs +++ b/compiler/types/src/subs.rs @@ -829,7 +829,7 @@ impl Content { #[derive(Clone, Debug)] pub enum FlatType { Apply(Symbol, Vec), - Func(SubsSlice, Variable, Variable), + Func(VariableSubsSlice, Variable, Variable), Record(RecordFields, Variable), TagUnion(MutMap>, Variable), FunctionOrTagUnion(Box, Symbol, Variable), @@ -847,6 +847,54 @@ pub enum Builtin { EmptyRecord, } +#[derive(Clone, Copy, Debug)] +pub struct VariableSubsSlice { + slice: SubsSlice, +} + +impl VariableSubsSlice { + pub fn len(&self) -> usize { + self.slice.len() + } + + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + + pub fn as_subs_slice(&self) -> &SubsSlice { + &self.slice + } + + pub fn new(start: u32, length: u16) -> Self { + Self { + slice: SubsSlice::new(start, length), + } + } + + pub fn insert_into_subs(subs: &mut Subs, input: I) -> Self + where + I: IntoIterator, + { + let start = subs.variables.len() as u32; + + subs.variables.extend(input.into_iter()); + + let length = (subs.variables.len() as u32 - start) as u16; + + Self::new(start, length) + } +} + +impl IntoIterator for VariableSubsSlice { + type Item = SubsIndex; + + type IntoIter = as IntoIterator>::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + self.slice.into_iter() + } +} + #[derive(Clone, Copy, Debug)] pub struct RecordFields { pub length: u16, @@ -907,8 +955,15 @@ impl RecordFields { let variables_start = subs.variables.len() as u32; let field_types_start = subs.record_fields.len() as u32; + let it = input.into_iter(); + let size_hint = it.size_hint().0; + + subs.variables.reserve(size_hint); + subs.field_names.reserve(size_hint); + subs.record_fields.reserve(size_hint); + let mut length = 0; - for (k, v) in input { + for (k, v) in it { let var = *v.as_inner(); let record_field = v.map(|_| ()); @@ -1049,7 +1104,7 @@ fn occurs( Func(arg_vars, closure_var, ret_var) => { let it = once(ret_var) .chain(once(closure_var)) - .chain(subs.get_subs_slice(*arg_vars).iter()); + .chain(subs.get_subs_slice(*arg_vars.as_subs_slice()).iter()); short_circuit(subs, root_var, &new_seen, it) } Record(vars_by_field, ext_var) => { diff --git a/compiler/unify/src/unify.rs b/compiler/unify/src/unify.rs index f57e524fdf..f0e6d481ee 100644 --- a/compiler/unify/src/unify.rs +++ b/compiler/unify/src/unify.rs @@ -4,6 +4,7 @@ use roc_module::symbol::Symbol; use roc_types::subs::Content::{self, *}; use roc_types::subs::{ Descriptor, FlatType, GetSubsSlice, Mark, OptVariable, RecordFields, Subs, SubsSlice, Variable, + VariableSubsSlice, }; use roc_types::types::{ErrorType, Mismatch, RecordField}; @@ -1206,7 +1207,8 @@ 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_slices(subs, pool, *l_args, *r_args); + let arg_problems = + unify_zip_slices(subs, pool, *l_args.as_subs_slice(), *r_args.as_subs_slice()); let ret_problems = unify_pool(subs, pool, *l_ret, *r_ret); let closure_problems = unify_pool(subs, pool, *l_closure, *r_closure); @@ -1537,7 +1539,7 @@ fn unify_function_or_tag_union_and_func( tag_name: &TagName, tag_symbol: Symbol, tag_ext: Variable, - function_arguments: SubsSlice, + function_arguments: VariableSubsSlice, function_return: Variable, function_lambda_set: Variable, left: bool, @@ -1548,7 +1550,8 @@ fn unify_function_or_tag_union_and_func( new_tags.insert( tag_name.clone(), - subs.get_subs_slice(function_arguments).to_owned(), + subs.get_subs_slice(*function_arguments.as_subs_slice()) + .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 4c1f0d7064..16822acb39 100644 --- a/editor/src/lang/solve.rs +++ b/editor/src/lang/solve.rs @@ -10,7 +10,8 @@ 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, RecordFields, Subs, SubsSlice, Variable, + Content, Descriptor, FlatType, Mark, OptVariable, Rank, RecordFields, Subs, Variable, + VariableSubsSlice, }; use roc_types::types::{Alias, Category, ErrorType, PatternCategory, RecordField}; use roc_unify::unify::unify; @@ -871,11 +872,7 @@ fn type_to_variable<'a>( 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 arg_vars = VariableSubsSlice::insert_into_subs(subs, new_arg_vars); let ret_var = type_to_variable(arena, mempool, subs, rank, pools, cached, ret_type); let closure_var = @@ -1507,11 +1504,7 @@ fn deep_copy_var_help( 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); + let arg_vars = VariableSubsSlice::insert_into_subs(subs, new_arg_vars); Func(arg_vars, new_closure_var, new_ret_var) }