actually infer the size

This commit is contained in:
Folkert 2020-10-02 22:33:31 +02:00
parent c00cd2f415
commit e9f5c1a73c
8 changed files with 51 additions and 25 deletions

View file

@ -1012,7 +1012,7 @@ fn canonicalize_pending_def<'a>(
function_type,
closure_type,
return_type,
name: *symbol,
name: *defined_symbol,
recursive: is_recursive,
arguments: arguments.clone(),
loc_body: body.clone(),
@ -1145,7 +1145,7 @@ fn canonicalize_pending_def<'a>(
function_type,
closure_type,
return_type,
name: *symbol,
name: *defined_symbol,
recursive: is_recursive,
arguments: arguments.clone(),
loc_body: body.clone(),

View file

@ -961,6 +961,7 @@ pub fn constrain_decls(
Vec::new(),
constrain_def(&env, def, constraint),
);
debug_assert!(format!("{:?}", &constraint).contains("SaveTheEnvironment"));
}
Declaration::DeclareRec(defs) => {
constraint = exists_with_aliases(
@ -968,6 +969,7 @@ pub fn constrain_decls(
Vec::new(),
constrain_recursive_defs(&env, defs, constraint),
);
debug_assert!(format!("{:?}", &constraint).contains("SaveTheEnvironment"));
}
Declaration::InvalidCycle(_, _) => {
// invalid cycles give a canonicalization error. we skip them here.
@ -976,6 +978,7 @@ pub fn constrain_decls(
}
}
debug_assert!(format!("{:?}", &constraint).contains("SaveTheEnvironment"));
constraint
}

View file

@ -45,7 +45,7 @@ pub fn helper_without_uniqueness<'a>(
let subs = Subs::new(var_store.into());
let mut unify_problems = Vec::new();
let (content, mut subs) = infer_expr(subs, &mut unify_problems, &constraint, var);
let (content, mut subs, solve_env) = infer_expr(subs, &mut unify_problems, &constraint, var);
assert_eq!(
unify_problems,
@ -103,7 +103,7 @@ pub fn helper_without_uniqueness<'a>(
};
// infer the size of any closures
roc_mono::closures::infer_closure_size(&loc_expr.value, mono_env.subs);
roc_mono::closures::infer_closure_size(&loc_expr.value, mono_env.subs, &solve_env);
let main_body = roc_mono::ir::Stmt::new(&mut mono_env, loc_expr.value, &mut procs);
@ -219,7 +219,7 @@ pub fn helper_with_uniqueness<'a>(
assert_eq!(errors, Vec::new(), "Encountered errors: {:?}", errors);
let mut unify_problems = Vec::new();
let (content, mut subs) = infer_expr(subs, &mut unify_problems, &constraint, var);
let (content, mut subs, solve_env) = infer_expr(subs, &mut unify_problems, &constraint, var);
assert_eq!(
unify_problems,
@ -275,7 +275,7 @@ pub fn helper_with_uniqueness<'a>(
};
// infer the size of any closures
roc_mono::closures::infer_closure_size(&loc_expr.value, mono_env.subs);
roc_mono::closures::infer_closure_size(&loc_expr.value, mono_env.subs, &solve_env);
let main_body = roc_mono::ir::Stmt::new(&mut mono_env, loc_expr.value, &mut procs);
let mut headers = {

View file

@ -74,16 +74,16 @@ pub fn infer_expr(
problems: &mut Vec<roc_solve::solve::TypeError>,
constraint: &Constraint,
expr_var: Variable,
) -> (Content, Subs) {
) -> (Content, Subs, solve::Env) {
let env = solve::Env {
aliases: MutMap::default(),
vars_by_symbol: SendMap::default(),
};
let (solved, _) = solve::run(&env, problems, subs, constraint);
let (solved, env) = solve::run(&env, problems, subs, constraint);
let content = solved.inner().get_without_compacting(expr_var).content;
(content, solved.into_inner())
(content, solved.into_inner(), env)
}
pub fn parse_loc_with<'a>(arena: &'a Bump, input: &'a str) -> Result<Located<ast::Expr<'a>>, Fail> {

View file

@ -6,19 +6,22 @@ use roc_collections::all::MutSet;
use roc_constrain::expr::exists;
use roc_module::symbol::Symbol;
use roc_region::all::Region;
use roc_solve::solve;
use roc_types::subs::{Subs, VarStore};
use roc_types::types::{Category, Type};
pub fn infer_closure_size(expr: &Expr, subs: &mut Subs) {
use roc_solve::solve;
pub fn infer_closure_size(expr: &Expr, subs: &mut Subs, solve_env: &solve::Env) {
let mut var_store = VarStore::new_from_subs(subs);
let env = solve::Env::default();
let mut problems = Vec::new();
let constraint = generate_constraint(expr, &mut var_store);
let _new_env = solve::run_in_place(&env, &mut problems, subs, &constraint);
let next = var_store.fresh().index();
let variables_introduced = next as usize - (subs.len() - 1);
subs.extend_by(variables_introduced);
let _new_env = solve::run_in_place(solve_env, &mut problems, subs, &constraint);
debug_assert_eq!(problems.len(), 0);
}
@ -224,7 +227,8 @@ pub fn generate_constraints_help(
}
Closure {
arguments: _,
arguments,
name,
closure_type: closure_var,
loc_body: boxed_body,
..
@ -232,7 +236,18 @@ pub fn generate_constraints_help(
let mut cons = Vec::new();
let mut variables = Vec::new();
let closed_over_symbols = MutSet::default();
let bound_by_closure = arguments
.iter()
.map(|(_, pattern)| symbols_from_pattern(&pattern.value))
.flatten()
.collect::<MutSet<_>>();
// let closed_over_symbols = MutSet::default();
let closed_over_symbols = free_variables(expr)
.into_iter()
.filter(|x| !x.is_builtin() && !bound_by_closure.contains(&x) && !(x == name))
.collect::<MutSet<_>>();
let closure_ext_var = var_store.fresh();
let closure_var = *closure_var;

View file

@ -196,8 +196,9 @@ fn solve(
constraint: &Constraint,
) -> State {
match constraint {
True => state,
SaveTheEnvironment => {
// True => state,
True | SaveTheEnvironment => {
// NOTE deviation: elm only copies the env into the state on SaveTheEnvironment
let mut copy = state;
copy.env = env.clone();

View file

@ -73,6 +73,7 @@ impl VarStore {
}
pub fn new_from_subs(subs: &Subs) -> Self {
// TODO why -2, are we not overwriting something here?
let next_var = (subs.utable.len() - 1) as u32;
debug_assert!(next_var >= Variable::FIRST_USER_SPACE_VAR.0);
@ -266,6 +267,12 @@ impl Subs {
subs
}
pub fn extend_by(&mut self, entries: usize) {
for _ in 0..entries {
self.utable.new_key(flex_var_descriptor());
}
}
pub fn fresh(&mut self, value: Descriptor) -> Variable {
self.utable.new_key(value)
}

View file

@ -133,13 +133,13 @@ fn unify_context(subs: &mut Subs, pool: &mut Pool, ctx: Context) -> Outcome {
// NOTE: names are generated here (when creating an error type) and that modifies names
// generated by pretty_print.rs. So many test will fail with changes in variable names when
// this block runs.
let (type1, _problems1) = subs.var_to_error_type(ctx.first);
let (type2, _problems2) = subs.var_to_error_type(ctx.second);
println!("\n --------------- \n");
dbg!(ctx.first, type1);
println!("\n --- \n");
dbg!(ctx.second, type2);
println!("\n --------------- \n");
// let (type1, _problems1) = subs.var_to_error_type(ctx.first);
// let (type2, _problems2) = subs.var_to_error_type(ctx.second);
// println!("\n --------------- \n");
// dbg!(ctx.first, type1);
// println!("\n --- \n");
// dbg!(ctx.second, type2);
// println!("\n --------------- \n");
println!(
"{:?} {:?} ~ {:?} {:?}",
ctx.first,