diff --git a/ast/src/solve_type.rs b/ast/src/solve_type.rs index 2b39c606b3..ce63419a56 100644 --- a/ast/src/solve_type.rs +++ b/ast/src/solve_type.rs @@ -810,17 +810,13 @@ fn type_to_variable<'a>( */ let mut arg_vars = Vec::with_capacity(args.len()); - let mut new_aliases = BumpMap::new_in(arena); - for (arg, arg_type_id) in args.iter(mempool) { + for (_, arg_type_id) in args.iter(mempool) { let arg_type = mempool.get(*arg_type_id); let arg_var = type_to_variable(arena, mempool, subs, rank, pools, cached, arg_type); - let arg_str = arg.as_str(mempool); - - arg_vars.push((roc_module::ident::Lowercase::from(arg_str), arg_var)); - new_aliases.insert(arg_str, arg_var); + arg_vars.push(arg_var); } let arg_vars = AliasVariables::insert_into_subs(subs, arg_vars, []); diff --git a/compiler/module/src/ident.rs b/compiler/module/src/ident.rs index 6f31a28751..57e3c7f18c 100644 --- a/compiler/module/src/ident.rs +++ b/compiler/module/src/ident.rs @@ -29,7 +29,7 @@ impl std::ops::Deref for ModuleName { } /// An uncapitalized identifier, such as a field name or local variable -#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] +#[derive(Clone, Default, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct Lowercase(IdentStr); /// A capitalized identifier, such as a tag name or module name diff --git a/compiler/solve/src/solve.rs b/compiler/solve/src/solve.rs index f7741fcb4a..59fe4f868d 100644 --- a/compiler/solve/src/solve.rs +++ b/compiler/solve/src/solve.rs @@ -100,15 +100,17 @@ impl Pools { } pub fn get_mut(&mut self, rank: Rank) -> &mut Vec { - self.0 - .get_mut(rank.into_usize()) - .unwrap_or_else(|| panic!("Compiler bug: could not find pool at rank {}", rank)) + match self.0.get_mut(rank.into_usize()) { + Some(reference) => reference, + None => panic!("Compiler bug: could not find pool at rank {}", rank), + } } pub fn get(&self, rank: Rank) -> &Vec { - self.0 - .get(rank.into_usize()) - .unwrap_or_else(|| panic!("Compiler bug: could not find pool at rank {}", rank)) + match self.0.get(rank.into_usize()) { + Some(reference) => reference, + None => panic!("Compiler bug: could not find pool at rank {}", rank), + } } pub fn iter(&self) -> std::slice::Iter<'_, Vec> { @@ -628,18 +630,6 @@ fn type_to_var( type_to_variable(subs, rank, pools, &arena, typ) } -/// Abusing existing functions for our purposes -/// this is to put a solved type back into subs -pub fn insert_type_into_subs(subs: &mut Subs, typ: &Type) -> Variable { - let rank = Rank::NONE; - let mut pools = Pools::default(); - - // capacity based on the false hello world program - let arena = bumpalo::Bump::with_capacity(4 * 1024); - - type_to_variable(subs, rank, &mut pools, &arena, typ) -} - fn type_to_variable<'a>( subs: &mut Subs, rank: Rank, @@ -652,14 +642,13 @@ fn type_to_variable<'a>( match typ { Variable(var) => *var, Apply(symbol, args) => { - let mut new_arg_vars = Vec::with_capacity_in(args.len(), arena); + let arg_vars = VariableSubsSlice::reserve_into_subs(subs, args.len()); - for arg in args { + for (i, arg) in (arg_vars.slice.start as usize..).zip(args) { let var = type_to_variable(subs, rank, pools, arena, arg); - new_arg_vars.push(var); + subs.variables[i] = var; } - let arg_vars = VariableSubsSlice::insert_into_subs(subs, new_arg_vars); let flat_type = FlatType::Apply(*symbol, arg_vars); let content = Content::Structure(flat_type); @@ -669,16 +658,14 @@ fn type_to_variable<'a>( EmptyTagUnion => Variable::EMPTY_TAG_UNION, // This case is important for the rank of boolean variables - Function(arg_vars, closure_type, ret_type) => { - let mut new_arg_vars = Vec::with_capacity_in(arg_vars.len(), arena); + Function(args, closure_type, ret_type) => { + let arg_vars = VariableSubsSlice::reserve_into_subs(subs, args.len()); - for arg in arg_vars { + for (i, arg) in (arg_vars.slice.start as usize..).zip(args) { let var = type_to_variable(subs, rank, pools, arena, arg); - new_arg_vars.push(var); + subs.variables[i] = var; } - let arg_vars = VariableSubsSlice::insert_into_subs(subs, new_arg_vars); - let ret_var = type_to_variable(subs, rank, pools, arena, ret_type); let closure_var = type_to_variable(subs, rank, pools, arena, closure_type); let content = Content::Structure(FlatType::Func(arg_vars, closure_var, ret_var)); @@ -801,10 +788,10 @@ fn type_to_variable<'a>( let mut arg_vars = Vec::with_capacity_in(args.len(), arena); - for (arg, arg_type) in args { + for (_, arg_type) in args { let arg_var = type_to_variable(subs, rank, pools, arena, arg_type); - arg_vars.push((arg.clone(), arg_var)); + arg_vars.push(arg_var); } let lambda_set_variables_it = lambda_set_variables @@ -829,10 +816,10 @@ fn type_to_variable<'a>( } => { let mut arg_vars = Vec::with_capacity_in(args.len(), arena); - for (arg, arg_type) in args { + for (_, arg_type) in args { let arg_var = type_to_variable(subs, rank, pools, arena, arg_type); - arg_vars.push((arg.clone(), arg_var)); + arg_vars.push(arg_var); } let lambda_set_variables_it = lambda_set_variables @@ -884,14 +871,13 @@ fn type_to_union_tags<'a>( let mut tag_vars = Vec::with_capacity_in(tags.len(), arena); - let mut tag_argument_vars = Vec::with_capacity_in(tags.len(), arena); for (tag, tag_argument_types) in tags { - for arg_type in tag_argument_types { - let new_var = type_to_variable(subs, rank, pools, arena, arg_type); - tag_argument_vars.push(new_var); - } + let new_slice = VariableSubsSlice::reserve_into_subs(subs, tag_argument_types.len()); - let new_slice = VariableSubsSlice::insert_into_subs(subs, tag_argument_vars.drain(..)); + for (i, arg) in (new_slice.slice.start as usize..).zip(tag_argument_types) { + let var = type_to_variable(subs, rank, pools, arena, arg); + subs.variables[i] = var; + } tag_vars.push((tag.clone(), new_slice)); } @@ -1654,12 +1640,14 @@ fn deep_copy_var_help( } fn register(subs: &mut Subs, rank: Rank, pools: &mut Pools, content: Content) -> Variable { - let var = subs.fresh(Descriptor { + let descriptor = Descriptor { content, rank, mark: Mark::NONE, copy: OptVariable::NONE, - }); + }; + + let var = subs.fresh(descriptor); pools.get_mut(rank).push(var); diff --git a/compiler/types/src/pretty_print.rs b/compiler/types/src/pretty_print.rs index 23576b9af3..dbfed01a18 100644 --- a/compiler/types/src/pretty_print.rs +++ b/compiler/types/src/pretty_print.rs @@ -199,7 +199,7 @@ fn find_names_needed( } Alias(_symbol, args, _actual) => { // only find names for named parameters! - for var_index in args.variables().into_iter().take(args.len()) { + for var_index in args.into_iter().take(args.len()) { let var = subs[var_index]; find_names_needed(var, subs, roots, root_appearances, names_taken); } @@ -309,7 +309,6 @@ fn write_content(env: &Env, content: &Content, subs: &Subs, buf: &mut String, pa debug_assert_eq!(args.len(), 1); let arg_var_index = args - .variables() .into_iter() .next() .expect("Num was not applied to a type argument!"); @@ -337,7 +336,7 @@ fn write_content(env: &Env, content: &Content, subs: &Subs, buf: &mut String, pa _ => write_parens!(write_parens, buf, { write_symbol(env, *symbol, buf); - for var_index in args.variables() { + for var_index in args.into_iter() { let var = subs[var_index]; buf.push(' '); write_content( diff --git a/compiler/types/src/solved_types.rs b/compiler/types/src/solved_types.rs index 5173dc43af..2473597a35 100644 --- a/compiler/types/src/solved_types.rs +++ b/compiler/types/src/solved_types.rs @@ -229,7 +229,7 @@ impl SolvedType { } } - pub fn from_var(subs: &Subs, var: Variable) -> Self { + fn from_var(subs: &Subs, var: Variable) -> Self { let mut seen = RecursionVars::default(); Self::from_var_help(subs, &mut seen, var) } @@ -254,16 +254,17 @@ impl SolvedType { Alias(symbol, args, actual_var) => { let mut new_args = Vec::with_capacity(args.len()); - for (name_index, var_index) in args.named_type_arguments() { + for var_index in args.named_type_arguments() { let arg_var = subs[var_index]; - new_args.push(( - subs[name_index].clone(), - Self::from_var_help(subs, recursion_vars, arg_var), - )); + let node = Self::from_var_help(subs, recursion_vars, arg_var); + + // NOTE we fake the lowercase here: the user will never get to see it anyway + new_args.push((Lowercase::default(), node)); } let mut solved_lambda_sets = Vec::with_capacity(0); + for var_index in args.unnamed_type_arguments() { let var = subs[var_index]; diff --git a/compiler/types/src/subs.rs b/compiler/types/src/subs.rs index 1ee1bcfc0e..abceb92e63 100644 --- a/compiler/types/src/subs.rs +++ b/compiler/types/src/subs.rs @@ -797,7 +797,7 @@ fn integer_type( Content::Structure(FlatType::TagUnion(tags, Variable::EMPTY_TAG_UNION)) }); - let vars = AliasVariables::insert_into_subs(subs, [("range".into(), signed64)], []); + let vars = AliasVariables::insert_into_subs(subs, [signed64], []); subs.set_content(num_integer_signed64, { Content::Alias(Symbol::NUM_INTEGER, vars, at_signed64) }); @@ -812,7 +812,7 @@ fn integer_type( Content::Structure(FlatType::TagUnion(tags, Variable::EMPTY_TAG_UNION)) }); - let vars = AliasVariables::insert_into_subs(subs, [("range".into(), integer_signed64)], []); + let vars = AliasVariables::insert_into_subs(subs, [integer_signed64], []); subs.set_content(num_integer_signed64, { Content::Alias(Symbol::NUM_NUM, vars, at_num_integer_signed64) }); @@ -1358,7 +1358,7 @@ impl From for Descriptor { static_assertions::assert_eq_size!([u8; 4 * 8], Content); static_assertions::assert_eq_size!([u8; 4 * 8], (Variable, Option)); static_assertions::assert_eq_size!([u8; 3 * 8], (Symbol, AliasVariables, Variable)); -static_assertions::assert_eq_size!([u8; 12], AliasVariables); +static_assertions::assert_eq_size!([u8; 8], AliasVariables); static_assertions::assert_eq_size!([u8; 3 * 8], FlatType); #[derive(Clone, Debug)] @@ -1382,29 +1382,26 @@ pub enum Content { #[derive(Clone, Copy, Debug, Default)] pub struct AliasVariables { - pub lowercases_start: u32, pub variables_start: u32, - pub lowercases_len: u16, - pub variables_len: u16, + pub all_variables_len: u16, + + /// an alias has type variables and lambda set variables + pub type_variables_len: u16, } impl AliasVariables { - pub const fn names(&self) -> SubsSlice { - SubsSlice::new(self.lowercases_start, self.lowercases_len) - } - pub const fn variables(&self) -> VariableSubsSlice { VariableSubsSlice { - slice: SubsSlice::new(self.variables_start, self.variables_len), + slice: SubsSlice::new(self.variables_start, self.all_variables_len), } } pub const fn len(&self) -> usize { - self.lowercases_len as usize + self.type_variables_len as usize } pub const fn is_empty(&self) -> bool { - self.lowercases_len == 0 + self.type_variables_len == 0 } pub fn replace_variables( @@ -1416,24 +1413,21 @@ impl AliasVariables { subs.variables.extend(variables); let variables_len = (subs.variables.len() - variables_start as usize) as u16; - debug_assert_eq!(variables_len, self.variables_len); + debug_assert_eq!(variables_len, self.all_variables_len); self.variables_start = variables_start; } - pub fn named_type_arguments( - &self, - ) -> impl Iterator, SubsIndex)> { - let names = self.names(); - let vars = self.variables(); - - names.into_iter().zip(vars.into_iter()) + pub fn named_type_arguments(&self) -> impl Iterator> { + self.variables() + .into_iter() + .take(self.type_variables_len as usize) } pub fn unnamed_type_arguments(&self) -> impl Iterator> { self.variables() .into_iter() - .skip(self.lowercases_len as usize) + .skip(self.type_variables_len as usize) } pub fn insert_into_subs( @@ -1442,38 +1436,41 @@ impl AliasVariables { unnamed_arguments: I2, ) -> Self where - I1: IntoIterator, + I1: IntoIterator, I2: IntoIterator, { - let lowercases_start = subs.field_names.len() as u32; let variables_start = subs.variables.len() as u32; - let it1 = type_arguments.into_iter(); - let it2 = unnamed_arguments.into_iter(); + subs.variables.extend(type_arguments); - subs.variables - .reserve(it1.size_hint().0 + it2.size_hint().0); - subs.field_names.reserve(it1.size_hint().0); + let type_variables_len = (subs.variables.len() as u32 - variables_start) as u16; - for (field_name, var) in it1 { - subs.field_names.push(field_name); - subs.variables.push(var); + subs.variables.extend(unnamed_arguments); + + let all_variables_len = (subs.variables.len() as u32 - variables_start) as u16; + + if type_variables_len == 3 { + panic!(); } - subs.variables.extend(it2); - - let lowercases_len = (subs.field_names.len() as u32 - lowercases_start) as u16; - let variables_len = (subs.variables.len() as u32 - variables_start) as u16; - Self { - lowercases_start, variables_start, - lowercases_len, - variables_len, + type_variables_len, + all_variables_len, } } } +impl IntoIterator for AliasVariables { + type Item = ::Item; + + type IntoIter = ::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + self.variables().into_iter() + } +} + impl Content { #[inline(always)] pub fn is_number(&self) -> bool { @@ -1548,6 +1545,15 @@ impl VariableSubsSlice { } } + pub fn reserve_into_subs(subs: &mut Subs, length: usize) -> Self { + let start = subs.variables.len() as u32; + + subs.variables + .extend(std::iter::repeat(Variable::NULL).take(length)); + + Self::new(start, length as u16) + } + pub fn insert_into_subs(subs: &mut Subs, input: I) -> Self where I: IntoIterator, @@ -2081,7 +2087,7 @@ fn occurs( let mut new_seen = seen.clone(); new_seen.insert(root_var); - for var_index in args.variables().into_iter() { + for var_index in args.into_iter() { let var = subs[var_index]; short_circuit_help(subs, root_var, &new_seen, var)?; } @@ -2265,7 +2271,7 @@ fn explicit_substitute( in_var } Alias(symbol, args, actual) => { - for index in args.variables().into_iter() { + for index in args.into_iter() { let var = subs[index]; let new_var = explicit_substitute(subs, from, to, var, seen); subs[index] = new_var; @@ -2322,12 +2328,9 @@ fn get_var_names( RigidVar(name) => add_name(subs, 0, name, var, RigidVar, taken_names), - Alias(_, args, _) => args - .variables() - .into_iter() - .fold(taken_names, |answer, arg_var| { - get_var_names(subs, subs[arg_var], answer) - }), + Alias(_, args, _) => args.into_iter().fold(taken_names, |answer, arg_var| { + get_var_names(subs, subs[arg_var], answer) + }), Structure(flat_type) => match flat_type { FlatType::Apply(_, args) => { @@ -2528,15 +2531,14 @@ fn content_to_err_type( Alias(symbol, args, aliased_to) => { let err_type = var_to_err_type(subs, state, aliased_to); - let mut err_args = Vec::with_capacity(args.names().len()); + let mut err_args = Vec::with_capacity(args.len()); - for (name_index, var_index) in args.named_type_arguments() { - let name = subs[name_index].clone(); + for var_index in args.into_iter() { let var = subs[var_index]; let arg = var_to_err_type(subs, state, var); - err_args.push((name, arg)); + err_args.push(arg); } ErrorType::Alias(symbol, err_args, Box::new(err_type)) @@ -2989,7 +2991,6 @@ impl StorageSubs { offsets: &StorageSubsOffsets, mut alias_variables: AliasVariables, ) -> AliasVariables { - alias_variables.lowercases_start += offsets.field_names; alias_variables.variables_start += offsets.variables; alias_variables @@ -3357,9 +3358,9 @@ fn deep_copy_var_to_help<'a>( } Alias(symbol, mut args, real_type_var) => { - let mut new_vars = Vec::with_capacity_in(args.variables().len(), arena); + let mut new_vars = Vec::with_capacity_in(args.len(), arena); - for var_index in args.variables() { + for var_index in args.into_iter() { let var = source[var_index]; let new_var = deep_copy_var_to_help(arena, visited, source, target, max_rank, var); @@ -3368,12 +3369,6 @@ fn deep_copy_var_to_help<'a>( args.replace_variables(target, new_vars); - let lowercases = &source.field_names[args.lowercases_start as usize..] - [..args.lowercases_len as usize]; - - args.lowercases_start = target.field_names.len() as u32; - target.field_names.extend(lowercases.iter().cloned()); - let new_real_type_var = deep_copy_var_to_help(arena, visited, source, target, max_rank, real_type_var); let new_content = Alias(symbol, args, new_real_type_var); diff --git a/compiler/types/src/types.rs b/compiler/types/src/types.rs index 174b49e438..96e0190a43 100644 --- a/compiler/types/src/types.rs +++ b/compiler/types/src/types.rs @@ -1241,7 +1241,7 @@ pub enum ErrorType { TagUnion(SendMap>, TypeExt), RecursiveTagUnion(Box, SendMap>, TypeExt), Function(Vec, Box, Box), - Alias(Symbol, Vec<(Lowercase, ErrorType)>, Box), + Alias(Symbol, Vec, Box), Error, } @@ -1303,7 +1303,7 @@ fn write_error_type_help( Alias(Symbol::NUM_NUM, mut arguments, _actual) => { debug_assert!(arguments.len() == 1); - let argument = arguments.remove(0).1; + let argument = arguments.remove(0); match argument { Type(Symbol::NUM_INTEGER, _) => { @@ -1421,7 +1421,7 @@ fn write_debug_error_type_help(error_type: ErrorType, buf: &mut String, parens: Alias(Symbol::NUM_NUM, mut arguments, _actual) => { debug_assert!(arguments.len() == 1); - let argument = arguments.remove(0).1; + let argument = arguments.remove(0); match argument { Type(Symbol::NUM_INTEGER, _) => { @@ -1456,7 +1456,7 @@ fn write_debug_error_type_help(error_type: ErrorType, buf: &mut String, parens: for arg in arguments { buf.push(' '); - write_debug_error_type_help(arg.1, buf, Parens::InTypeParam); + write_debug_error_type_help(arg, buf, Parens::InTypeParam); } // useful for debugging diff --git a/compiler/unify/src/unify.rs b/compiler/unify/src/unify.rs index f469b0be1c..ff8f51966e 100644 --- a/compiler/unify/src/unify.rs +++ b/compiler/unify/src/unify.rs @@ -209,7 +209,8 @@ fn unify_alias( problems } else { - mismatch!("{}", symbol) + dbg!(args.len(), other_args.len()); + mismatch!("{:?}", symbol) } } else { unify_pool(subs, pool, real_var, *other_real_var) diff --git a/editor/src/editor/main.rs b/editor/src/editor/main.rs index cc27fb2848..e94412d628 100644 --- a/editor/src/editor/main.rs +++ b/editor/src/editor/main.rs @@ -471,12 +471,7 @@ fn read_main_roc_file(project_dir_path_opt: Option<&Path>) -> (PathStr, String) let project_dir_path_str = path_to_string(project_dir_path); if let Some(&roc_file_name) = roc_file_names.first() { - let full_roc_file_path_str = vec![ - project_dir_path_str.clone(), - "/".to_owned(), - roc_file_name.clone(), - ] - .join(""); + let full_roc_file_path_str = path_to_string(&project_dir_path.join(roc_file_name)); let file_as_str = std::fs::read_to_string(&Path::new(&full_roc_file_path_str)) .unwrap_or_else(|err| panic!("In the provided project {:?}, I found the roc file {}, but I failed to read it: {}", &project_dir_path_str, &full_roc_file_path_str, err)); diff --git a/reporting/src/error/type.rs b/reporting/src/error/type.rs index f80f3b63c9..d8745a1a9c 100644 --- a/reporting/src/error/type.rs +++ b/reporting/src/error/type.rs @@ -1493,7 +1493,7 @@ pub fn to_doc<'b>( parens, alloc.symbol_foreign_qualified(symbol), args.into_iter() - .map(|(_, arg)| to_doc(alloc, Parens::InTypeParam, arg)) + .map(|arg| to_doc(alloc, Parens::InTypeParam, arg)) .collect(), ), @@ -1657,10 +1657,7 @@ fn to_diff<'b>( } (Alias(symbol1, args1, _), Alias(symbol2, args2, _)) if symbol1 == symbol2 => { - // TODO remove collects - let a1 = args1.into_iter().map(|(_, v)| v).collect::>(); - let a2 = args2.into_iter().map(|(_, v)| v).collect::>(); - let args_diff = traverse(alloc, Parens::InTypeParam, a1, a2); + let args_diff = traverse(alloc, Parens::InTypeParam, args1, args2); let left = report_text::apply( alloc, parens, @@ -1729,8 +1726,8 @@ fn to_diff<'b>( ErrorType::Alias(Symbol::NUM_NUM, args, _) => { matches!( &args.get(0), - Some((_, ErrorType::Type(Symbol::NUM_INTEGER, _))) - | Some((_, ErrorType::Alias(Symbol::NUM_INTEGER, _, _))) + Some(ErrorType::Type(Symbol::NUM_INTEGER, _)) + | Some(ErrorType::Alias(Symbol::NUM_INTEGER, _, _)) ) } _ => false, @@ -1750,8 +1747,8 @@ fn to_diff<'b>( ErrorType::Alias(Symbol::NUM_NUM, args, _) => { matches!( &args.get(0), - Some((_, ErrorType::Type(Symbol::NUM_FLOATINGPOINT, _))) - | Some((_, ErrorType::Alias(Symbol::NUM_FLOATINGPOINT, _, _))) + Some(ErrorType::Type(Symbol::NUM_FLOATINGPOINT, _)) + | Some(ErrorType::Alias(Symbol::NUM_FLOATINGPOINT, _, _)) ) } _ => false,