Fix List.len monomorphization

This commit is contained in:
Richard Feldman 2020-06-23 21:14:23 -04:00
parent 750523ba5c
commit f350c0ed52
6 changed files with 69 additions and 37 deletions

View File

@ -792,10 +792,7 @@ pub fn constrain_expr(
let mut arg_types = Vec::with_capacity(args.len());
let mut arg_cons = Vec::with_capacity(args.len());
let args_iter = args.iter();
for (index, (arg_var, arg)) in args_iter.enumerate() {
let arg_type = Variable(*arg_var);
let mut add_arg = |index, arg_type: Type, arg| {
let reason = Reason::LowLevelOpArg {
op: *op,
arg_index: Index::zero_based(index),
@ -803,9 +800,14 @@ pub fn constrain_expr(
let expected_arg = ForReason(reason, arg_type.clone(), Region::zero());
let arg_con = constrain_expr(env, Region::zero(), arg, expected_arg);
vars.push(*arg_var);
arg_types.push(arg_type);
arg_cons.push(arg_con);
};
for (index, (arg_var, arg)) in args.iter().enumerate() {
vars.push(*arg_var);
add_arg(index, Variable(*arg_var), arg);
}
let category = Category::LowLevelOpResult(*op);

View File

@ -177,7 +177,7 @@ lazy_static! {
std::sync::Mutex::new(roc_collections::all::MutMap::default());
}
#[derive(Debug)]
#[derive(Debug, Default)]
pub struct Interns {
pub module_ids: ModuleIds,
pub all_ident_ids: MutMap<ModuleId, IdentIds>,

View File

@ -1,4 +1,4 @@
use crate::layout::{Builtin, Layout, LayoutCache};
use crate::layout::{Builtin, Layout, LayoutCache, LayoutProblem};
use crate::pattern::{Ctor, Guard, RenderAs, TagId};
use bumpalo::collections::Vec;
use bumpalo::Bump;
@ -789,8 +789,11 @@ fn from_can<'a>(
Content::FlexVar(_) => Layout::Builtin(Builtin::EmptyList),
_ => match layout_cache.from_var(arena, elem_var, env.subs, env.pointer_size) {
Ok(layout) => layout.clone(),
Err(()) => {
panic!("TODO gracefully handle List with invalid element layout");
Err(problem) => {
todo!(
"gracefully handle List with element layout problem: {:?}",
problem
);
}
},
};
@ -1300,7 +1303,7 @@ fn call_by_name<'a>(
Ok(layout) => {
args.push((from_can(env, loc_arg.value, procs, layout_cache), layout));
}
Err(()) => {
Err(_) => {
// One of this function's arguments code gens to a runtime error,
// so attempting to call it will immediately crash.
return Expr::RuntimeError("");
@ -1323,7 +1326,7 @@ fn call_by_name<'a>(
args: args.into_bump_slice(),
}
}
Err(()) => {
Err(_) => {
// This function code gens to a runtime error,
// so attempting to call it will immediately crash.
Expr::RuntimeError("")
@ -1376,7 +1379,7 @@ pub fn specialize_all<'a>(
Ok(proc) => {
answer.insert((name, layout), proc);
}
Err(()) => {
Err(_) => {
runtime_errors.insert(name);
}
}
@ -1397,7 +1400,7 @@ fn specialize<'a>(
layout_cache: &mut LayoutCache<'a>,
pending: PendingSpecialization<'a>,
partial_proc: PartialProc<'a>,
) -> Result<Proc<'a>, ()> {
) -> Result<Proc<'a>, LayoutProblem> {
let PendingSpecialization {
ret_var,
fn_var,

View File

@ -47,13 +47,11 @@ impl<'a> Layout<'a> {
content: Content,
subs: &Subs,
pointer_size: u32,
) -> Result<Self, ()> {
) -> Result<Self, LayoutProblem> {
use roc_types::subs::Content::*;
match content {
var @ FlexVar(_) | var @ RigidVar(_) => {
panic!("Layout::new encountered an unresolved {:?}", var);
}
FlexVar(_) | RigidVar(_) => Err(LayoutProblem::UnboundVar),
Structure(flat_type) => layout_from_flat_type(arena, flat_type, subs, pointer_size),
Alias(Symbol::NUM_INT, args, _) => {
@ -70,7 +68,7 @@ impl<'a> Layout<'a> {
subs,
pointer_size,
),
Error => Err(()),
Error => Err(LayoutProblem::Erroneous),
}
}
@ -82,7 +80,7 @@ impl<'a> Layout<'a> {
var: Variable,
subs: &Subs,
pointer_size: u32,
) -> Result<Self, ()> {
) -> Result<Self, LayoutProblem> {
let content = subs.get_without_compacting(var).content;
Self::new(arena, content, subs, pointer_size)
@ -143,7 +141,7 @@ impl<'a> Layout<'a> {
/// Avoid recomputing Layout from Variable multiple times.
#[derive(Default)]
pub struct LayoutCache<'a> {
layouts: MutMap<Variable, Result<Layout<'a>, ()>>,
layouts: MutMap<Variable, Result<Layout<'a>, LayoutProblem>>,
}
impl<'a> LayoutCache<'a> {
@ -156,7 +154,7 @@ impl<'a> LayoutCache<'a> {
var: Variable,
subs: &Subs,
pointer_size: u32,
) -> Result<Layout<'a>, ()> {
) -> Result<Layout<'a>, LayoutProblem> {
// Store things according to the root Variable, to avoid duplicate work.
let var = subs.get_root_key_without_compacting(var);
@ -228,12 +226,23 @@ impl<'a> Builtin<'a> {
}
}
#[derive(Debug, Clone)]
pub enum LayoutProblem {
/// We get this error when, after unwrapping all the Attr wrappers,
/// we ultimately end up with an unresolved FlexVar. This can happen
/// legitimately, for example when resolving a layout for a `List (Attr * *)` -
/// which should be an empty list. However, if we get all the way back to
/// the top and it's still this error, that's a compiler bug.
UnboundVar,
Erroneous,
}
fn layout_from_flat_type<'a>(
arena: &'a Bump,
flat_type: FlatType,
subs: &Subs,
pointer_size: u32,
) -> Result<Layout<'a>, ()> {
) -> Result<Layout<'a>, LayoutProblem> {
use roc_types::subs::FlatType::*;
match flat_type {
@ -258,19 +267,24 @@ fn layout_from_flat_type<'a>(
}
Symbol::STR_STR => Ok(Layout::Builtin(Builtin::Str)),
Symbol::LIST_LIST => {
use roc_types::subs::Content::*;
use LayoutProblem::*;
match subs.get_without_compacting(args[0]).content {
FlexVar(_) | RigidVar(_) => Ok(Layout::Builtin(Builtin::EmptyList)),
content => {
let elem_layout = Layout::new(arena, content, subs, pointer_size)?;
let content = subs.get_without_compacting(args[0]).content;
match Layout::new(arena, content, subs, pointer_size) {
Ok(elem_layout) => {
// This is a normal list.
Ok(Layout::Builtin(Builtin::List(arena.alloc(elem_layout))))
}
Err(UnboundVar) => {
// This is an empty list. That's fine!
Ok(Layout::Builtin(Builtin::EmptyList))
}
Err(Erroneous) => Err(Erroneous),
}
}
Symbol::ATTR_ATTR => {
debug_assert!(args.len() == 2);
debug_assert_eq!(args.len(), 2);
// The first argument is the uniqueness info;
// that doesn't affect layout, so we don't need it here.
@ -316,7 +330,7 @@ fn layout_from_flat_type<'a>(
let field_content = subs.get_without_compacting(field_var).content;
let field_layout = match Layout::new(arena, field_content, subs, pointer_size) {
Ok(layout) => layout,
Err(()) => {
Err(_) => {
// Invalid field!
panic!("TODO gracefully handle record with invalid field.var");
}
@ -341,7 +355,7 @@ fn layout_from_flat_type<'a>(
Boolean(_) => {
panic!("TODO make Layout for Boolean");
}
Erroneous(_) => Err(()),
Erroneous(_) => Err(LayoutProblem::Erroneous),
EmptyRecord => Ok(Layout::Struct(&[])),
}
}
@ -538,7 +552,7 @@ fn ext_var_is_empty_record(subs: &Subs, ext_var: Variable) -> bool {
}
}
fn layout_from_num_content<'a>(content: Content) -> Result<Layout<'a>, ()> {
fn layout_from_num_content<'a>(content: Content) -> Result<Layout<'a>, LayoutProblem> {
use roc_types::subs::Content::*;
use roc_types::subs::FlatType::*;
@ -566,11 +580,11 @@ fn layout_from_num_content<'a>(content: Content) -> Result<Layout<'a>, ()> {
Structure(_) => {
panic!("Invalid Num.Num type application: {:?}", content);
}
Error => Err(()),
Error => Err(LayoutProblem::Erroneous),
}
}
fn unwrap_num_tag<'a>(subs: &Subs, var: Variable) -> Result<Layout<'a>, ()> {
fn unwrap_num_tag<'a>(subs: &Subs, var: Variable) -> Result<Layout<'a>, LayoutProblem> {
match subs.get_without_compacting(var).content {
Content::Structure(flat_type) => match flat_type {
FlatType::Apply(Symbol::ATTR_ATTR, args) => {

View File

@ -132,10 +132,7 @@ pub fn can_expr_with(
let loc_expr = match parse_loc_with(&arena, expr_str) {
Ok(e) => e,
Err(fail) => {
let interns = Interns {
module_ids: ModuleIds::default(),
all_ident_ids: MutMap::default(),
};
let interns = Interns::default();
return Err(ParseErrOut {
fail,

View File

@ -544,6 +544,22 @@ impl Content {
_ => false,
}
}
#[cfg(debug_assertions)]
#[allow(dead_code)]
pub fn dbg(self, subs: &Subs) -> Self {
let home = roc_module::symbol::ModuleIds::default().get_or_insert(&"#Dbg".into());
let mut interns = roc_module::symbol::Interns::default();
interns.all_ident_ids = roc_module::symbol::IdentIds::exposed_builtins(0);
eprintln!(
"{}",
crate::pretty_print::content_to_string(self.clone(), subs, home, &interns)
);
self
}
}
#[derive(Clone, Debug, PartialEq, Eq)]