mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-18 17:49:47 +00:00
Use Derived_synth for synthesizing implementations, and Derived_gen for codegen
This commit is contained in:
parent
7c2e806a02
commit
df9bcb1a0c
16 changed files with 1543 additions and 628 deletions
|
@ -14,7 +14,7 @@ use roc_collections::all::MutMap;
|
|||
use roc_debug_flags::dbg_do;
|
||||
#[cfg(debug_assertions)]
|
||||
use roc_debug_flags::{ROC_TRACE_COMPACTION, ROC_VERIFY_RIGID_LET_GENERALIZED};
|
||||
use roc_derive::{DerivedModule, SharedDerivedModule};
|
||||
use roc_derive::SharedDerivedModule;
|
||||
use roc_derive_key::{DeriveError, DeriveKey};
|
||||
use roc_error_macros::internal_error;
|
||||
use roc_module::ident::TagName;
|
||||
|
@ -575,7 +575,7 @@ pub fn run(
|
|||
/// Modify an existing subs in-place instead
|
||||
#[allow(clippy::too_many_arguments)] // TODO: put params in a context/env var
|
||||
fn run_in_place(
|
||||
home: ModuleId,
|
||||
_home: ModuleId, // TODO: remove me?
|
||||
constraints: &Constraints,
|
||||
problems: &mut Vec<TypeError>,
|
||||
subs: &mut Subs,
|
||||
|
@ -620,10 +620,9 @@ fn run_in_place(
|
|||
// Now that the module has been solved, we can run through and check all
|
||||
// types claimed to implement abilities. This will also tell us what derives
|
||||
// are legal, which we need to register.
|
||||
let mut subs_proxy = SubsProxy::new(home, subs, &derived_module);
|
||||
|
||||
let new_must_implement = compact_lambda_sets_of_vars(
|
||||
&mut subs_proxy,
|
||||
subs,
|
||||
&derived_module,
|
||||
&arena,
|
||||
&mut pools,
|
||||
deferred_uls_to_resolve,
|
||||
|
@ -1763,70 +1762,6 @@ fn check_ability_specialization(
|
|||
}
|
||||
}
|
||||
|
||||
/// A proxy for managing [`Subs`] and the derived module, in the presence of possibly having to
|
||||
/// solve within the derived module's subs.
|
||||
// TODO remove this, how can we make this better?
|
||||
pub struct SubsProxy<'a> {
|
||||
home: ModuleId,
|
||||
subs: &'a mut Subs,
|
||||
derived_module: &'a SharedDerivedModule,
|
||||
}
|
||||
|
||||
impl<'a> SubsProxy<'a> {
|
||||
/// Creates a new subs proxy with the derived module.
|
||||
/// The contract is:
|
||||
/// - `subs` is for the `home` module
|
||||
/// - if `home` is the derived module, then the derived module is not in a stolen state
|
||||
pub fn new(
|
||||
home: ModuleId,
|
||||
subs: &'a mut Subs,
|
||||
derived_module: &'a SharedDerivedModule,
|
||||
) -> Self {
|
||||
Self {
|
||||
home,
|
||||
subs,
|
||||
derived_module,
|
||||
}
|
||||
}
|
||||
|
||||
fn with_subs<T, F>(&mut self, f: F) -> T
|
||||
where
|
||||
F: FnOnce(&mut Subs) -> T,
|
||||
{
|
||||
if self.home != ModuleId::DERIVED {
|
||||
f(self.subs)
|
||||
} else {
|
||||
let mut derived_module = self.derived_module.lock().unwrap();
|
||||
let mut stolen = derived_module.steal();
|
||||
let result = f(&mut stolen.subs);
|
||||
derived_module.return_stolen(stolen);
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
fn with_derived<T, F>(&mut self, f: F) -> T
|
||||
where
|
||||
F: FnOnce(&mut DerivedModule) -> T,
|
||||
{
|
||||
let mut derived_module = self.derived_module.lock().unwrap();
|
||||
f(&mut derived_module)
|
||||
}
|
||||
|
||||
fn copy_lambda_set_ambient_function_from_derived_to_subs(
|
||||
&mut self,
|
||||
lambda_set_var_in_derived: Variable,
|
||||
target_rank: Rank,
|
||||
) -> Variable {
|
||||
let derived_module = self.derived_module.lock().unwrap();
|
||||
derived_module.copy_lambda_set_ambient_function_to_subs(
|
||||
lambda_set_var_in_derived,
|
||||
self.home,
|
||||
self.subs,
|
||||
target_rank,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
fn trace_compaction_step_1(subs: &Subs, c_a: Variable, uls_a: &[Variable]) {
|
||||
let c_a = roc_types::subs::SubsFmtContent(subs.get_content_without_compacting(c_a), subs);
|
||||
|
@ -1949,7 +1884,8 @@ fn unique_unspecialized_lambda(subs: &Subs, c_a: Variable, uls: &[Uls]) -> Optio
|
|||
|
||||
#[must_use]
|
||||
pub fn compact_lambda_sets_of_vars<P: Phase>(
|
||||
subs_proxy: &mut SubsProxy,
|
||||
subs: &mut Subs,
|
||||
derived_module: &SharedDerivedModule,
|
||||
arena: &Bump,
|
||||
pools: &mut Pools,
|
||||
uls_of_var: UlsOfVar,
|
||||
|
@ -1964,111 +1900,108 @@ pub fn compact_lambda_sets_of_vars<P: Phase>(
|
|||
|
||||
// Suppose a type variable `a` with `uls_of_var` mapping `uls_a = {l1, ... ln}` has been instantiated to a concrete type `C_a`.
|
||||
while let Some((c_a, uls_a)) = uls_of_var_queue.pop_front() {
|
||||
let uls_a = subs_proxy.with_subs(|subs| {
|
||||
let c_a = subs.get_root_key_without_compacting(c_a);
|
||||
// 1. Let each `l` in `uls_a` be of form `[solved_lambdas + ... + C:f:r + ...]`.
|
||||
// NB: There may be multiple unspecialized lambdas of form `C:f:r, C:f1:r1, ..., C:fn:rn` in `l`.
|
||||
// In this case, let `t1, ... tm` be the other unspecialized lambdas not of form `C:_:_`,
|
||||
// that is, none of which are now specialized to the type `C`. Then, deconstruct
|
||||
// `l` such that `l' = [solved_lambdas + t1 + ... + tm + C:f:r]` and `l1 = [[] + C:f1:r1], ..., ln = [[] + C:fn:rn]`.
|
||||
// Replace `l` with `l', l1, ..., ln` in `uls_a`, flattened.
|
||||
// TODO: the flattening step described above
|
||||
let uls_a = uls_a.into_vec();
|
||||
trace_compact!(1. subs, c_a, &uls_a);
|
||||
let c_a = subs.get_root_key_without_compacting(c_a);
|
||||
// 1. Let each `l` in `uls_a` be of form `[solved_lambdas + ... + C:f:r + ...]`.
|
||||
// NB: There may be multiple unspecialized lambdas of form `C:f:r, C:f1:r1, ..., C:fn:rn` in `l`.
|
||||
// In this case, let `t1, ... tm` be the other unspecialized lambdas not of form `C:_:_`,
|
||||
// that is, none of which are now specialized to the type `C`. Then, deconstruct
|
||||
// `l` such that `l' = [solved_lambdas + t1 + ... + tm + C:f:r]` and `l1 = [[] + C:f1:r1], ..., ln = [[] + C:fn:rn]`.
|
||||
// Replace `l` with `l', l1, ..., ln` in `uls_a`, flattened.
|
||||
// TODO: the flattening step described above
|
||||
let uls_a = uls_a.into_vec();
|
||||
trace_compact!(1. subs, c_a, &uls_a);
|
||||
|
||||
// The flattening step - remove lambda sets that don't reference the concrete var, and for
|
||||
// flatten lambda sets that reference it more than once.
|
||||
let mut uls_a: Vec<_> = uls_a
|
||||
.into_iter()
|
||||
.flat_map(|lambda_set| {
|
||||
let LambdaSet {
|
||||
solved,
|
||||
recursion_var,
|
||||
unspecialized,
|
||||
ambient_function,
|
||||
} = subs.get_lambda_set(lambda_set);
|
||||
let lambda_set_rank = subs.get_rank(lambda_set);
|
||||
let unspecialized = subs.get_subs_slice(unspecialized);
|
||||
// TODO: is it faster to traverse once, see if we only have one concrete lambda, and
|
||||
// bail in that happy-path, rather than always splitting?
|
||||
let (concrete, mut not_concrete): (Vec<_>, Vec<_>) = unspecialized
|
||||
.iter()
|
||||
.copied()
|
||||
.partition(|Uls(var, _, _)| subs.equivalent_without_compacting(*var, c_a));
|
||||
if concrete.len() == 1 {
|
||||
// No flattening needs to be done, just return the lambda set as-is
|
||||
return vec![lambda_set];
|
||||
}
|
||||
// Must flatten
|
||||
concrete
|
||||
.into_iter()
|
||||
.enumerate()
|
||||
.map(|(i, concrete_lambda)| {
|
||||
let (var, unspecialized) = if i == 0 {
|
||||
// The first lambda set contains one concrete lambda, plus all solved
|
||||
// lambdas, plus all other unspecialized lambdas.
|
||||
// l' = [solved_lambdas + t1 + ... + tm + C:f:r]
|
||||
let unspecialized = SubsSlice::extend_new(
|
||||
&mut subs.unspecialized_lambda_sets,
|
||||
not_concrete
|
||||
.drain(..)
|
||||
.chain(std::iter::once(concrete_lambda)),
|
||||
);
|
||||
(lambda_set, unspecialized)
|
||||
} else {
|
||||
// All the other lambda sets consists only of their respective concrete
|
||||
// lambdas.
|
||||
// ln = [[] + C:fn:rn]
|
||||
let unspecialized = SubsSlice::extend_new(
|
||||
&mut subs.unspecialized_lambda_sets,
|
||||
[concrete_lambda],
|
||||
);
|
||||
let var = subs.fresh(Descriptor {
|
||||
content: Content::Error,
|
||||
rank: lambda_set_rank,
|
||||
mark: Mark::NONE,
|
||||
copy: OptVariable::NONE,
|
||||
});
|
||||
(var, unspecialized)
|
||||
};
|
||||
|
||||
subs.set_content(
|
||||
var,
|
||||
Content::LambdaSet(LambdaSet {
|
||||
solved,
|
||||
recursion_var,
|
||||
unspecialized,
|
||||
ambient_function,
|
||||
}),
|
||||
);
|
||||
var
|
||||
})
|
||||
.collect()
|
||||
})
|
||||
.collect();
|
||||
|
||||
// 2. Now, each `l` in `uls_a` has a unique unspecialized lambda of form `C:f:r`.
|
||||
// Sort `uls_a` primarily by `f` (arbitrary order), and secondarily by `r` in descending order.
|
||||
uls_a.sort_by(|v1, v2| {
|
||||
let unspec_1 = subs.get_subs_slice(subs.get_lambda_set(*v1).unspecialized);
|
||||
let unspec_2 = subs.get_subs_slice(subs.get_lambda_set(*v2).unspecialized);
|
||||
|
||||
let Uls(_, f1, r1) = unique_unspecialized_lambda(subs, c_a, unspec_1).unwrap();
|
||||
let Uls(_, f2, r2) = unique_unspecialized_lambda(subs, c_a, unspec_2).unwrap();
|
||||
|
||||
match f1.cmp(&f2) {
|
||||
std::cmp::Ordering::Equal => {
|
||||
// Order by descending order of region.
|
||||
r2.cmp(&r1)
|
||||
}
|
||||
ord => ord,
|
||||
// The flattening step - remove lambda sets that don't reference the concrete var, and for
|
||||
// flatten lambda sets that reference it more than once.
|
||||
let mut uls_a: Vec<_> = uls_a
|
||||
.into_iter()
|
||||
.flat_map(|lambda_set| {
|
||||
let LambdaSet {
|
||||
solved,
|
||||
recursion_var,
|
||||
unspecialized,
|
||||
ambient_function,
|
||||
} = subs.get_lambda_set(lambda_set);
|
||||
let lambda_set_rank = subs.get_rank(lambda_set);
|
||||
let unspecialized = subs.get_subs_slice(unspecialized);
|
||||
// TODO: is it faster to traverse once, see if we only have one concrete lambda, and
|
||||
// bail in that happy-path, rather than always splitting?
|
||||
let (concrete, mut not_concrete): (Vec<_>, Vec<_>) = unspecialized
|
||||
.iter()
|
||||
.copied()
|
||||
.partition(|Uls(var, _, _)| subs.equivalent_without_compacting(*var, c_a));
|
||||
if concrete.len() == 1 {
|
||||
// No flattening needs to be done, just return the lambda set as-is
|
||||
return vec![lambda_set];
|
||||
}
|
||||
});
|
||||
// Must flatten
|
||||
concrete
|
||||
.into_iter()
|
||||
.enumerate()
|
||||
.map(|(i, concrete_lambda)| {
|
||||
let (var, unspecialized) = if i == 0 {
|
||||
// The first lambda set contains one concrete lambda, plus all solved
|
||||
// lambdas, plus all other unspecialized lambdas.
|
||||
// l' = [solved_lambdas + t1 + ... + tm + C:f:r]
|
||||
let unspecialized = SubsSlice::extend_new(
|
||||
&mut subs.unspecialized_lambda_sets,
|
||||
not_concrete
|
||||
.drain(..)
|
||||
.chain(std::iter::once(concrete_lambda)),
|
||||
);
|
||||
(lambda_set, unspecialized)
|
||||
} else {
|
||||
// All the other lambda sets consists only of their respective concrete
|
||||
// lambdas.
|
||||
// ln = [[] + C:fn:rn]
|
||||
let unspecialized = SubsSlice::extend_new(
|
||||
&mut subs.unspecialized_lambda_sets,
|
||||
[concrete_lambda],
|
||||
);
|
||||
let var = subs.fresh(Descriptor {
|
||||
content: Content::Error,
|
||||
rank: lambda_set_rank,
|
||||
mark: Mark::NONE,
|
||||
copy: OptVariable::NONE,
|
||||
});
|
||||
(var, unspecialized)
|
||||
};
|
||||
|
||||
trace_compact!(2. subs, &uls_a);
|
||||
uls_a
|
||||
subs.set_content(
|
||||
var,
|
||||
Content::LambdaSet(LambdaSet {
|
||||
solved,
|
||||
recursion_var,
|
||||
unspecialized,
|
||||
ambient_function,
|
||||
}),
|
||||
);
|
||||
var
|
||||
})
|
||||
.collect()
|
||||
})
|
||||
.collect();
|
||||
|
||||
// 2. Now, each `l` in `uls_a` has a unique unspecialized lambda of form `C:f:r`.
|
||||
// Sort `uls_a` primarily by `f` (arbitrary order), and secondarily by `r` in descending order.
|
||||
uls_a.sort_by(|v1, v2| {
|
||||
let unspec_1 = subs.get_subs_slice(subs.get_lambda_set(*v1).unspecialized);
|
||||
let unspec_2 = subs.get_subs_slice(subs.get_lambda_set(*v2).unspecialized);
|
||||
|
||||
let Uls(_, f1, r1) = unique_unspecialized_lambda(subs, c_a, unspec_1).unwrap();
|
||||
let Uls(_, f2, r2) = unique_unspecialized_lambda(subs, c_a, unspec_2).unwrap();
|
||||
|
||||
match f1.cmp(&f2) {
|
||||
std::cmp::Ordering::Equal => {
|
||||
// Order by descending order of region.
|
||||
r2.cmp(&r1)
|
||||
}
|
||||
ord => ord,
|
||||
}
|
||||
});
|
||||
|
||||
trace_compact!(2. subs, &uls_a);
|
||||
|
||||
// 3. For each `l` in `uls_a` with unique unspecialized lambda `C:f:r`:
|
||||
// 1. Let `t_f1` be the directly ambient function of the lambda set containing `C:f:r`. Remove `C:f:r` from `t_f1`'s lambda set.
|
||||
// - For example, `(b' -[[] + Fo:f:2]-> {})` if `C:f:r=Fo:f:2`. Removing `Fo:f:2`, we get `(b' -[[]]-> {})`.
|
||||
|
@ -2082,8 +2015,16 @@ pub fn compact_lambda_sets_of_vars<P: Phase>(
|
|||
// continue;
|
||||
// }
|
||||
|
||||
let (new_must_implement, new_uls_of_var) =
|
||||
compact_lambda_set(subs_proxy, arena, pools, c_a, l, phase, exposed_by_module);
|
||||
let (new_must_implement, new_uls_of_var) = compact_lambda_set(
|
||||
subs,
|
||||
derived_module,
|
||||
arena,
|
||||
pools,
|
||||
c_a,
|
||||
l,
|
||||
phase,
|
||||
exposed_by_module,
|
||||
);
|
||||
|
||||
must_implement.extend(new_must_implement);
|
||||
uls_of_var_queue.extend(new_uls_of_var.drain());
|
||||
|
@ -2097,7 +2038,8 @@ pub fn compact_lambda_sets_of_vars<P: Phase>(
|
|||
|
||||
#[must_use]
|
||||
fn compact_lambda_set<P: Phase>(
|
||||
subs_proxy: &mut SubsProxy,
|
||||
subs: &mut Subs,
|
||||
derived_module: &SharedDerivedModule,
|
||||
arena: &Bump,
|
||||
pools: &mut Pools,
|
||||
resolved_concrete: Variable,
|
||||
|
@ -2111,63 +2053,59 @@ fn compact_lambda_set<P: Phase>(
|
|||
// 2. Let `t_f2` be the directly ambient function of the specialization lambda set resolved by `C:f:r`.
|
||||
// - For example, `(b -[[] + b:g:1]-> {})` if `C:f:r=Fo:f:2`, from the algorithm's running example.
|
||||
// 3. Unify `t_f1 ~ t_f2`.
|
||||
let (target_rank, f, r, t_f1, specialization_decision) = subs_proxy.with_subs(|subs| {
|
||||
let LambdaSet {
|
||||
solved,
|
||||
recursion_var,
|
||||
unspecialized,
|
||||
ambient_function: t_f1,
|
||||
} = subs.get_lambda_set(this_lambda_set);
|
||||
let target_rank = subs.get_rank(this_lambda_set);
|
||||
let LambdaSet {
|
||||
solved,
|
||||
recursion_var,
|
||||
unspecialized,
|
||||
ambient_function: t_f1,
|
||||
} = subs.get_lambda_set(this_lambda_set);
|
||||
let target_rank = subs.get_rank(this_lambda_set);
|
||||
|
||||
debug_assert!(!unspecialized.is_empty());
|
||||
debug_assert!(!unspecialized.is_empty());
|
||||
|
||||
let unspecialized = subs.get_subs_slice(unspecialized);
|
||||
let unspecialized = subs.get_subs_slice(unspecialized);
|
||||
|
||||
// 1. Let `t_f1` be the directly ambient function of the lambda set containing `C:f:r`.
|
||||
let Uls(c, f, r) =
|
||||
unique_unspecialized_lambda(subs, resolved_concrete, unspecialized).unwrap();
|
||||
// 1. Let `t_f1` be the directly ambient function of the lambda set containing `C:f:r`.
|
||||
let Uls(c, f, r) = unique_unspecialized_lambda(subs, resolved_concrete, unspecialized).unwrap();
|
||||
|
||||
debug_assert!(subs.equivalent_without_compacting(c, resolved_concrete));
|
||||
debug_assert!(subs.equivalent_without_compacting(c, resolved_concrete));
|
||||
|
||||
// 1b. Remove `C:f:r` from `t_f1`'s lambda set.
|
||||
let new_unspecialized: Vec<_> = unspecialized
|
||||
.iter()
|
||||
.filter(|Uls(v, _, _)| !subs.equivalent_without_compacting(*v, resolved_concrete))
|
||||
.copied()
|
||||
.collect();
|
||||
debug_assert_eq!(new_unspecialized.len(), unspecialized.len() - 1);
|
||||
let t_f1_lambda_set_without_concrete = LambdaSet {
|
||||
solved,
|
||||
recursion_var,
|
||||
unspecialized: SubsSlice::extend_new(
|
||||
&mut subs.unspecialized_lambda_sets,
|
||||
new_unspecialized,
|
||||
),
|
||||
ambient_function: t_f1,
|
||||
};
|
||||
subs.set_content(
|
||||
this_lambda_set,
|
||||
Content::LambdaSet(t_f1_lambda_set_without_concrete),
|
||||
);
|
||||
// 1b. Remove `C:f:r` from `t_f1`'s lambda set.
|
||||
let new_unspecialized: Vec<_> = unspecialized
|
||||
.iter()
|
||||
.filter(|Uls(v, _, _)| !subs.equivalent_without_compacting(*v, resolved_concrete))
|
||||
.copied()
|
||||
.collect();
|
||||
debug_assert_eq!(new_unspecialized.len(), unspecialized.len() - 1);
|
||||
let t_f1_lambda_set_without_concrete = LambdaSet {
|
||||
solved,
|
||||
recursion_var,
|
||||
unspecialized: SubsSlice::extend_new(
|
||||
&mut subs.unspecialized_lambda_sets,
|
||||
new_unspecialized,
|
||||
),
|
||||
ambient_function: t_f1,
|
||||
};
|
||||
subs.set_content(
|
||||
this_lambda_set,
|
||||
Content::LambdaSet(t_f1_lambda_set_without_concrete),
|
||||
);
|
||||
|
||||
let specialization_decision = make_specialization_decision(subs, c);
|
||||
|
||||
(target_rank, f, r, t_f1, specialization_decision)
|
||||
});
|
||||
let specialization_decision = make_specialization_decision(subs, c);
|
||||
|
||||
let specialization_key = match specialization_decision {
|
||||
SpecializeDecision::Specialize(key) => key,
|
||||
SpecializeDecision::Drop => {
|
||||
// Do nothing other than to remove the concrete lambda to drop from the lambda set,
|
||||
// which we already did in 1b above.
|
||||
subs_proxy.with_subs(|subs| trace_compact!(3iter_end_skipped. subs, t_f1));
|
||||
trace_compact!(3iter_end_skipped. subs, t_f1);
|
||||
return (Default::default(), Default::default());
|
||||
}
|
||||
};
|
||||
|
||||
let specialized_lambda_set = get_specialization_lambda_set_ambient_function(
|
||||
subs_proxy,
|
||||
subs,
|
||||
derived_module,
|
||||
phase,
|
||||
f,
|
||||
r,
|
||||
|
@ -2181,26 +2119,24 @@ fn compact_lambda_set<P: Phase>(
|
|||
Err(()) => {
|
||||
// Do nothing other than to remove the concrete lambda to drop from the lambda set,
|
||||
// which we already did in 1b above.
|
||||
subs_proxy.with_subs(|subs| trace_compact!(3iter_end_skipped. subs, t_f1));
|
||||
trace_compact!(3iter_end_skipped. subs, t_f1);
|
||||
return (Default::default(), Default::default());
|
||||
}
|
||||
};
|
||||
|
||||
subs_proxy.with_subs(|subs| {
|
||||
// Ensure the specialized ambient function we'll unify with is not a generalized one, but one
|
||||
// at the rank of the lambda set being compacted.
|
||||
let t_f2 = deep_copy_var_in(subs, target_rank, pools, t_f2, arena);
|
||||
// Ensure the specialized ambient function we'll unify with is not a generalized one, but one
|
||||
// at the rank of the lambda set being compacted.
|
||||
let t_f2 = deep_copy_var_in(subs, target_rank, pools, t_f2, arena);
|
||||
|
||||
// 3. Unify `t_f1 ~ t_f2`.
|
||||
trace_compact!(3iter_start. subs, this_lambda_set, t_f1, t_f2);
|
||||
let (vars, new_must_implement_ability, new_lambda_sets_to_specialize, _meta) =
|
||||
unify(subs, t_f1, t_f2, Mode::EQ).expect_success("ambient functions don't unify");
|
||||
trace_compact!(3iter_end. subs, t_f1);
|
||||
// 3. Unify `t_f1 ~ t_f2`.
|
||||
trace_compact!(3iter_start. subs, this_lambda_set, t_f1, t_f2);
|
||||
let (vars, new_must_implement_ability, new_lambda_sets_to_specialize, _meta) =
|
||||
unify(subs, t_f1, t_f2, Mode::EQ).expect_success("ambient functions don't unify");
|
||||
trace_compact!(3iter_end. subs, t_f1);
|
||||
|
||||
introduce(subs, target_rank, pools, &vars);
|
||||
introduce(subs, target_rank, pools, &vars);
|
||||
|
||||
(new_must_implement_ability, new_lambda_sets_to_specialize)
|
||||
})
|
||||
(new_must_implement_ability, new_lambda_sets_to_specialize)
|
||||
}
|
||||
|
||||
enum SpecializationTypeKey {
|
||||
|
@ -2273,7 +2209,8 @@ fn make_specialization_decision(subs: &Subs, var: Variable) -> SpecializeDecisio
|
|||
}
|
||||
|
||||
fn get_specialization_lambda_set_ambient_function<P: Phase>(
|
||||
subs: &mut SubsProxy,
|
||||
subs: &mut Subs,
|
||||
derived_module: &SharedDerivedModule,
|
||||
phase: &P,
|
||||
ability_member: Symbol,
|
||||
lset_region: u8,
|
||||
|
@ -2310,33 +2247,32 @@ fn get_specialization_lambda_set_ambient_function<P: Phase>(
|
|||
}
|
||||
})?;
|
||||
|
||||
let local_lset = subs.with_subs(|subs| {
|
||||
phase.copy_lambda_set_ambient_function_to_home_subs(
|
||||
external_specialized_lset,
|
||||
opaque_home,
|
||||
subs,
|
||||
)
|
||||
});
|
||||
let specialized_ambient = phase.copy_lambda_set_ambient_function_to_home_subs(
|
||||
external_specialized_lset,
|
||||
opaque_home,
|
||||
subs,
|
||||
);
|
||||
|
||||
Ok(local_lset)
|
||||
Ok(specialized_ambient)
|
||||
}
|
||||
|
||||
SpecializationTypeKey::Derived(derive_key) => {
|
||||
let specialized_lambda_set = subs.with_derived(|derived_module| {
|
||||
let (_, _, specialization_lambda_sets) =
|
||||
derived_module.get_or_insert(exposed_by_module, derive_key);
|
||||
let mut derived_module = derived_module.lock().unwrap();
|
||||
|
||||
*specialization_lambda_sets
|
||||
.get(&lset_region)
|
||||
.expect("lambda set region not resolved")
|
||||
});
|
||||
let (_, _, specialization_lambda_sets) =
|
||||
derived_module.get_or_insert(exposed_by_module, derive_key);
|
||||
|
||||
let local_lset = subs.copy_lambda_set_ambient_function_from_derived_to_subs(
|
||||
let specialized_lambda_set = *specialization_lambda_sets
|
||||
.get(&lset_region)
|
||||
.expect("lambda set region not resolved");
|
||||
|
||||
let specialized_ambient = derived_module.copy_lambda_set_ambient_function_to_subs(
|
||||
specialized_lambda_set,
|
||||
subs,
|
||||
target_rank,
|
||||
);
|
||||
|
||||
Ok(local_lset)
|
||||
Ok(specialized_ambient)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue