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", "bumpalo",
"roc_can", "roc_can",
"roc_collections", "roc_collections",
"roc_derive_key",
"roc_module", "roc_module",
"roc_solve", "roc_solve",
"roc_types", "roc_types",
@ -3923,6 +3924,7 @@ dependencies = [
"roc_collections", "roc_collections",
"roc_constrain", "roc_constrain",
"roc_debug_flags", "roc_debug_flags",
"roc_derive_key",
"roc_error_macros", "roc_error_macros",
"roc_late_solve", "roc_late_solve",
"roc_module", "roc_module",
@ -4119,6 +4121,7 @@ dependencies = [
"roc_can", "roc_can",
"roc_collections", "roc_collections",
"roc_debug_flags", "roc_debug_flags",
"roc_derive_key",
"roc_error_macros", "roc_error_macros",
"roc_exhaustive", "roc_exhaustive",
"roc_load", "roc_load",

View file

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

View file

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

View file

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

View file

@ -13,6 +13,7 @@ roc_module = { path = "../module" }
roc_types = { path = "../types" } roc_types = { path = "../types" }
roc_can = { path = "../can" } roc_can = { path = "../can" }
roc_constrain = { path = "../constrain" } roc_constrain = { path = "../constrain" }
roc_derive_key = { path = "../derive_key" }
roc_builtins = { path = "../builtins" } roc_builtins = { path = "../builtins" }
roc_problem = { path = "../problem" } roc_problem = { path = "../problem" }
roc_unify = { path = "../unify" } 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_IR_AFTER_REFCOUNT, ROC_PRINT_IR_AFTER_RESET_REUSE, ROC_PRINT_IR_AFTER_SPECIALIZATION,
ROC_PRINT_LOAD_LOG, ROC_PRINT_LOAD_LOG,
}; };
use roc_derive_key::GlobalDerivedMethods;
use roc_error_macros::internal_error; use roc_error_macros::internal_error;
use roc_late_solve::{AbilitiesView, WorldAbilities}; use roc_late_solve::{AbilitiesView, WorldAbilities};
use roc_module::ident::{Ident, ModuleName, QualifiedModuleName}; use roc_module::ident::{Ident, ModuleName, QualifiedModuleName};
@ -372,6 +373,8 @@ fn start_phase<'a>(
.. ..
} = constrained; } = constrained;
let derived_methods = GlobalDerivedMethods::clone(&state.derived_methods);
BuildTask::solve_module( BuildTask::solve_module(
module, module,
ident_ids, ident_ids,
@ -385,6 +388,7 @@ fn start_phase<'a>(
dep_idents, dep_idents,
declarations, declarations,
state.cached_subs.clone(), state.cached_subs.clone(),
derived_methods,
) )
} }
Phase::FindSpecializations => { Phase::FindSpecializations => {
@ -412,6 +416,8 @@ fn start_phase<'a>(
} }
} }
let derived_methods = GlobalDerivedMethods::clone(&state.derived_methods);
BuildTask::BuildPendingSpecializations { BuildTask::BuildPendingSpecializations {
layout_cache, layout_cache,
module_id, module_id,
@ -422,6 +428,7 @@ fn start_phase<'a>(
ident_ids, ident_ids,
exposed_to_host: state.exposed_to_host.clone(), exposed_to_host: state.exposed_to_host.clone(),
abilities_store, abilities_store,
derived_methods,
} }
} }
Phase::MakeSpecializations => { Phase::MakeSpecializations => {
@ -479,6 +486,8 @@ fn start_phase<'a>(
(ident_ids, subs, procs_base, layout_cache, module_timing) (ident_ids, subs, procs_base, layout_cache, module_timing)
}; };
let derived_methods = GlobalDerivedMethods::clone(&state.derived_methods);
BuildTask::MakeSpecializations { BuildTask::MakeSpecializations {
module_id, module_id,
ident_ids, ident_ids,
@ -488,6 +497,7 @@ fn start_phase<'a>(
specializations_we_must_make, specializations_we_must_make,
module_timing, module_timing,
world_abilities: state.world_abilities.clone_ref(), 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<_>>! /// 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_modules: Arc<Mutex<PackageModuleIds<'a>>>,
pub arc_shorthands: Arc<Mutex<MutMap<&'a str, PackageName<'a>>>>, pub arc_shorthands: Arc<Mutex<MutMap<&'a str, PackageName<'a>>>>,
#[allow(unused)]
pub derived_methods: GlobalDerivedMethods,
pub ident_ids_by_module: SharedIdentIdsByModule, pub ident_ids_by_module: SharedIdentIdsByModule,
@ -854,6 +866,7 @@ impl<'a> State<'a> {
exposed_types, exposed_types,
arc_modules, arc_modules,
arc_shorthands, arc_shorthands,
derived_methods: Default::default(),
constrained_ident_ids: IdentIds::exposed_builtins(0), constrained_ident_ids: IdentIds::exposed_builtins(0),
ident_ids_by_module, ident_ids_by_module,
declarations_by_id: MutMap::default(), declarations_by_id: MutMap::default(),
@ -973,6 +986,7 @@ enum BuildTask<'a> {
declarations: Vec<Declaration>, declarations: Vec<Declaration>,
dep_idents: IdentIdsByModule, dep_idents: IdentIdsByModule,
cached_subs: CachedSubs, cached_subs: CachedSubs,
derived_methods: GlobalDerivedMethods,
}, },
BuildPendingSpecializations { BuildPendingSpecializations {
module_timing: ModuleTiming, module_timing: ModuleTiming,
@ -984,6 +998,7 @@ enum BuildTask<'a> {
decls: Vec<Declaration>, decls: Vec<Declaration>,
exposed_to_host: ExposedToHost, exposed_to_host: ExposedToHost,
abilities_store: AbilitiesStore, abilities_store: AbilitiesStore,
derived_methods: GlobalDerivedMethods,
}, },
MakeSpecializations { MakeSpecializations {
module_id: ModuleId, module_id: ModuleId,
@ -994,6 +1009,7 @@ enum BuildTask<'a> {
specializations_we_must_make: Vec<ExternalSpecializations>, specializations_we_must_make: Vec<ExternalSpecializations>,
module_timing: ModuleTiming, module_timing: ModuleTiming,
world_abilities: WorldAbilities, world_abilities: WorldAbilities,
derived_methods: GlobalDerivedMethods,
}, },
} }
@ -3719,6 +3735,7 @@ impl<'a> BuildTask<'a> {
dep_idents: IdentIdsByModule, dep_idents: IdentIdsByModule,
declarations: Vec<Declaration>, declarations: Vec<Declaration>,
cached_subs: CachedSubs, cached_subs: CachedSubs,
derived_methods: GlobalDerivedMethods,
) -> Self { ) -> Self {
let exposed_by_module = exposed_types.retain_modules(imported_modules.keys()); let exposed_by_module = exposed_types.retain_modules(imported_modules.keys());
@ -3746,6 +3763,7 @@ impl<'a> BuildTask<'a> {
dep_idents, dep_idents,
module_timing, module_timing,
cached_subs, cached_subs,
derived_methods,
} }
} }
} }
@ -3876,6 +3894,7 @@ fn run_solve_solve(
pending_derives: PendingDerives, pending_derives: PendingDerives,
mut var_store: VarStore, mut var_store: VarStore,
module: Module, module: Module,
derived_methods: GlobalDerivedMethods,
) -> ( ) -> (
Solved<Subs>, Solved<Subs>,
ResolvedSpecializations, ResolvedSpecializations,
@ -3923,6 +3942,7 @@ fn run_solve_solve(
solve_aliases, solve_aliases,
abilities_store, abilities_store,
pending_derives, pending_derives,
derived_methods,
); );
let module_id = module.module_id; let module_id = module.module_id;
@ -3979,6 +3999,7 @@ fn run_solve<'a>(
decls: Vec<Declaration>, decls: Vec<Declaration>,
dep_idents: IdentIdsByModule, dep_idents: IdentIdsByModule,
cached_subs: CachedSubs, cached_subs: CachedSubs,
derived_methods: GlobalDerivedMethods,
) -> Msg<'a> { ) -> Msg<'a> {
let solve_start = SystemTime::now(); let solve_start = SystemTime::now();
@ -3998,6 +4019,7 @@ fn run_solve<'a>(
pending_derives, pending_derives,
var_store, var_store,
module, module,
derived_methods,
), ),
Some((subs, exposed_vars_by_symbol)) => { Some((subs, exposed_vars_by_symbol)) => {
( (
@ -4020,6 +4042,7 @@ fn run_solve<'a>(
pending_derives, pending_derives,
var_store, var_store,
module, module,
derived_methods,
) )
} }
}; };
@ -4375,6 +4398,7 @@ fn make_specializations<'a>(
mut module_timing: ModuleTiming, mut module_timing: ModuleTiming,
target_info: TargetInfo, target_info: TargetInfo,
world_abilities: WorldAbilities, world_abilities: WorldAbilities,
derived_methods: GlobalDerivedMethods,
) -> Msg<'a> { ) -> Msg<'a> {
let make_specializations_start = SystemTime::now(); let make_specializations_start = SystemTime::now();
let mut update_mode_ids = UpdateModeIds::new(); let mut update_mode_ids = UpdateModeIds::new();
@ -4389,6 +4413,7 @@ fn make_specializations<'a>(
// call_specialization_counter=0 is reserved // call_specialization_counter=0 is reserved
call_specialization_counter: 1, call_specialization_counter: 1,
abilities: AbilitiesView::World(world_abilities), abilities: AbilitiesView::World(world_abilities),
derived_methods: &derived_methods,
}; };
let mut procs = Procs::new_in(arena); let mut procs = Procs::new_in(arena);
@ -4449,9 +4474,9 @@ fn build_pending_specializations<'a>(
mut module_timing: ModuleTiming, mut module_timing: ModuleTiming,
mut layout_cache: LayoutCache<'a>, mut layout_cache: LayoutCache<'a>,
target_info: TargetInfo, target_info: TargetInfo,
// TODO remove exposed_to_host: ExposedToHost, // TODO remove
exposed_to_host: ExposedToHost,
abilities_store: AbilitiesStore, abilities_store: AbilitiesStore,
derived_methods: GlobalDerivedMethods,
) -> Msg<'a> { ) -> Msg<'a> {
let find_specializations_start = SystemTime::now(); 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 // to know the types and abilities in our modules. Only for building *all* specializations
// do we need a global view. // do we need a global view.
abilities: AbilitiesView::Module(&abilities_store), abilities: AbilitiesView::Module(&abilities_store),
derived_methods: &derived_methods,
}; };
// Add modules' decls to Procs // Add modules' decls to Procs
@ -4747,6 +4773,7 @@ fn run_task<'a>(
declarations, declarations,
dep_idents, dep_idents,
cached_subs, cached_subs,
derived_methods,
} => Ok(run_solve( } => Ok(run_solve(
module, module,
ident_ids, ident_ids,
@ -4760,6 +4787,7 @@ fn run_task<'a>(
declarations, declarations,
dep_idents, dep_idents,
cached_subs, cached_subs,
derived_methods,
)), )),
BuildPendingSpecializations { BuildPendingSpecializations {
module_id, module_id,
@ -4771,6 +4799,7 @@ fn run_task<'a>(
imported_module_thunks, imported_module_thunks,
exposed_to_host, exposed_to_host,
abilities_store, abilities_store,
derived_methods,
} => Ok(build_pending_specializations( } => Ok(build_pending_specializations(
arena, arena,
solved_subs, solved_subs,
@ -4783,6 +4812,7 @@ fn run_task<'a>(
target_info, target_info,
exposed_to_host, exposed_to_host,
abilities_store, abilities_store,
derived_methods,
)), )),
MakeSpecializations { MakeSpecializations {
module_id, module_id,
@ -4793,6 +4823,7 @@ fn run_task<'a>(
specializations_we_must_make, specializations_we_must_make,
module_timing, module_timing,
world_abilities, world_abilities,
derived_methods,
} => Ok(make_specializations( } => Ok(make_specializations(
arena, arena,
module_id, module_id,
@ -4804,6 +4835,7 @@ fn run_task<'a>(
module_timing, module_timing,
target_info, target_info,
world_abilities, 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_can::pattern::Pattern;
use roc_collections::SendMap; use roc_collections::SendMap;
use roc_derive_key::encoding::FlatEncodableKey; use roc_derive_key::encoding::FlatEncodableKey;
use roc_derive_key::GlobalDerivedMethods;
use roc_error_macros::internal_error; use roc_error_macros::internal_error;
use roc_late_solve::{instantiate_rigids, AbilitiesView}; use roc_late_solve::{instantiate_rigids, AbilitiesView};
use roc_module::called_via::CalledVia; use roc_module::called_via::CalledVia;
@ -43,6 +44,7 @@ pub struct Env<'a> {
pub subs: &'a mut Subs, pub subs: &'a mut Subs,
pub ident_ids: &'a mut IdentIds, pub ident_ids: &'a mut IdentIds,
pub exposed_encode_types: &'a mut ExposedTypesStorageSubs, pub exposed_encode_types: &'a mut ExposedTypesStorageSubs,
pub derived_methods: &'a GlobalDerivedMethods,
} }
impl Env<'_> { impl Env<'_> {
@ -78,6 +80,7 @@ impl Env<'_> {
self.arena, self.arena,
self.subs, self.subs,
&AbilitiesView::Module(&AbilitiesStore::default()), &AbilitiesView::Module(&AbilitiesStore::default()),
self.derived_methods,
left, left,
right, right,
) )

View file

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

View file

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

View file

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

View file

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