diff --git a/compiler/can/src/constraint.rs b/compiler/can/src/constraint.rs index ae24ba78c9..70573d252a 100644 --- a/compiler/can/src/constraint.rs +++ b/compiler/can/src/constraint.rs @@ -11,7 +11,7 @@ pub struct Constraints { pub constraints: Vec, pub types: Vec, pub variables: Vec, - pub def_types: Vec<(Symbol, Loc>)>, + pub loc_symbols: Vec<(Symbol, Region)>, pub let_constraints: Vec, pub categories: Vec, pub pattern_categories: Vec, @@ -32,7 +32,7 @@ impl Constraints { let constraints = Vec::new(); let mut types = Vec::new(); let variables = Vec::new(); - let def_types = Vec::new(); + let loc_symbols = Vec::new(); let let_constraints = Vec::new(); let mut categories = Vec::with_capacity(16); let mut pattern_categories = Vec::with_capacity(16); @@ -78,7 +78,7 @@ impl Constraints { constraints, types, variables, - def_types, + loc_symbols, let_constraints, categories, pattern_categories, @@ -260,28 +260,33 @@ impl Constraints { Slice::new(start as _, length as _) } - fn def_types_slice(&mut self, it: I) -> Slice<(Symbol, Loc>)> + fn def_types_slice(&mut self, it: I) -> DefTypes where I: IntoIterator)>, I::IntoIter: ExactSizeIterator, { let it = it.into_iter(); - let start = self.def_types.len(); + let types_start = self.types.len(); + let loc_symbols_start = self.loc_symbols.len(); // because we have an ExactSizeIterator, we can reserve space here - self.def_types.reserve(it.len()); + let length = it.len(); + + self.types.reserve(length); + self.loc_symbols.reserve(length); for (symbol, loc_type) in it { let Loc { region, value } = loc_type; - let type_index = Index::push_new(&mut self.types, value); - self.def_types.push((symbol, Loc::at(region, type_index))); + self.types.push(value); + self.loc_symbols.push((symbol, region)); } - let length = self.def_types.len() - start; - - Slice::new(start as _, length as _) + DefTypes { + types: Slice::new(types_start as _, length as _), + loc_symbols: Slice::new(loc_symbols_start as _, length as _), + } } #[inline(always)] @@ -297,7 +302,7 @@ impl Constraints { let let_contraint = LetConstraint { rigid_vars: Slice::default(), flex_vars: self.variable_slice(flex_vars), - def_types: Slice::default(), + def_types: DefTypes::default(), defs_and_ret_constraint, }; @@ -323,7 +328,7 @@ impl Constraints { let let_contraint = LetConstraint { rigid_vars: Slice::default(), flex_vars: self.variable_slice(flex_vars), - def_types: Slice::default(), + def_types: DefTypes::default(), defs_and_ret_constraint, }; @@ -476,11 +481,17 @@ pub enum Constraint { ), } +#[derive(Debug, Clone, Copy, PartialEq, Default)] +pub struct DefTypes { + pub types: Slice, + pub loc_symbols: Slice<(Symbol, Region)>, +} + #[derive(Debug, Clone, PartialEq)] pub struct LetConstraint { pub rigid_vars: Slice, pub flex_vars: Slice, - pub def_types: Slice<(Symbol, Loc>)>, + pub def_types: DefTypes, pub defs_and_ret_constraint: Index<(Constraint, Constraint)>, } diff --git a/compiler/constrain/src/expr.rs b/compiler/constrain/src/expr.rs index e534e5a45f..a0e2f5009c 100644 --- a/compiler/constrain/src/expr.rs +++ b/compiler/constrain/src/expr.rs @@ -100,7 +100,6 @@ pub fn constrain_expr( if fields.is_empty() { constrain_empty_record(constraints, region, expected) } else { - let mut field_exprs = SendMap::default(); let mut field_types = SendMap::default(); let mut field_vars = Vec::with_capacity(fields.len()); @@ -115,7 +114,6 @@ pub fn constrain_expr( constrain_field(constraints, env, field_var, &*loc_field_expr); field_vars.push(field_var); - field_exprs.insert(label.clone(), loc_field_expr); field_types.insert(label.clone(), RecordField::Required(field_type)); rec_constraints.push(field_con); @@ -1194,13 +1192,7 @@ fn constrain_when_branch( // must introduce the headers from the pattern before constraining the guard let state_constraints = constraints.and_constraint(state.constraints); - let inner = constraints.let_constraint( - [], - [], - SendMap::default(), - guard_constraint, - ret_constraint, - ); + let inner = constraints.let_constraint([], [], [], guard_constraint, ret_constraint); constraints.let_constraint([], state.vars, state.headers, state_constraints, inner) } else { @@ -1546,13 +1538,7 @@ fn constrain_def( ); let cons = [ - constraints.let_constraint( - [], - [], - SendMap::default(), - Constraint::True, - ret_constraint, - ), + constraints.let_constraint([], [], [], Constraint::True, ret_constraint), // Store type into AST vars. We use Store so errors aren't reported twice constraints.store(signature, expr_var, std::file!(), std::line!()), ]; @@ -1605,7 +1591,7 @@ fn constrain_def_make_constraint( let def_con = constraints.let_constraint( [], new_infer_variables, - SendMap::default(), // empty, because our functions have no arguments! + [], // empty, because our functions have no arguments! and_constraint, expr_con, ); @@ -1721,6 +1707,11 @@ fn instantiate_rigids( annotation.substitute(&rigid_substitution); } + // TODO investigate when we can skip this. It seems to only be required for correctness + // for recursive functions. For non-recursive functions the final type is correct, but + // alias information is sometimes lost + // + // Skipping all of this cloning here would be neat! let loc_annotation_ref = Loc::at(loc_pattern.region, &annotation); if let Pattern::Identifier(symbol) = loc_pattern.value { headers.insert(symbol, Loc::at(loc_pattern.region, annotation.clone())); @@ -1783,8 +1774,8 @@ pub fn rec_defs_help( // TODO investigate if this let can be safely removed let def_con = constraints.let_constraint( [], - [], // empty because Roc function defs have no args - SendMap::default(), // empty because Roc function defs have no args + [], // empty because Roc function defs have no args + [], // empty because Roc function defs have no args Constraint::True, // I think this is correct, once again because there are no args expr_con, ); @@ -1974,7 +1965,7 @@ pub fn rec_defs_help( rigid_info.constraints.push(constraints.let_constraint( new_rigid_variables, def_pattern_state.vars, - SendMap::default(), // no headers introduced (at this level) + [], // no headers introduced (at this level) def_con, Constraint::True, )); @@ -1995,7 +1986,7 @@ pub fn rec_defs_help( constraints.let_constraint( [], [], - SendMap::default(), + [], Constraint::True, ret_constraint, ), @@ -2009,7 +2000,7 @@ pub fn rec_defs_help( rigid_info.constraints.push(constraints.let_constraint( new_rigid_variables, def_pattern_state.vars, - SendMap::default(), // no headers introduced (at this level) + [], // no headers introduced (at this level) def_con, Constraint::True, )); diff --git a/compiler/solve/src/solve.rs b/compiler/solve/src/solve.rs index e0603652a6..0e30a52104 100644 --- a/compiler/solve/src/solve.rs +++ b/compiler/solve/src/solve.rs @@ -3,7 +3,6 @@ use roc_can::constraint::Constraint::{self, *}; use roc_can::constraint::{Constraints, LetConstraint}; use roc_can::expected::{Expected, PExpected}; use roc_collections::all::MutMap; -use roc_collections::soa::{Index, Slice}; use roc_module::ident::TagName; use roc_module::symbol::{ModuleId, Symbol}; use roc_region::all::{Loc, Region}; @@ -822,23 +821,17 @@ impl LocalDefVarsVec<(Symbol, Loc)> { pools: &mut Pools, cached_aliases: &mut MutMap, subs: &mut Subs, - def_types_slice: Slice<(Symbol, Loc>)>, + def_types_slice: roc_can::constraint::DefTypes, ) -> Self { - let def_types = &constraints.def_types[def_types_slice.indices()]; + let types_slice = &constraints.types[def_types_slice.types.indices()]; + let loc_symbols_slice = &constraints.loc_symbols[def_types_slice.loc_symbols.indices()]; - let mut local_def_vars = Self::with_length(def_types.len()); + let mut local_def_vars = Self::with_length(types_slice.len()); - for (symbol, loc_type_index) in def_types.iter() { - let typ = &constraints.types[loc_type_index.value.index()]; + for ((symbol, region), typ) in loc_symbols_slice.iter().copied().zip(types_slice) { let var = type_to_var(subs, rank, pools, cached_aliases, typ); - local_def_vars.push(( - *symbol, - Loc { - value: var, - region: loc_type_index.region, - }, - )); + local_def_vars.push((symbol, Loc { value: var, region })); } local_def_vars