Lambda set compaction in mono

This commit is contained in:
Ayaz Hafiz 2022-06-07 11:50:39 -04:00
parent db479cbcc2
commit 201853ecca
No known key found for this signature in database
GPG key ID: 0E2A37416A25EF58
2 changed files with 47 additions and 26 deletions

View file

@ -30,7 +30,6 @@ use roc_types::subs::{
Content, ExhaustiveMark, FlatType, RedundantMark, StorageSubs, Subs, Variable, Content, ExhaustiveMark, FlatType, RedundantMark, StorageSubs, Subs, Variable,
VariableSubsSlice, VariableSubsSlice,
}; };
use roc_unify::unify::Mode;
use std::collections::HashMap; use std::collections::HashMap;
use ven_pretty::{BoxAllocator, DocAllocator, DocBuilder}; use ven_pretty::{BoxAllocator, DocAllocator, DocBuilder};
@ -1268,6 +1267,35 @@ impl<'a, 'i> Env<'a, 'i> {
pub fn is_imported_symbol(&self, symbol: Symbol) -> bool { pub fn is_imported_symbol(&self, symbol: Symbol) -> bool {
symbol.module_id() != self.home symbol.module_id() != self.home
} }
/// Unifies two variables and performs lambda set compaction.
/// Use this rather than [roc_unify::unify] directly!
fn unify(&mut self, left: Variable, right: Variable) -> Result<(), ()> {
use roc_solve::solve::{compact_lambda_sets_of_vars, Pools};
use roc_unify::unify::{unify, Mode, Unified};
let unified = unify(self.subs, left, right, Mode::EQ);
match unified {
Unified::Success {
vars: _,
must_implement_ability: _,
lambda_sets_to_specialize,
} => {
let mut pools = Pools::default();
compact_lambda_sets_of_vars(
self.subs,
self.arena,
&mut pools,
self.abilities_store,
lambda_sets_to_specialize,
);
// pools don't matter because we don't care about ranks here
Ok(())
}
Unified::Failure(..) | Unified::BadType(..) => Err(()),
}
}
} }
#[derive(Clone, Debug, PartialEq, Copy, Eq, Hash)] #[derive(Clone, Debug, PartialEq, Copy, Eq, Hash)]
@ -2246,7 +2274,7 @@ fn from_can_let<'a>(
needed_specializations.next().unwrap(); needed_specializations.next().unwrap();
// Unify the expr_var with the requested specialization once. // Unify the expr_var with the requested specialization once.
let _res = roc_unify::unify::unify(env.subs, var, def.expr_var, Mode::EQ); let _res = env.unify(var, def.expr_var);
resolve_abilities_in_specialized_body( resolve_abilities_in_specialized_body(
env, env,
@ -2285,8 +2313,7 @@ fn from_can_let<'a>(
"expr marked as having specializations, but it has no type variables!", "expr marked as having specializations, but it has no type variables!",
); );
let _res = let _res = env.unify(var, new_def_expr_var);
roc_unify::unify::unify(env.subs, var, new_def_expr_var, Mode::EQ);
resolve_abilities_in_specialized_body( resolve_abilities_in_specialized_body(
env, env,
@ -2780,16 +2807,14 @@ fn resolve_abilities_in_specialized_body<'a>(
) -> std::vec::Vec<SpecializationId> { ) -> std::vec::Vec<SpecializationId> {
use roc_can::expr::Expr; use roc_can::expr::Expr;
use roc_can::traverse::{walk_expr, Visitor}; use roc_can::traverse::{walk_expr, Visitor};
use roc_unify::unify::unify;
struct Resolver<'a> { struct Resolver<'a, 'b, 'borrow> {
subs: &'a mut Subs, env: &'borrow mut Env<'a, 'b>,
procs: &'a Procs<'a>, procs: &'borrow Procs<'a>,
abilities_store: &'a mut AbilitiesStore,
seen_defs: MutSet<Symbol>, seen_defs: MutSet<Symbol>,
specialized: std::vec::Vec<SpecializationId>, specialized: std::vec::Vec<SpecializationId>,
} }
impl Visitor for Resolver<'_> { impl Visitor for Resolver<'_, '_, '_> {
fn visit_expr(&mut self, expr: &Expr, _region: Region, var: Variable) { fn visit_expr(&mut self, expr: &Expr, _region: Region, var: Variable) {
match expr { match expr {
Expr::Closure(..) => { Expr::Closure(..) => {
@ -2805,6 +2830,7 @@ fn resolve_abilities_in_specialized_body<'a>(
} }
Expr::AbilityMember(member_sym, specialization_id, _specialization_var) => { Expr::AbilityMember(member_sym, specialization_id, _specialization_var) => {
let (specialization, specialization_def) = match self let (specialization, specialization_def) = match self
.env
.abilities_store .abilities_store
.get_resolved(*specialization_id) .get_resolved(*specialization_id)
{ {
@ -2823,8 +2849,8 @@ fn resolve_abilities_in_specialized_body<'a>(
), ),
None => { None => {
let specialization = resolve_ability_specialization( let specialization = resolve_ability_specialization(
self.subs, self.env.subs,
self.abilities_store, self.env.abilities_store,
*member_sym, *member_sym,
var, var,
) )
@ -2837,7 +2863,8 @@ fn resolve_abilities_in_specialized_body<'a>(
} }
}; };
self.abilities_store self.env
.abilities_store
.insert_resolved(*specialization_id, specialization); .insert_resolved(*specialization_id, specialization);
debug_assert!(!self.specialized.contains(specialization_id)); debug_assert!(!self.specialized.contains(specialization_id));
@ -2854,8 +2881,8 @@ fn resolve_abilities_in_specialized_body<'a>(
.expect("Specialization found, but it's not in procs"); .expect("Specialization found, but it's not in procs");
let specialization_var = specialization_def.annotation; let specialization_var = specialization_def.annotation;
let unified = unify(self.subs, var, specialization_var, Mode::EQ); let unified = self.env.unify(var, specialization_var);
unified.expect_success( unified.expect(
"Specialization does not unify - this is a typechecker bug!", "Specialization does not unify - this is a typechecker bug!",
); );
@ -2880,9 +2907,8 @@ fn resolve_abilities_in_specialized_body<'a>(
} }
let mut resolver = Resolver { let mut resolver = Resolver {
subs: env.subs, env,
procs, procs,
abilities_store: env.abilities_store,
seen_defs: MutSet::default(), seen_defs: MutSet::default(),
specialized: vec![], specialized: vec![],
}; };
@ -2907,12 +2933,7 @@ fn specialize_external<'a>(
let snapshot = env.subs.snapshot(); let snapshot = env.subs.snapshot();
let cache_snapshot = layout_cache.snapshot(); let cache_snapshot = layout_cache.snapshot();
let _unified = roc_unify::unify::unify( let _unified = env.unify(partial_proc.annotation, fn_var);
env.subs,
partial_proc.annotation,
fn_var,
roc_unify::unify::Mode::EQ,
);
// This will not hold for programs with type errors // This will not hold for programs with type errors
// let is_valid = matches!(unified, roc_unify::unify::Unified::Success(_)); // let is_valid = matches!(unified, roc_unify::unify::Unified::Success(_));

View file

@ -427,7 +427,7 @@ impl Env {
const DEFAULT_POOLS: usize = 8; const DEFAULT_POOLS: usize = 8;
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub(crate) struct Pools(Vec<Vec<Variable>>); pub struct Pools(Vec<Vec<Variable>>);
impl Default for Pools { impl Default for Pools {
fn default() -> Self { fn default() -> Self {
@ -553,7 +553,7 @@ fn run_in_place(
let (obligation_problems, _derived) = deferred_obligations.check_all(subs, abilities_store); let (obligation_problems, _derived) = deferred_obligations.check_all(subs, abilities_store);
problems.extend(obligation_problems); problems.extend(obligation_problems);
compact_deferred_lambda_sets( compact_lambda_sets_of_vars(
subs, subs,
&arena, &arena,
&mut pools, &mut pools,
@ -1761,7 +1761,7 @@ fn find_specialization_lambda_sets(
(leftover_uls, specialization_lambda_sets) (leftover_uls, specialization_lambda_sets)
} }
fn compact_deferred_lambda_sets( pub fn compact_lambda_sets_of_vars(
subs: &mut Subs, subs: &mut Subs,
arena: &Bump, arena: &Bump,
pools: &mut Pools, pools: &mut Pools,