mirror of
https://github.com/roc-lang/roc.git
synced 2025-07-23 06:25:10 +00:00
Import ambient functions into storage subs properly
This commit is contained in:
parent
6c79efa43a
commit
ae7ad36d60
3 changed files with 52 additions and 22 deletions
|
@ -9,7 +9,7 @@ use roc_collections::MutMap;
|
|||
use roc_derive_key::GlobalDerivedSymbols;
|
||||
use roc_module::symbol::ModuleId;
|
||||
use roc_solve::solve::{compact_lambda_sets_of_vars, Phase, Pools};
|
||||
use roc_types::subs::{Content, LambdaSet};
|
||||
use roc_types::subs::{Content, FlatType, LambdaSet};
|
||||
use roc_types::subs::{ExposedTypesStorageSubs, Subs, Variable};
|
||||
use roc_unify::unify::{unify as unify_unify, Mode, Unified};
|
||||
|
||||
|
@ -121,19 +121,17 @@ impl Phase for LatePhase<'_> {
|
|||
.as_inner()
|
||||
.get_lambda_set(storage_lambda_set_var);
|
||||
|
||||
todo!("I don't think the ambient function is in the storage subs properly yet");
|
||||
|
||||
let copied = module_types
|
||||
.storage_subs
|
||||
.export_variable_to(target_subs, storage_lambda_set_var);
|
||||
let our_lambda_set_var = copied.variable;
|
||||
.export_variable_to(target_subs, ambient_function);
|
||||
let our_ambient_function_var = copied.variable;
|
||||
|
||||
debug_assert!(matches!(
|
||||
target_subs.get_content_without_compacting(our_lambda_set_var),
|
||||
Content::LambdaSet(..)
|
||||
target_subs.get_content_without_compacting(our_ambient_function_var),
|
||||
Content::Structure(FlatType::Func(..))
|
||||
));
|
||||
|
||||
our_lambda_set_var
|
||||
our_ambient_function_var
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -162,7 +160,7 @@ pub fn unify(
|
|||
|
||||
let late_phase = LatePhase { home, abilities };
|
||||
|
||||
compact_lambda_sets_of_vars(
|
||||
let must_implement_constraints = compact_lambda_sets_of_vars(
|
||||
subs,
|
||||
arena,
|
||||
&mut pools,
|
||||
|
@ -170,6 +168,11 @@ pub fn unify(
|
|||
&late_phase,
|
||||
derived_symbols,
|
||||
);
|
||||
// At this point we can't do anything with must-implement constraints, since we're no
|
||||
// longer solving. We must assume that they were totally caught during solving.
|
||||
// After we land https://github.com/rtfeldman/roc/issues/3207 this concern should totally
|
||||
// go away.
|
||||
let _ = must_implement_constraints;
|
||||
// Pools are only used to keep track of variable ranks for generalization purposes.
|
||||
// Since we break generalization during monomorphization, `pools` is irrelevant
|
||||
// here. We only need it for `compact_lambda_sets_of_vars`, which is also used in a
|
||||
|
|
|
@ -6,9 +6,10 @@ use roc_can::module::RigidVariables;
|
|||
use roc_collections::all::MutMap;
|
||||
use roc_collections::VecMap;
|
||||
use roc_derive_key::GlobalDerivedSymbols;
|
||||
use roc_error_macros::internal_error;
|
||||
use roc_module::symbol::Symbol;
|
||||
use roc_types::solved_types::Solved;
|
||||
use roc_types::subs::{ExposedTypesStorageSubs, StorageSubs, Subs, Variable};
|
||||
use roc_types::subs::{Content, ExposedTypesStorageSubs, FlatType, StorageSubs, Subs, Variable};
|
||||
use roc_types::types::Alias;
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -100,10 +101,29 @@ pub fn exposed_types_storage_subs(
|
|||
for (_, member_specialization) in solved_specializations.iter() {
|
||||
for (_, &specialization_lset_var) in member_specialization.specialization_lambda_sets.iter()
|
||||
{
|
||||
let new_var = storage_subs
|
||||
.import_variable_from(subs, specialization_lset_var)
|
||||
let specialization_lset_ambient_function_var = subs
|
||||
.get_lambda_set(specialization_lset_var)
|
||||
.ambient_function;
|
||||
|
||||
// Import the ambient function of this specialization lambda set; that will import the
|
||||
// lambda set as well. The ambient function is needed for the lambda set compaction
|
||||
// algorithm.
|
||||
let imported_lset_ambient_function_var = storage_subs
|
||||
.import_variable_from(subs, specialization_lset_ambient_function_var)
|
||||
.variable;
|
||||
stored_specialization_lambda_set_vars.insert(specialization_lset_var, new_var);
|
||||
|
||||
let imported_lset_var = match storage_subs
|
||||
.as_inner()
|
||||
.get_content_without_compacting(imported_lset_ambient_function_var)
|
||||
{
|
||||
Content::Structure(FlatType::Func(_, lambda_set_var, _)) => *lambda_set_var,
|
||||
content => internal_error!(
|
||||
"ambient lambda set function import is not a function, found: {:?}",
|
||||
roc_types::subs::SubsFmtContent(content, storage_subs.as_inner())
|
||||
),
|
||||
};
|
||||
stored_specialization_lambda_set_vars
|
||||
.insert(specialization_lset_var, imported_lset_var);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1900,11 +1900,11 @@ 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 c_a = subs.get_root_key_without_compacting(c_a);
|
||||
// 1. Let each `l` in `uls_a` be of form `[concrete_lambdas + ... + C:f:r + ...]`.
|
||||
// 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' = [concrete_lambdas + t1 + ... + tm + C:f:r]` and `l1 = [[] + C:f1:r1], ..., ln = [[] + C:fn:rn]`.
|
||||
// `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();
|
||||
|
@ -1939,7 +1939,9 @@ pub fn compact_lambda_sets_of_vars<P: Phase>(
|
|||
.enumerate()
|
||||
.map(|(i, concrete_lambda)| {
|
||||
let (var, unspecialized) = if i == 0 {
|
||||
// `l' = [concrete_lambdas + t1 + ... + tm + C:f:r`
|
||||
// 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
|
||||
|
@ -1948,6 +1950,8 @@ pub fn compact_lambda_sets_of_vars<P: Phase>(
|
|||
);
|
||||
(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,
|
||||
|
@ -2100,7 +2104,7 @@ fn compact_lambda_set<P: Phase>(
|
|||
let specialization_symbol_slice =
|
||||
UnionLabels::insert_into_subs(subs, vec![(specialization_symbol, vec![])]);
|
||||
// TODO: This is WRONG, fix it!
|
||||
let ambient_function = subs.fresh_unnamed_flex_var();
|
||||
let ambient_function = Variable::NULL;
|
||||
let _lambda_set_for_derived = subs.fresh(Descriptor {
|
||||
content: Content::LambdaSet(subs::LambdaSet {
|
||||
solved: specialization_symbol_slice,
|
||||
|
@ -2501,11 +2505,14 @@ fn type_to_variable<'a>(
|
|||
($typ:expr, $ambient_function_policy:expr) => {{
|
||||
match RegisterVariable::from_type(subs, rank, pools, arena, $typ) {
|
||||
RegisterVariable::Direct(var) => {
|
||||
if delayed_alias_lambda_set_vars.len() > 0 {
|
||||
let slice = subs.get_subs_slice(delayed_alias_lambda_set_vars);
|
||||
if slice.contains(&var) {
|
||||
$ambient_function_policy.link_to_alias_lambda_set_var(subs, var);
|
||||
}
|
||||
let slice = subs.get_subs_slice(delayed_alias_lambda_set_vars);
|
||||
if slice.contains(&var)
|
||||
|| matches!(
|
||||
$ambient_function_policy,
|
||||
AmbientFunctionPolicy::Function(..)
|
||||
)
|
||||
{
|
||||
$ambient_function_policy.link_to_alias_lambda_set_var(subs, var);
|
||||
}
|
||||
|
||||
var
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue