Thread derived methods map through solve and mono for use in compaction

This commit is contained in:
Ayaz Hafiz 2022-06-21 09:32:01 -04:00
parent c9d828c284
commit a429835da4
No known key found for this signature in database
GPG key ID: 0E2A37416A25EF58
11 changed files with 99 additions and 20 deletions

3
Cargo.lock generated
View file

@ -3869,6 +3869,7 @@ dependencies = [
"bumpalo",
"roc_can",
"roc_collections",
"roc_derive_key",
"roc_module",
"roc_solve",
"roc_types",
@ -3923,6 +3924,7 @@ dependencies = [
"roc_collections",
"roc_constrain",
"roc_debug_flags",
"roc_derive_key",
"roc_error_macros",
"roc_late_solve",
"roc_module",
@ -4119,6 +4121,7 @@ dependencies = [
"roc_can",
"roc_collections",
"roc_debug_flags",
"roc_derive_key",
"roc_error_macros",
"roc_exhaustive",
"roc_load",

View file

@ -15,6 +15,8 @@
pub mod encoding;
use std::sync::{Arc, RwLock};
use encoding::{FlatEncodable, FlatEncodableKey};
use roc_collections::MutMap;
@ -50,19 +52,13 @@ impl Derived {
}
/// Map of [`DeriveKey`]s to their derived symbols.
#[derive(Debug, Default)]
pub struct DerivedMethods {
map: MutMap<DeriveKey, Symbol>,
derived_ident_ids: IdentIds,
}
impl DerivedMethods {
pub fn new(derived_ident_ids: IdentIds) -> Self {
Self {
map: MutMap::default(),
derived_ident_ids,
}
}
pub fn get_or_insert(&mut self, key: DeriveKey) -> Symbol {
let symbol = self.map.entry(key).or_insert_with(|| {
let ident_id = self.derived_ident_ids.gen_unique();
@ -72,3 +68,6 @@ impl DerivedMethods {
*symbol
}
}
/// Thread-sharable [`DerivedMethods`].
pub type GlobalDerivedMethods = Arc<RwLock<DerivedMethods>>;

View file

@ -8,6 +8,7 @@ edition = "2021"
[dependencies]
roc_types = { path = "../types" }
roc_can = { path = "../can" }
roc_derive_key = { path = "../derive_key" }
roc_module = { path = "../module" }
roc_unify = { path = "../unify" }
roc_solve = { path = "../solve" }

View file

@ -6,6 +6,7 @@ use std::sync::{Arc, RwLock};
use bumpalo::Bump;
use roc_can::abilities::AbilitiesStore;
use roc_collections::MutMap;
use roc_derive_key::GlobalDerivedMethods;
use roc_module::symbol::ModuleId;
use roc_solve::solve::{compact_lambda_sets_of_vars, Phase, Pools};
use roc_types::subs::Content;
@ -136,6 +137,7 @@ pub fn unify(
arena: &Bump,
subs: &mut Subs,
abilities: &AbilitiesView,
derived_methods: &GlobalDerivedMethods,
left: Variable,
right: Variable,
) -> Result<(), UnificationFailed> {
@ -157,6 +159,7 @@ pub fn unify(
&mut pools,
lambda_sets_to_specialize,
&late_phase,
derived_methods,
);
// Pools are only used to keep track of variable ranks for generalization purposes.
// Since we break generalization during monomorphization, `pools` is irrelevant

View file

@ -13,6 +13,7 @@ roc_module = { path = "../module" }
roc_types = { path = "../types" }
roc_can = { path = "../can" }
roc_constrain = { path = "../constrain" }
roc_derive_key = { path = "../derive_key" }
roc_builtins = { path = "../builtins" }
roc_problem = { path = "../problem" }
roc_unify = { path = "../unify" }

View file

@ -22,6 +22,7 @@ use roc_debug_flags::{
ROC_PRINT_IR_AFTER_REFCOUNT, ROC_PRINT_IR_AFTER_RESET_REUSE, ROC_PRINT_IR_AFTER_SPECIALIZATION,
ROC_PRINT_LOAD_LOG,
};
use roc_derive_key::GlobalDerivedMethods;
use roc_error_macros::internal_error;
use roc_late_solve::{AbilitiesView, WorldAbilities};
use roc_module::ident::{Ident, ModuleName, QualifiedModuleName};
@ -372,6 +373,8 @@ fn start_phase<'a>(
..
} = constrained;
let derived_methods = GlobalDerivedMethods::clone(&state.derived_methods);
BuildTask::solve_module(
module,
ident_ids,
@ -385,6 +388,7 @@ fn start_phase<'a>(
dep_idents,
declarations,
state.cached_subs.clone(),
derived_methods,
)
}
Phase::FindSpecializations => {
@ -412,6 +416,8 @@ fn start_phase<'a>(
}
}
let derived_methods = GlobalDerivedMethods::clone(&state.derived_methods);
BuildTask::BuildPendingSpecializations {
layout_cache,
module_id,
@ -422,6 +428,7 @@ fn start_phase<'a>(
ident_ids,
exposed_to_host: state.exposed_to_host.clone(),
abilities_store,
derived_methods,
}
}
Phase::MakeSpecializations => {
@ -479,6 +486,8 @@ fn start_phase<'a>(
(ident_ids, subs, procs_base, layout_cache, module_timing)
};
let derived_methods = GlobalDerivedMethods::clone(&state.derived_methods);
BuildTask::MakeSpecializations {
module_id,
ident_ids,
@ -488,6 +497,7 @@ fn start_phase<'a>(
specializations_we_must_make,
module_timing,
world_abilities: state.world_abilities.clone_ref(),
derived_methods,
}
}
}
@ -795,6 +805,8 @@ struct State<'a> {
/// From now on, these will be used by multiple threads; time to make an Arc<Mutex<_>>!
pub arc_modules: Arc<Mutex<PackageModuleIds<'a>>>,
pub arc_shorthands: Arc<Mutex<MutMap<&'a str, PackageName<'a>>>>,
#[allow(unused)]
pub derived_methods: GlobalDerivedMethods,
pub ident_ids_by_module: SharedIdentIdsByModule,
@ -854,6 +866,7 @@ impl<'a> State<'a> {
exposed_types,
arc_modules,
arc_shorthands,
derived_methods: Default::default(),
constrained_ident_ids: IdentIds::exposed_builtins(0),
ident_ids_by_module,
declarations_by_id: MutMap::default(),
@ -973,6 +986,7 @@ enum BuildTask<'a> {
declarations: Vec<Declaration>,
dep_idents: IdentIdsByModule,
cached_subs: CachedSubs,
derived_methods: GlobalDerivedMethods,
},
BuildPendingSpecializations {
module_timing: ModuleTiming,
@ -984,6 +998,7 @@ enum BuildTask<'a> {
decls: Vec<Declaration>,
exposed_to_host: ExposedToHost,
abilities_store: AbilitiesStore,
derived_methods: GlobalDerivedMethods,
},
MakeSpecializations {
module_id: ModuleId,
@ -994,6 +1009,7 @@ enum BuildTask<'a> {
specializations_we_must_make: Vec<ExternalSpecializations>,
module_timing: ModuleTiming,
world_abilities: WorldAbilities,
derived_methods: GlobalDerivedMethods,
},
}
@ -3719,6 +3735,7 @@ impl<'a> BuildTask<'a> {
dep_idents: IdentIdsByModule,
declarations: Vec<Declaration>,
cached_subs: CachedSubs,
derived_methods: GlobalDerivedMethods,
) -> Self {
let exposed_by_module = exposed_types.retain_modules(imported_modules.keys());
@ -3746,6 +3763,7 @@ impl<'a> BuildTask<'a> {
dep_idents,
module_timing,
cached_subs,
derived_methods,
}
}
}
@ -3876,6 +3894,7 @@ fn run_solve_solve(
pending_derives: PendingDerives,
mut var_store: VarStore,
module: Module,
derived_methods: GlobalDerivedMethods,
) -> (
Solved<Subs>,
ResolvedSpecializations,
@ -3923,6 +3942,7 @@ fn run_solve_solve(
solve_aliases,
abilities_store,
pending_derives,
derived_methods,
);
let module_id = module.module_id;
@ -3979,6 +3999,7 @@ fn run_solve<'a>(
decls: Vec<Declaration>,
dep_idents: IdentIdsByModule,
cached_subs: CachedSubs,
derived_methods: GlobalDerivedMethods,
) -> Msg<'a> {
let solve_start = SystemTime::now();
@ -3998,6 +4019,7 @@ fn run_solve<'a>(
pending_derives,
var_store,
module,
derived_methods,
),
Some((subs, exposed_vars_by_symbol)) => {
(
@ -4020,6 +4042,7 @@ fn run_solve<'a>(
pending_derives,
var_store,
module,
derived_methods,
)
}
};
@ -4375,6 +4398,7 @@ fn make_specializations<'a>(
mut module_timing: ModuleTiming,
target_info: TargetInfo,
world_abilities: WorldAbilities,
derived_methods: GlobalDerivedMethods,
) -> Msg<'a> {
let make_specializations_start = SystemTime::now();
let mut update_mode_ids = UpdateModeIds::new();
@ -4389,6 +4413,7 @@ fn make_specializations<'a>(
// call_specialization_counter=0 is reserved
call_specialization_counter: 1,
abilities: AbilitiesView::World(world_abilities),
derived_methods: &derived_methods,
};
let mut procs = Procs::new_in(arena);
@ -4449,9 +4474,9 @@ fn build_pending_specializations<'a>(
mut module_timing: ModuleTiming,
mut layout_cache: LayoutCache<'a>,
target_info: TargetInfo,
// TODO remove
exposed_to_host: ExposedToHost,
exposed_to_host: ExposedToHost, // TODO remove
abilities_store: AbilitiesStore,
derived_methods: GlobalDerivedMethods,
) -> Msg<'a> {
let find_specializations_start = SystemTime::now();
@ -4480,6 +4505,7 @@ fn build_pending_specializations<'a>(
// to know the types and abilities in our modules. Only for building *all* specializations
// do we need a global view.
abilities: AbilitiesView::Module(&abilities_store),
derived_methods: &derived_methods,
};
// Add modules' decls to Procs
@ -4747,6 +4773,7 @@ fn run_task<'a>(
declarations,
dep_idents,
cached_subs,
derived_methods,
} => Ok(run_solve(
module,
ident_ids,
@ -4760,6 +4787,7 @@ fn run_task<'a>(
declarations,
dep_idents,
cached_subs,
derived_methods,
)),
BuildPendingSpecializations {
module_id,
@ -4771,6 +4799,7 @@ fn run_task<'a>(
imported_module_thunks,
exposed_to_host,
abilities_store,
derived_methods,
} => Ok(build_pending_specializations(
arena,
solved_subs,
@ -4783,6 +4812,7 @@ fn run_task<'a>(
target_info,
exposed_to_host,
abilities_store,
derived_methods,
)),
MakeSpecializations {
module_id,
@ -4793,6 +4823,7 @@ fn run_task<'a>(
specializations_we_must_make,
module_timing,
world_abilities,
derived_methods,
} => Ok(make_specializations(
arena,
module_id,
@ -4804,6 +4835,7 @@ fn run_task<'a>(
module_timing,
target_info,
world_abilities,
derived_methods,
)),
}?;

View file

@ -9,6 +9,7 @@ use roc_can::expr::{AnnotatedMark, ClosureData, Expr, Field, Recursive, WhenBran
use roc_can::pattern::Pattern;
use roc_collections::SendMap;
use roc_derive_key::encoding::FlatEncodableKey;
use roc_derive_key::GlobalDerivedMethods;
use roc_error_macros::internal_error;
use roc_late_solve::{instantiate_rigids, AbilitiesView};
use roc_module::called_via::CalledVia;
@ -43,6 +44,7 @@ pub struct Env<'a> {
pub subs: &'a mut Subs,
pub ident_ids: &'a mut IdentIds,
pub exposed_encode_types: &'a mut ExposedTypesStorageSubs,
pub derived_methods: &'a GlobalDerivedMethods,
}
impl Env<'_> {
@ -78,6 +80,7 @@ impl Env<'_> {
self.arena,
self.subs,
&AbilitiesView::Module(&AbilitiesStore::default()),
self.derived_methods,
left,
right,
)

View file

@ -16,6 +16,7 @@ use roc_debug_flags::dbg_do;
use roc_debug_flags::{
ROC_PRINT_IR_AFTER_REFCOUNT, ROC_PRINT_IR_AFTER_RESET_REUSE, ROC_PRINT_IR_AFTER_SPECIALIZATION,
};
use roc_derive_key::GlobalDerivedMethods;
use roc_error_macros::todo_abilities;
use roc_exhaustive::{Ctor, CtorName, Guard, RenderAs, TagId};
use roc_late_solve::{
@ -1269,6 +1270,7 @@ pub struct Env<'a, 'i> {
pub update_mode_ids: &'i mut UpdateModeIds,
pub call_specialization_counter: u32,
pub abilities: AbilitiesView<'i>,
pub derived_methods: &'i GlobalDerivedMethods,
}
impl<'a, 'i> Env<'a, 'i> {
@ -1304,6 +1306,7 @@ impl<'a, 'i> Env<'a, 'i> {
self.arena,
self.subs,
&self.abilities,
self.derived_methods,
left,
right,
)

View file

@ -13,6 +13,7 @@ roc_region = { path = "../region" }
roc_module = { path = "../module" }
roc_types = { path = "../types" }
roc_can = { path = "../can" }
roc_derive_key = { path = "../derive_key" }
roc_problem = { path = "../problem" }
roc_unify = { path = "../unify" }
roc_debug_flags = { path = "../debug_flags" }

View file

@ -5,6 +5,7 @@ use roc_can::expr::PendingDerives;
use roc_can::module::RigidVariables;
use roc_collections::all::MutMap;
use roc_collections::VecMap;
use roc_derive_key::GlobalDerivedMethods;
use roc_module::symbol::Symbol;
use roc_types::solved_types::Solved;
use roc_types::subs::{ExposedTypesStorageSubs, StorageSubs, Subs, Variable};
@ -40,6 +41,7 @@ pub fn run_solve(
mut aliases: Aliases,
mut abilities_store: AbilitiesStore,
pending_derives: PendingDerives,
derived_methods: GlobalDerivedMethods,
) -> (
Solved<Subs>,
solve::Env,
@ -71,6 +73,7 @@ pub fn run_solve(
&constraint,
pending_derives,
&mut abilities_store,
derived_methods,
);
(solved_subs, solved_env, problems, abilities_store)

View file

@ -13,6 +13,7 @@ use roc_collections::VecSet;
use roc_debug_flags::dbg_do;
#[cfg(debug_assertions)]
use roc_debug_flags::ROC_VERIFY_RIGID_LET_GENERALIZED;
use roc_derive_key::{Derived, GlobalDerivedMethods};
use roc_error_macros::internal_error;
use roc_module::ident::TagName;
use roc_module::symbol::{ModuleId, Symbol};
@ -550,6 +551,7 @@ pub fn run(
constraint: &Constraint,
pending_derives: PendingDerives,
abilities_store: &mut AbilitiesStore,
derived_methods: GlobalDerivedMethods,
) -> (Solved<Subs>, Env) {
let env = run_in_place(
constraints,
@ -559,6 +561,7 @@ pub fn run(
constraint,
pending_derives,
abilities_store,
derived_methods,
);
(Solved(subs), env)
@ -573,6 +576,7 @@ fn run_in_place(
constraint: &Constraint,
pending_derives: PendingDerives,
abilities_store: &mut AbilitiesStore,
derived_methods: GlobalDerivedMethods,
) -> Env {
let mut pools = Pools::default();
@ -617,6 +621,7 @@ fn run_in_place(
&mut pools,
deferred_uls_to_resolve,
&SolvePhase { abilities_store },
&derived_methods,
);
state.env
@ -1748,6 +1753,7 @@ pub fn compact_lambda_sets_of_vars<P: Phase>(
pools: &mut Pools,
uls_of_var: UlsOfVar,
phase: &P,
derived_methods: &GlobalDerivedMethods,
) {
let mut seen = VecSet::default();
for (_, lambda_sets) in uls_of_var.drain() {
@ -1757,7 +1763,7 @@ pub fn compact_lambda_sets_of_vars<P: Phase>(
continue;
}
compact_lambda_set(subs, arena, pools, root_lset, phase);
compact_lambda_set(subs, arena, pools, root_lset, phase, derived_methods);
seen.insert(root_lset);
}
@ -1770,6 +1776,7 @@ fn compact_lambda_set<P: Phase>(
pools: &mut Pools,
this_lambda_set: Variable,
phase: &P,
derived_methods: &GlobalDerivedMethods,
) {
let LambdaSet {
solved,
@ -1795,14 +1802,30 @@ fn compact_lambda_set<P: Phase>(
continue;
}
Structure(_) | Alias(_, _, _, AliasKind::Structural) => {
// TODO: figure out a convention for references to structural types in the
// unspecialized lambda set. This may very well happen, for example
//
// Default has default : {} -> a | a has Default
//
// {a, b} = default {}
// # ^^^^^^^ {} -[{a: t1, b: t2}:default:1]-> {a: t1, b: t2}
new_unspecialized.push(uls);
// This is a structural type, find the name of the derived ability function it
// should use.
let specialization_symbol = match Derived::encoding(subs, var) {
Derived::Immediate(symbol) => symbol,
Derived::Key(derive_key) => {
let mut derived_methods = derived_methods.write().unwrap();
derived_methods.get_or_insert(derive_key)
}
};
let specialization_symbol_slice =
UnionLabels::insert_into_subs(subs, vec![(specialization_symbol, vec![])]);
let lambda_set_for_derived = subs.fresh(Descriptor {
content: LambdaSet(subs::LambdaSet {
solved: specialization_symbol_slice,
recursion_var: OptVariable::NONE,
unspecialized: SubsSlice::default(),
}),
rank: target_rank,
mark: Mark::NONE,
copy: OptVariable::NONE,
});
specialized_to_unify_with.push(lambda_set_for_derived);
continue;
}
Alias(opaque, _, _, AliasKind::Opaque) => opaque,
@ -1864,7 +1887,14 @@ fn compact_lambda_set<P: Phase>(
// Ensure the specialization lambda set is already compacted.
if subs.get_root_key(specialized_lambda_set) != subs.get_root_key(this_lambda_set) {
compact_lambda_set(subs, arena, pools, specialized_lambda_set, phase);
compact_lambda_set(
subs,
arena,
pools,
specialized_lambda_set,
phase,
derived_methods,
);
}
// Ensure the specialization lambda set we'll unify with is not a generalized one, but one
@ -1889,7 +1919,7 @@ fn compact_lambda_set<P: Phase>(
unify(subs, this_lambda_set, other_specialized, Mode::EQ)
.expect_success("lambda sets don't unify");
introduce(subs, subs.get_rank(this_lambda_set), pools, &vars);
introduce(subs, target_rank, pools, &vars);
debug_assert!(
must_implement_ability.is_empty(),