Import both specializations and declared ability mappings

This commit is contained in:
Ayaz Hafiz 2022-07-25 10:06:49 -04:00
parent cd0b8577ab
commit 0525c6d616
No known key found for this signature in database
GPG key ID: 0E2A37416A25EF58
5 changed files with 159 additions and 86 deletions

View file

@ -1,15 +1,15 @@
use crate::solve::{self, Aliases};
use roc_can::abilities::AbilitiesStore;
use roc_can::abilities::{AbilitiesStore, ImplKey, ResolvedImpl};
use roc_can::constraint::{Constraint as ConstraintSoa, Constraints};
use roc_can::expr::PendingDerives;
use roc_can::module::{ExposedByModule, ResolvedSpecializations, RigidVariables};
use roc_can::module::{ExposedByModule, ResolvedImplementations, RigidVariables};
use roc_collections::all::MutMap;
use roc_collections::VecMap;
use roc_derive::SharedDerivedModule;
use roc_error_macros::internal_error;
use roc_module::symbol::{ModuleId, Symbol};
use roc_types::subs::{Content, ExposedTypesStorageSubs, FlatType, StorageSubs, Subs, Variable};
use roc_types::types::Alias;
use roc_types::types::{Alias, MemberImpl};
/// A marker that a given Subs has been solved.
/// The only way to obtain a Solved<Subs> is by running the solver on it.
@ -48,7 +48,7 @@ pub struct SolvedModule {
pub exposed_vars_by_symbol: Vec<(Symbol, Variable)>,
/// Used when importing this module into another module
pub solved_specializations: ResolvedSpecializations,
pub solved_implementations: ResolvedImplementations,
pub exposed_types: ExposedTypesStorageSubs,
}
@ -108,7 +108,7 @@ pub fn exposed_types_storage_subs(
home: ModuleId,
solved_subs: &mut Solved<Subs>,
exposed_vars_by_symbol: &[(Symbol, Variable)],
solved_specializations: &ResolvedSpecializations,
solved_implementations: &ResolvedImplementations,
abilities_store: &AbilitiesStore,
) -> ExposedTypesStorageSubs {
let subs = solved_subs.inner_mut();
@ -121,31 +121,42 @@ pub fn exposed_types_storage_subs(
}
let mut stored_specialization_lambda_set_vars =
VecMap::with_capacity(solved_specializations.len());
VecMap::with_capacity(solved_implementations.len());
for (_, member_specialization) in solved_specializations.iter() {
for (_, &lset_var) in member_specialization.specialization_lambda_sets.iter() {
let specialization_lset_ambient_function_var =
subs.get_lambda_set(lset_var).ambient_function;
for (_, member_impl) in solved_implementations.iter() {
match member_impl {
ResolvedImpl::Impl(member_specialization) => {
// Export all the lambda sets and their ambient functions.
for (_, &lset_var) in member_specialization.specialization_lambda_sets.iter() {
let specialization_lset_ambient_function_var =
subs.get_lambda_set(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;
// 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;
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(lset_var, imported_lset_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(lset_var, imported_lset_var);
}
}
ResolvedImpl::Derived => {
// nothing to do
}
ResolvedImpl::Error => {
// nothing to do
}
}
}
@ -171,3 +182,37 @@ pub fn exposed_types_storage_subs(
stored_ability_member_vars,
}
}
/// Extracts the ability member implementations owned by a solved module.
pub fn extract_module_owned_implementations(
module_id: ModuleId,
abilities_store: &AbilitiesStore,
) -> ResolvedImplementations {
abilities_store
.iter_declared_implementations()
.filter_map(|((member, typ), member_impl)| {
// This module solved this specialization if either the member or the type comes from the
// module.
if member.module_id() != module_id && typ.module_id() != module_id {
return None;
}
let impl_key = ImplKey {
opaque: typ,
ability_member: member,
};
let resolved_impl = match member_impl {
MemberImpl::Impl(impl_symbol) => {
let specialization = abilities_store.specialization_info(*impl_symbol).expect(
"declared implementations should be resolved conclusively after solving",
);
ResolvedImpl::Impl(specialization.clone())
}
MemberImpl::Derived => ResolvedImpl::Derived,
MemberImpl::Error => ResolvedImpl::Error,
};
Some((impl_key, resolved_impl))
})
.collect()
}