diff --git a/compiler/mono/src/ir.rs b/compiler/mono/src/ir.rs index 3f791837a9..d3ceaa9ef5 100644 --- a/compiler/mono/src/ir.rs +++ b/compiler/mono/src/ir.rs @@ -16,7 +16,7 @@ use roc_problem::can::RuntimeError; use roc_region::all::{Located, Region}; use roc_std::RocDec; use roc_types::solved_types::SolvedType; -use roc_types::subs::{Content, FlatType, Subs, Variable, VariableSubsSlice}; +use roc_types::subs::{Content, FlatType, StorageSubs, Subs, Variable, VariableSubsSlice}; use std::collections::HashMap; use ven_pretty::{BoxAllocator, DocAllocator, DocBuilder}; @@ -437,7 +437,7 @@ impl<'a> ExternalSpecializations<'a> { fn insert_external(&mut self, symbol: Symbol, env_subs: &mut Subs, variable: Variable) { let variable = - roc_solve::solve::deep_copy_var_to(env_subs, &mut self.storage_subs, variable); + roc_types::subs::deep_copy_var_to(env_subs, &mut self.storage_subs, variable); match self.symbols.iter().position(|s| *s == symbol) { None => { @@ -468,7 +468,7 @@ impl<'a> ExternalSpecializations<'a> { #[derive(Clone, Debug)] pub struct Suspended<'a> { - pub store: Subs, + pub store: StorageSubs, pub symbols: Vec<'a, Symbol>, pub layouts: Vec<'a, ProcLayout<'a>>, pub variables: Vec<'a, Variable>, @@ -477,7 +477,7 @@ pub struct Suspended<'a> { impl<'a> Suspended<'a> { fn new_in(arena: &'a Bump) -> Self { Self { - store: Subs::new_from_varstore(Default::default()), + store: StorageSubs::new(Subs::new_from_varstore(Default::default())), symbols: Vec::new_in(arena), layouts: Vec::new_in(arena), variables: Vec::new_in(arena), @@ -505,7 +505,7 @@ impl<'a> Suspended<'a> { self.symbols.push(symbol); self.layouts.push(proc_layout); - let variable = roc_solve::solve::deep_copy_var_to(subs, &mut self.store, variable); + let variable = self.store.extend_with_variable(subs, variable); self.variables.push(variable); } @@ -1908,20 +1908,20 @@ pub fn specialize_all<'a>( match pending_specializations { PendingSpecializations::Making => {} - PendingSpecializations::Finding(mut suspended) => { - // TODO can we copy everything over in one pass (bumping variables by however many - // variables are in the env's subs? - for var in suspended.variables.iter_mut() { - debug_assert!((var.index() as usize) < suspended.store.len()); + PendingSpecializations::Finding(suspended) => { + let offset_variable = StorageSubs::merge_into(suspended.store, env.subs); - *var = roc_solve::solve::deep_copy_var_to(&mut suspended.store, env.subs, *var); - } - - for (i, symbol) in suspended.symbols.iter().enumerate() { + for (i, (symbol, var)) in suspended + .symbols + .iter() + .zip(suspended.variables.iter()) + .enumerate() + { let name = *symbol; - let var = suspended.variables[i]; let outside_layout = suspended.layouts[i]; + let var = offset_variable(*var); + // TODO define our own Entry for Specialized? let partial_proc = if procs.specialized.is_specialized(name, &outside_layout) { // already specialized, just continue @@ -2069,7 +2069,7 @@ fn specialize_externals_others_need<'a>( }; let variable = - roc_solve::solve::deep_copy_var_to(&mut store, env.subs, store_variable); + roc_types::subs::deep_copy_var_to(&mut store, env.subs, store_variable); // TODO I believe this is also duplicated match specialize_variable( diff --git a/compiler/solve/src/solve.rs b/compiler/solve/src/solve.rs index a72c36d4a7..8c92222966 100644 --- a/compiler/solve/src/solve.rs +++ b/compiler/solve/src/solve.rs @@ -1383,346 +1383,6 @@ fn instantiate_rigids_help( var } -pub fn deep_copy_var_to( - source: &mut Subs, // mut to set the copy - target: &mut Subs, - var: Variable, -) -> Variable { - let mut pools = Pools::default(); - let rank = Rank::toplevel(); - - let mut mapping = Vec::with_capacity(100); - - let copy = deep_copy_var_to_help(source, target, rank, &mut pools, &mut mapping, var); - - source.restore(var); - - copy -} - -fn deep_copy_var_to_help( - // source: &mut Subs, // mut to set the copy - source: &mut Subs, - target: &mut Subs, - max_rank: Rank, - pools: &mut Pools, - mapping: &mut Vec, // maps copies in the source to copies in the target - var: Variable, -) -> Variable { - use roc_types::subs::Content::*; - use roc_types::subs::FlatType::*; - - let desc = source.get_without_compacting(var); - - if let Some(copy) = desc.copy.into_variable() { - debug_assert!(target.contains(copy)); - return copy; - } else if desc.rank != Rank::NONE { - // DO NOTHING - // - // The original deep_copy_var can do - // return var; - // - // but we cannot, because this `var` is in the source, not the target, and we - // should only return variables in the target - } - - let make_descriptor = |content| Descriptor { - content, - rank: max_rank, - mark: Mark::NONE, - copy: OptVariable::NONE, - }; - - let content = desc.content; - // let copy = target.fresh(make_descriptor(content.clone())); - let copy = target.fresh_unnamed_flex_var(); - - // pools.get_mut(max_rank).push(copy); - - // Link the original variable to the new variable. This lets us - // avoid making multiple copies of the variable we are instantiating. - // - // Need to do this before recursively copying to avoid looping. - - source.set( - var, - Descriptor { - content: content.clone(), - rank: desc.rank, - mark: Mark::NONE, - copy: copy.into(), - }, - ); - - // Now we recursively copy the content of the variable. - // We have already marked the variable as copied, so we - // 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 mut new_arg_vars = Vec::with_capacity(args.len()); - - for index in args.into_iter() { - let var = source[index]; - let copy_var = - deep_copy_var_to_help(source, target, max_rank, pools, mapping, var); - new_arg_vars.push(copy_var); - } - - let arg_vars = VariableSubsSlice::insert_into_subs(target, new_arg_vars); - - Apply(symbol, arg_vars) - } - - Func(arg_vars, closure_var, ret_var) => { - let new_ret_var = - deep_copy_var_to_help(source, target, max_rank, pools, mapping, ret_var); - - let new_closure_var = deep_copy_var_to_help( - source, - target, - max_rank, - pools, - mapping, - closure_var, - ); - - let mut new_arg_vars = Vec::with_capacity(arg_vars.len()); - - for index in arg_vars.into_iter() { - let var = source[index]; - let copy_var = - deep_copy_var_to_help(source, target, max_rank, pools, mapping, var); - new_arg_vars.push(copy_var); - } - - let arg_vars = VariableSubsSlice::insert_into_subs(target, new_arg_vars); - - Func(arg_vars, new_closure_var, new_ret_var) - } - - same @ EmptyRecord | same @ EmptyTagUnion | same @ Erroneous(_) => same, - - Record(fields, ext_var) => { - let record_fields = { - let mut new_vars = Vec::with_capacity(fields.len()); - - for index in fields.iter_variables() { - let var = source[index]; - let copy_var = deep_copy_var_to_help( - source, target, max_rank, pools, mapping, var, - ); - - new_vars.push(copy_var); - } - - let field_names_start = target.field_names.len() as u32; - let variables_start = target.variables.len() as u32; - let field_types_start = target.record_fields.len() as u32; - - let mut length = 0; - - for ((i1, _, i3), var) in fields.iter_all().zip(new_vars) { - let record_field = source[i3].map(|_| var); - - target.field_names.push(source[i1].clone()); - target.record_fields.push(record_field.map(|_| ())); - target.variables.push(*record_field.as_inner()); - - length += 1; - } - - RecordFields { - length, - field_names_start, - variables_start, - field_types_start, - } - }; - - Record( - record_fields, - deep_copy_var_to_help(source, target, max_rank, pools, mapping, ext_var), - ) - } - - TagUnion(tags, ext_var) => { - let new_ext = - deep_copy_var_to_help(source, target, max_rank, pools, mapping, ext_var); - - let mut new_variable_slices = Vec::with_capacity(tags.len()); - - let mut new_variables = Vec::new(); - for index in tags.variables() { - let slice = source[index]; - for var_index in slice { - let var = source[var_index]; - let new_var = deep_copy_var_to_help( - source, target, max_rank, pools, mapping, var, - ); - new_variables.push(new_var); - } - - let new_slice = - VariableSubsSlice::insert_into_subs(target, new_variables.drain(..)); - - new_variable_slices.push(new_slice); - } - - let new_variables = { - let start = target.variable_slices.len() as u32; - let length = new_variable_slices.len() as u16; - target.variable_slices.extend(new_variable_slices); - - SubsSlice::new(start, length) - }; - - let new_tag_names = { - let tag_names = tags.tag_names(); - let slice = &source.tag_names[tag_names.start as usize..] - [..tag_names.length as usize]; - - let start = target.tag_names.len() as u32; - let length = tag_names.len() as u16; - - target.tag_names.extend(slice.iter().cloned()); - - SubsSlice::new(start, length) - }; - - let union_tags = UnionTags::from_slices(new_tag_names, new_variables); - - TagUnion(union_tags, new_ext) - } - - FunctionOrTagUnion(tag_name, symbol, ext_var) => { - let new_tag_name = SubsIndex::new(target.tag_names.len() as u32); - - target.tag_names.push(source[tag_name].clone()); - - FunctionOrTagUnion( - new_tag_name, - symbol, - deep_copy_var_to_help(source, target, max_rank, pools, mapping, ext_var), - ) - } - - RecursiveTagUnion(rec_var, tags, ext_var) => { - let mut new_variable_slices = Vec::with_capacity(tags.len()); - - let mut new_variables = Vec::new(); - for index in tags.variables() { - let slice = source[index]; - for var_index in slice { - let var = source[var_index]; - let new_var = deep_copy_var_to_help( - source, target, max_rank, pools, mapping, var, - ); - new_variables.push(new_var); - } - - let new_slice = - VariableSubsSlice::insert_into_subs(target, new_variables.drain(..)); - - new_variable_slices.push(new_slice); - } - - let new_variables = { - let start = target.variable_slices.len() as u32; - let length = new_variable_slices.len() as u16; - target.variable_slices.extend(new_variable_slices); - - SubsSlice::new(start, length) - }; - - let new_tag_names = { - let tag_names = tags.tag_names(); - let slice = &source.tag_names[tag_names.start as usize..] - [..tag_names.length as usize]; - - let start = target.tag_names.len() as u32; - let length = tag_names.len() as u16; - - target.tag_names.extend(slice.iter().cloned()); - - SubsSlice::new(start, length) - }; - - let union_tags = UnionTags::from_slices(new_tag_names, new_variables); - - let new_ext = - deep_copy_var_to_help(source, target, max_rank, pools, mapping, ext_var); - let new_rec_var = - deep_copy_var_to_help(source, target, max_rank, pools, mapping, rec_var); - - RecursiveTagUnion(new_rec_var, union_tags, new_ext) - } - }; - - target.set(copy, make_descriptor(Structure(new_flat_type))); - - copy - } - - FlexVar(_) | Error => copy, - - RecursionVar { - opt_name, - structure, - } => { - let new_structure = - deep_copy_var_to_help(source, target, max_rank, pools, mapping, structure); - - debug_assert!((new_structure.index() as usize) < target.len()); - - target.set( - copy, - make_descriptor(RecursionVar { - opt_name, - structure: new_structure, - }), - ); - - copy - } - - RigidVar(name) => { - target.set(copy, make_descriptor(FlexVar(Some(name)))); - - copy - } - - Alias(symbol, mut args, real_type_var) => { - let mut new_vars = Vec::with_capacity(args.variables().len()); - - for var_index in args.variables() { - let var = source[var_index]; - let new_var = deep_copy_var_to_help(source, target, max_rank, pools, mapping, var); - - new_vars.push(new_var); - } - - 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(source, target, max_rank, pools, mapping, real_type_var); - let new_content = Alias(symbol, args, new_real_type_var); - - target.set(copy, make_descriptor(new_content)); - - copy - } - } -} - fn deep_copy_var(subs: &mut Subs, rank: Rank, pools: &mut Pools, var: Variable) -> Variable { let copy = deep_copy_var_help(subs, rank, pools, var); diff --git a/compiler/types/src/subs.rs b/compiler/types/src/subs.rs index 105c135b9f..4aaaf28abb 100644 --- a/compiler/types/src/subs.rs +++ b/compiler/types/src/subs.rs @@ -1051,6 +1051,7 @@ impl Subs { } pub fn extend_by(&mut self, entries: usize) { + self.utable.reserve(entries); for _ in 0..entries { self.utable.new_key(flex_var_descriptor()); } @@ -2801,11 +2802,12 @@ fn restore_help(subs: &mut Subs, initial: Variable) { } } -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct StorageSubs { subs: Subs, } +#[derive(Copy, Clone, Debug)] struct StorageSubsOffsets { utable: u32, variables: u32, @@ -2816,7 +2818,24 @@ struct StorageSubsOffsets { } impl StorageSubs { - pub fn merge_into(self, target: &mut Subs) { + pub fn new(subs: Subs) -> Self { + Self { subs } + } + + pub fn extend_with_variable(&mut self, source: &mut Subs, variable: Variable) -> Variable { + deep_copy_var_to(source, &mut self.subs, variable) + } + + pub fn merge_into(self, target: &mut Subs) -> impl Fn(Variable) -> Variable { + let self_offsets = StorageSubsOffsets { + utable: self.subs.utable.len() as u32, + variables: self.subs.variables.len() as u32, + tag_names: self.subs.tag_names.len() as u32, + field_names: self.subs.field_names.len() as u32, + record_fields: self.subs.record_fields.len() as u32, + variable_slices: self.subs.variable_slices.len() as u32, + }; + let offsets = StorageSubsOffsets { utable: target.utable.len() as u32, variables: target.variables.len() as u32, @@ -2826,33 +2845,36 @@ impl StorageSubs { variable_slices: target.variable_slices.len() as u32, }; - let range = Variable::NUM_RESERVED_VARS..self.subs.utable.len(); + let range = 0..self.subs.utable.len(); - target.utable.reserve(range.len()); + // fill new slots with empty values + target.extend_by(range.len()); for i in range { - let descriptor = self.subs.get_ref(Variable(i as u32)); + let variable = Variable(i as u32); + let descriptor = self.subs.get_ref(variable); debug_assert!(descriptor.copy.is_none()); let new_content = Self::offset_content(&offsets, &descriptor.content); - let new_variable = Variable(i as u32 + offsets.utable); - let new_descriptor = Descriptor { rank: descriptor.rank, mark: descriptor.mark, + // rank: Rank::NONE, + // mark: Mark::NONE, copy: OptVariable::NONE, content: new_content, }; + let new_variable = Self::offset_variable(&offsets, variable); target.set(new_variable, new_descriptor); } target.variables.extend( self.subs .variables - .into_iter() - .map(|v| Self::offset_variable(&offsets, v)), + .iter() + .map(|v| Self::offset_variable(&offsets, *v)), ); target.variable_slices.extend( @@ -2865,6 +2887,21 @@ impl StorageSubs { target.tag_names.extend(self.subs.tag_names); target.field_names.extend(self.subs.field_names); target.record_fields.extend(self.subs.record_fields); + + debug_assert_eq!( + target.utable.len(), + (self_offsets.utable + offsets.utable) as usize + ); + + debug_assert_eq!( + target.tag_names.len(), + (self_offsets.tag_names + offsets.tag_names) as usize + ); + + move |v| { + let offsets = offsets; + Self::offset_variable(&offsets, v) + } } fn offset_flat_type(offsets: &StorageSubsOffsets, flat_type: &FlatType) -> FlatType { match flat_type { @@ -2935,7 +2972,7 @@ impl StorageSubs { fn offset_union_tags(offsets: &StorageSubsOffsets, mut union_tags: UnionTags) -> UnionTags { union_tags.tag_names_start += offsets.tag_names; - union_tags.variables_start += offsets.variables; + union_tags.variables_start += offsets.variable_slices; union_tags } @@ -2961,19 +2998,331 @@ impl StorageSubs { } fn offset_variable(offsets: &StorageSubsOffsets, variable: Variable) -> Variable { - if variable.index() < Variable::FIRST_USER_SPACE_VAR.index() { - variable - } else { - Variable(variable.0 + offsets.variables) - } + let new_index = variable.0 + offsets.utable; + Variable(new_index) } fn offset_variable_slice( offsets: &StorageSubsOffsets, mut slice: VariableSubsSlice, ) -> VariableSubsSlice { - slice.slice.start += offsets.variable_slices; + slice.slice.start += offsets.variables; slice } } + +pub fn deep_copy_var_to( + source: &mut Subs, // mut to set the copy + target: &mut Subs, + var: Variable, +) -> Variable { + let rank = Rank::toplevel(); + + let copy = deep_copy_var_to_help(source, target, rank, var); + + source.restore(var); + + copy +} + +fn deep_copy_var_to_help( + // source: &mut Subs, // mut to set the copy + source: &mut Subs, + target: &mut Subs, + max_rank: Rank, + var: Variable, +) -> Variable { + use Content::*; + use FlatType::*; + + let desc = source.get_without_compacting(var); + + if let Some(copy) = desc.copy.into_variable() { + debug_assert!(target.contains(copy)); + return copy; + } else if desc.rank != Rank::NONE { + // DO NOTHING + // + // The original deep_copy_var can do + // return var; + // + // but we cannot, because this `var` is in the source, not the target, and we + // should only return variables in the target + } + + let make_descriptor = |content| Descriptor { + content, + rank: max_rank, + mark: Mark::NONE, + copy: OptVariable::NONE, + }; + + let content = desc.content; + // let copy = target.fresh(make_descriptor(content.clone())); + let copy = target.fresh_unnamed_flex_var(); + + // pools.get_mut(max_rank).push(copy); + + // Link the original variable to the new variable. This lets us + // avoid making multiple copies of the variable we are instantiating. + // + // Need to do this before recursively copying to avoid looping. + + source.set( + var, + Descriptor { + content: content.clone(), + rank: desc.rank, + mark: Mark::NONE, + copy: copy.into(), + }, + ); + + // Now we recursively copy the content of the variable. + // We have already marked the variable as copied, so we + // 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 mut new_arg_vars = Vec::with_capacity(args.len()); + + for index in args.into_iter() { + let var = source[index]; + let copy_var = deep_copy_var_to_help(source, target, max_rank, var); + new_arg_vars.push(copy_var); + } + + let arg_vars = VariableSubsSlice::insert_into_subs(target, new_arg_vars); + + Apply(symbol, arg_vars) + } + + Func(arg_vars, closure_var, ret_var) => { + let new_ret_var = deep_copy_var_to_help(source, target, max_rank, ret_var); + + let new_closure_var = + deep_copy_var_to_help(source, target, max_rank, closure_var); + + let mut new_arg_vars = Vec::with_capacity(arg_vars.len()); + + for index in arg_vars.into_iter() { + let var = source[index]; + let copy_var = deep_copy_var_to_help(source, target, max_rank, var); + new_arg_vars.push(copy_var); + } + + let arg_vars = VariableSubsSlice::insert_into_subs(target, new_arg_vars); + + Func(arg_vars, new_closure_var, new_ret_var) + } + + same @ EmptyRecord | same @ EmptyTagUnion | same @ Erroneous(_) => same, + + Record(fields, ext_var) => { + let record_fields = { + let mut new_vars = Vec::with_capacity(fields.len()); + + for index in fields.iter_variables() { + let var = source[index]; + let copy_var = deep_copy_var_to_help(source, target, max_rank, var); + + new_vars.push(copy_var); + } + + let field_names_start = target.field_names.len() as u32; + let variables_start = target.variables.len() as u32; + let field_types_start = target.record_fields.len() as u32; + + let mut length = 0; + + for ((i1, _, i3), var) in fields.iter_all().zip(new_vars) { + let record_field = source[i3].map(|_| var); + + target.field_names.push(source[i1].clone()); + target.record_fields.push(record_field.map(|_| ())); + target.variables.push(*record_field.as_inner()); + + length += 1; + } + + RecordFields { + length, + field_names_start, + variables_start, + field_types_start, + } + }; + + Record( + record_fields, + deep_copy_var_to_help(source, target, max_rank, ext_var), + ) + } + + TagUnion(tags, ext_var) => { + let new_ext = deep_copy_var_to_help(source, target, max_rank, ext_var); + + let mut new_variable_slices = Vec::with_capacity(tags.len()); + + let mut new_variables = Vec::new(); + for index in tags.variables() { + let slice = source[index]; + for var_index in slice { + let var = source[var_index]; + let new_var = deep_copy_var_to_help(source, target, max_rank, var); + new_variables.push(new_var); + } + + let new_slice = + VariableSubsSlice::insert_into_subs(target, new_variables.drain(..)); + + new_variable_slices.push(new_slice); + } + + let new_variables = { + let start = target.variable_slices.len() as u32; + let length = new_variable_slices.len() as u16; + target.variable_slices.extend(new_variable_slices); + + SubsSlice::new(start, length) + }; + + let new_tag_names = { + let tag_names = tags.tag_names(); + let slice = &source.tag_names[tag_names.start as usize..] + [..tag_names.length as usize]; + + let start = target.tag_names.len() as u32; + let length = tag_names.len() as u16; + + target.tag_names.extend(slice.iter().cloned()); + + SubsSlice::new(start, length) + }; + + let union_tags = UnionTags::from_slices(new_tag_names, new_variables); + + TagUnion(union_tags, new_ext) + } + + FunctionOrTagUnion(tag_name, symbol, ext_var) => { + let new_tag_name = SubsIndex::new(target.tag_names.len() as u32); + + target.tag_names.push(source[tag_name].clone()); + + FunctionOrTagUnion( + new_tag_name, + symbol, + deep_copy_var_to_help(source, target, max_rank, ext_var), + ) + } + + RecursiveTagUnion(rec_var, tags, ext_var) => { + let mut new_variable_slices = Vec::with_capacity(tags.len()); + + let mut new_variables = Vec::new(); + for index in tags.variables() { + let slice = source[index]; + for var_index in slice { + let var = source[var_index]; + let new_var = deep_copy_var_to_help(source, target, max_rank, var); + new_variables.push(new_var); + } + + let new_slice = + VariableSubsSlice::insert_into_subs(target, new_variables.drain(..)); + + new_variable_slices.push(new_slice); + } + + let new_variables = { + let start = target.variable_slices.len() as u32; + let length = new_variable_slices.len() as u16; + target.variable_slices.extend(new_variable_slices); + + SubsSlice::new(start, length) + }; + + let new_tag_names = { + let tag_names = tags.tag_names(); + let slice = &source.tag_names[tag_names.start as usize..] + [..tag_names.length as usize]; + + let start = target.tag_names.len() as u32; + let length = tag_names.len() as u16; + + target.tag_names.extend(slice.iter().cloned()); + + SubsSlice::new(start, length) + }; + + let union_tags = UnionTags::from_slices(new_tag_names, new_variables); + + let new_ext = deep_copy_var_to_help(source, target, max_rank, ext_var); + let new_rec_var = deep_copy_var_to_help(source, target, max_rank, rec_var); + + RecursiveTagUnion(new_rec_var, union_tags, new_ext) + } + }; + + target.set(copy, make_descriptor(Structure(new_flat_type))); + + copy + } + + FlexVar(_) | Error => copy, + + RecursionVar { + opt_name, + structure, + } => { + let new_structure = deep_copy_var_to_help(source, target, max_rank, structure); + + debug_assert!((new_structure.index() as usize) < target.len()); + + target.set( + copy, + make_descriptor(RecursionVar { + opt_name, + structure: new_structure, + }), + ); + + copy + } + + RigidVar(name) => { + target.set(copy, make_descriptor(FlexVar(Some(name)))); + + copy + } + + Alias(symbol, mut args, real_type_var) => { + let mut new_vars = Vec::with_capacity(args.variables().len()); + + for var_index in args.variables() { + let var = source[var_index]; + let new_var = deep_copy_var_to_help(source, target, max_rank, var); + + new_vars.push(new_var); + } + + 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(source, target, max_rank, real_type_var); + let new_content = Alias(symbol, args, new_real_type_var); + + target.set(copy, make_descriptor(new_content)); + + copy + } + } +} diff --git a/compiler/unify/src/unify.rs b/compiler/unify/src/unify.rs index 51771efe07..f469b0be1c 100644 --- a/compiler/unify/src/unify.rs +++ b/compiler/unify/src/unify.rs @@ -133,12 +133,14 @@ fn unify_context(subs: &mut Subs, pool: &mut Pool, ctx: Context) -> Outcome { // println!("\n --- \n"); // dbg!(ctx.second, type2); // println!("\n --------------- \n"); + let content_1 = subs.get(ctx.first).content; + let content_2 = subs.get(ctx.second).content; println!( "{:?} {:?} ~ {:?} {:?}", ctx.first, - subs.get(ctx.first).content, + roc_types::subs::SubsFmtContent(&content_1, subs), ctx.second, - subs.get(ctx.second).content + roc_types::subs::SubsFmtContent(&content_2, subs), ); } match &ctx.first_desc.content {