Merge remote-tracking branch 'origin/trunk' into alias-nominal-equality

This commit is contained in:
Folkert 2021-07-31 22:59:01 +02:00
commit a47f9baef4
16 changed files with 352 additions and 237 deletions

View file

@ -21,20 +21,14 @@ pub fn infer_borrow<'a>(
procs: &MutMap<(Symbol, ProcLayout<'a>), Proc<'a>>,
) -> ParamMap<'a> {
// intern the layouts
let mut declaration_to_index = MutMap::with_capacity_and_hasher(procs.len(), default_hasher());
let mut param_map = {
let mut i = 0;
for key in procs.keys() {
declaration_to_index.insert(*key, ParamOffset(i));
i += key.1.arguments.len();
}
let (declaration_to_index, total_number_of_params) = DeclarationToIndex::new(arena, procs);
ParamMap {
declaration_to_index,
join_points: MutMap::default(),
declarations: bumpalo::vec![in arena; Param::EMPTY; i],
declarations: bumpalo::vec![in arena; Param::EMPTY; total_number_of_params],
}
};
@ -118,7 +112,7 @@ pub fn infer_borrow<'a>(
for (key, proc) in procs {
let symbol = key.0;
let offset = param_map.declaration_to_index[key];
let offset = param_map.get_param_offset(key.0, key.1);
// the component this symbol is a part of
let component = symbol_to_component[&symbol];
@ -169,10 +163,71 @@ impl From<ParamOffset> for usize {
}
}
#[derive(Debug, Clone)]
#[derive(Debug)]
struct DeclarationToIndex<'a> {
elements: Vec<'a, ((Symbol, ProcLayout<'a>), ParamOffset)>,
}
impl<'a> DeclarationToIndex<'a> {
fn new(arena: &'a Bump, procs: &MutMap<(Symbol, ProcLayout<'a>), Proc<'a>>) -> (Self, usize) {
let mut declaration_to_index = Vec::with_capacity_in(procs.len(), arena);
let mut i = 0;
for key in procs.keys().copied() {
declaration_to_index.push((key, ParamOffset(i)));
i += key.1.arguments.len();
}
declaration_to_index.sort_unstable_by_key(|t| t.0 .0);
(
DeclarationToIndex {
elements: declaration_to_index,
},
i,
)
}
fn get_param_offset(
&self,
needle_symbol: Symbol,
needle_layout: ProcLayout<'a>,
) -> ParamOffset {
if let Ok(middle_index) = self
.elements
.binary_search_by_key(&needle_symbol, |t| t.0 .0)
{
// first, iterate backward until we hit a different symbol
let backward = self.elements[..middle_index].iter().rev();
for ((symbol, proc_layout), param_offset) in backward {
if *symbol != needle_symbol {
break;
} else if *proc_layout == needle_layout {
return *param_offset;
}
}
// if not found, iterate forward until we find our combo
let forward = self.elements[middle_index..].iter();
for ((symbol, proc_layout), param_offset) in forward {
if *symbol != needle_symbol {
break;
} else if *proc_layout == needle_layout {
return *param_offset;
}
}
}
unreachable!("symbol/layout combo must be in DeclarationToIndex")
}
}
#[derive(Debug)]
pub struct ParamMap<'a> {
/// Map a (Symbol, ProcLayout) pair to the starting index in the `declarations` array
declaration_to_index: MutMap<(Symbol, ProcLayout<'a>), ParamOffset>,
declaration_to_index: DeclarationToIndex<'a>,
/// the parameters of all functions in a single flat array.
///
/// - the map above gives the index of the first parameter for the function
@ -184,11 +239,17 @@ pub struct ParamMap<'a> {
}
impl<'a> ParamMap<'a> {
pub fn get_param_offset(&self, symbol: Symbol, layout: ProcLayout<'a>) -> ParamOffset {
self.declaration_to_index.get_param_offset(symbol, layout)
}
pub fn get_symbol(&self, symbol: Symbol, layout: ProcLayout<'a>) -> Option<&[Param<'a>]> {
let index: usize = self.declaration_to_index[&(symbol, layout)].into();
// let index: usize = self.declaration_to_index[&(symbol, layout)].into();
let index: usize = self.get_param_offset(symbol, layout).into();
self.declarations.get(index..index + layout.arguments.len())
}
pub fn get_join_point(&self, id: JoinPointId) -> &'a [Param<'a>] {
match self.join_points.get(&id) {
Some(slice) => slice,
@ -197,7 +258,7 @@ impl<'a> ParamMap<'a> {
}
pub fn iter_symbols(&'a self) -> impl Iterator<Item = &'a Symbol> {
self.declaration_to_index.iter().map(|t| &t.0 .0)
self.declaration_to_index.elements.iter().map(|t| &t.0 .0)
}
}
@ -247,7 +308,7 @@ impl<'a> ParamMap<'a> {
return;
}
let index: usize = self.declaration_to_index[&key].into();
let index: usize = self.get_param_offset(key.0, key.1).into();
for (i, param) in Self::init_borrow_args(arena, proc.args)
.iter()
@ -266,7 +327,7 @@ impl<'a> ParamMap<'a> {
proc: &Proc<'a>,
key: (Symbol, ProcLayout<'a>),
) {
let index: usize = self.declaration_to_index[&key].into();
let index: usize = self.get_param_offset(key.0, key.1).into();
for (i, param) in Self::init_borrow_args_always_owned(arena, proc.args)
.iter()

View file

@ -3010,7 +3010,7 @@ pub fn with_hole<'a>(
let arena = env.arena;
debug_assert!(!matches!(
env.subs.get_without_compacting(variant_var).content,
env.subs.get_content_without_compacting(variant_var),
Content::Structure(FlatType::Func(_, _, _))
));
convert_tag_union(
@ -3035,12 +3035,15 @@ pub fn with_hole<'a>(
} => {
let arena = env.arena;
let desc = env.subs.get_without_compacting(variant_var);
let content = env.subs.get_content_without_compacting(variant_var);
if let Content::Structure(FlatType::Func(arg_vars, _, ret_var)) = content {
let ret_var = *ret_var;
let arg_vars = arg_vars.clone();
if let Content::Structure(FlatType::Func(arg_vars, _, ret_var)) = desc.content {
tag_union_to_function(
env,
arg_vars,
&arg_vars,
ret_var,
tag_name,
closure_name,
@ -4343,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: std::vec::Vec<Variable>,
argument_variables: &[Variable],
return_variable: Variable,
tag_name: TagName,
proc_symbol: Symbol,
@ -4364,8 +4367,8 @@ fn tag_union_to_function<'a>(
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 {
@ -7395,8 +7398,8 @@ fn from_can_pattern_help<'a>(
// TODO these don't match up in the uniqueness inference; when we remove
// that, reinstate this assert!
//
// dbg!(&env.subs.get_without_compacting(*field_var).content);
// dbg!(&env.subs.get_without_compacting(destruct.value.var).content);
// dbg!(&env.subs.get_content_without_compacting(*field_var));
// dbg!(&env.subs.get_content_without_compacting(destruct.var).content);
// debug_assert_eq!(
// env.subs.get_root_key_without_compacting(*field_var),
// env.subs.get_root_key_without_compacting(destruct.value.var)
@ -7490,7 +7493,7 @@ pub fn num_argument_to_int_or_float(
var: Variable,
known_to_be_float: bool,
) -> IntOrFloat {
match subs.get_without_compacting(var).content {
match subs.get_content_without_compacting(var){
Content::FlexVar(_) | Content::RigidVar(_) if known_to_be_float => IntOrFloat::BinaryFloatType(FloatPrecision::F64),
Content::FlexVar(_) | Content::RigidVar(_) => IntOrFloat::SignedIntType(IntPrecision::I64), // We default (Num *) to I64