mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-27 22:09:09 +00:00
Lambda set compaction in mono
This commit is contained in:
parent
db479cbcc2
commit
201853ecca
2 changed files with 47 additions and 26 deletions
|
@ -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(_));
|
||||||
|
|
|
@ -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,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue