Refactor deriving tests to put testing utilities in separate module

As we prepare to add derivers for Decoders, we'll want to use this same
infrastructure for Decoder derive tests. This pulls out the common test
infrastructure into a separate module under test_derive.
This commit is contained in:
Ayaz Hafiz 2022-08-01 13:35:02 -05:00
parent fa14146054
commit c3383da994
No known key found for this signature in database
GPG key ID: 0E2A37416A25EF58
3 changed files with 387 additions and 378 deletions

View file

@ -4,299 +4,21 @@
// For the `v!` macro we use uppercase variables when constructing tag unions.
#![allow(non_snake_case)]
use std::path::PathBuf;
use bumpalo::Bump;
use insta::assert_snapshot;
use pretty_assertions::assert_eq;
use ven_pretty::DocAllocator;
use crate::pretty_print::{pretty_print_def, Ctx};
use roc_can::{
abilities::{AbilitiesStore, SpecializationLambdaSets},
constraint::Constraints,
def::Def,
expr::Declarations,
module::{
ExposedByModule, ExposedForModule, ExposedModuleTypes, ResolvedImplementations,
RigidVariables,
},
};
use roc_collections::VecSet;
use roc_constrain::expr::constrain_decls;
use roc_debug_flags::dbg_do;
use roc_derive::{synth_var, DerivedModule};
use roc_derive_key::{DeriveKey, Derived};
use roc_load_internal::file::{add_imports, default_aliases, LoadedModule, Threading};
use roc_module::{
ident::TagName,
symbol::{IdentIds, Interns, ModuleId, Symbol},
};
use roc_region::all::LineInfo;
use roc_reporting::report::{type_problem, RocDocAllocator};
use crate::{test_hash_eq, test_hash_neq, util::derive_test, v};
use roc_derive::synth_var;
use roc_derive_key::Derived;
use roc_module::{ident::TagName, symbol::Symbol};
use roc_types::{
pretty_print::{name_and_print_var, DebugPrint},
subs::{
AliasVariables, Content, ExposedTypesStorageSubs, FlatType, RecordFields, Subs, SubsIndex,
SubsSlice, UnionTags, Variable,
AliasVariables, Content, FlatType, RecordFields, Subs, SubsIndex, SubsSlice, UnionTags,
Variable,
},
types::{AliasKind, RecordField},
};
const DERIVED_MODULE: ModuleId = ModuleId::DERIVED_SYNTH;
fn encode_path() -> PathBuf {
let repo_root = std::env::var("ROC_WORKSPACE_DIR").expect("are you running with `cargo test`?");
PathBuf::from(repo_root)
.join("compiler")
.join("builtins")
.join("roc")
.join("Encode.roc")
}
#[allow(clippy::too_many_arguments)]
fn assemble_derived_golden(
subs: &mut Subs,
test_module: ModuleId,
interns: &Interns,
source_var: Variable,
derived_source: &str,
typ: Variable,
specialization_lsets: SpecializationLambdaSets,
) -> String {
let mut print_var = |var: Variable, print_only_under_alias| {
let snapshot = subs.snapshot();
let pretty_type = name_and_print_var(
var,
subs,
test_module,
interns,
DebugPrint {
print_lambda_sets: true,
print_only_under_alias,
},
);
subs.rollback_to(snapshot);
pretty_type
};
let mut pretty_buf = String::new();
pretty_buf.push_str(&format!("# derived for {}\n", print_var(source_var, false)));
let pretty_type = print_var(typ, false);
pretty_buf.push_str(&format!("# {}\n", &pretty_type));
let pretty_type_under_aliases = print_var(typ, true);
pretty_buf.push_str(&format!("# {}\n", &pretty_type_under_aliases));
pretty_buf.push_str("# Specialization lambda sets:\n");
let mut specialization_lsets = specialization_lsets.into_iter().collect::<Vec<_>>();
specialization_lsets.sort_by_key(|(region, _)| *region);
for (region, var) in specialization_lsets {
let pretty_lset = print_var(var, false);
pretty_buf.push_str(&format!("# @<{}>: {}\n", region, pretty_lset));
}
pretty_buf.push_str(derived_source);
pretty_buf
}
#[allow(clippy::too_many_arguments)]
fn check_derived_typechecks_and_golden(
derived_def: Def,
test_module: ModuleId,
mut test_subs: Subs,
interns: &Interns,
exposed_encode_types: ExposedTypesStorageSubs,
encode_abilities_store: AbilitiesStore,
source_var: Variable,
derived_program: &str,
specialization_lsets: SpecializationLambdaSets,
check_golden: impl Fn(&str),
) {
// constrain the derived
let mut constraints = Constraints::new();
let def_var = derived_def.expr_var;
let mut decls = Declarations::new();
decls.push_def(derived_def);
let constr = constrain_decls(&mut constraints, test_module, &decls);
// the derived depends on stuff from Encode, so
// - we need to add those dependencies as imported on the constraint
// - we need to add Encode ability info to a local abilities store
let encode_values_to_import = exposed_encode_types
.stored_vars_by_symbol
.keys()
.copied()
.collect::<VecSet<_>>();
let pending_abilities = encode_abilities_store.closure_from_imported(&encode_values_to_import);
let mut exposed_by_module = ExposedByModule::default();
exposed_by_module.insert(
ModuleId::ENCODE,
ExposedModuleTypes {
exposed_types_storage_subs: exposed_encode_types,
resolved_implementations: ResolvedImplementations::default(),
},
);
let exposed_for_module =
ExposedForModule::new(encode_values_to_import.iter(), exposed_by_module);
let mut def_types = Default::default();
let mut rigid_vars = Default::default();
let (import_variables, abilities_store) = add_imports(
test_module,
&mut test_subs,
pending_abilities,
&exposed_for_module,
&mut def_types,
&mut rigid_vars,
);
let constr =
constraints.let_import_constraint(rigid_vars, def_types, constr, &import_variables);
// run the solver, print and fail if we have errors
dbg_do!(
roc_debug_flags::ROC_PRINT_UNIFICATIONS_DERIVED,
std::env::set_var(roc_debug_flags::ROC_PRINT_UNIFICATIONS_DERIVED, "1")
);
let (mut solved_subs, _, problems, _) = roc_solve::module::run_solve(
test_module,
&constraints,
constr,
RigidVariables::default(),
test_subs,
default_aliases(),
abilities_store,
Default::default(),
&exposed_for_module.exposed_by_module,
Default::default(),
);
let subs = solved_subs.inner_mut();
if !problems.is_empty() {
let filename = PathBuf::from("Test.roc");
let lines = LineInfo::new(" ");
let src_lines = vec![" "];
let mut reports = Vec::new();
let alloc = RocDocAllocator::new(&src_lines, test_module, interns);
for problem in problems.into_iter() {
if let Some(report) = type_problem(&alloc, &lines, filename.clone(), problem.clone()) {
reports.push(report);
}
}
let has_reports = !reports.is_empty();
let doc = alloc
.stack(reports.into_iter().map(|v| v.pretty(&alloc)))
.append(if has_reports {
alloc.line()
} else {
alloc.nil()
});
let mut buf = String::new();
doc.1
.render_raw(80, &mut roc_reporting::report::CiWrite::new(&mut buf))
.unwrap();
panic!(
"Derived does not typecheck:\n{}\nDerived def:\n{}",
buf, derived_program
);
}
let golden = assemble_derived_golden(
subs,
test_module,
interns,
source_var,
derived_program,
def_var,
specialization_lsets,
);
check_golden(&golden)
}
fn derive_test<S>(synth_input: S, check_golden: impl Fn(&str))
where
S: FnOnce(&mut Subs) -> Variable,
{
let arena = Bump::new();
let source = roc_builtins::roc::module_source(ModuleId::ENCODE);
let target_info = roc_target::TargetInfo::default_x86_64();
let LoadedModule {
mut interns,
exposed_types_storage: exposed_encode_types,
abilities_store,
resolved_implementations,
..
} = roc_load_internal::file::load_and_typecheck_str(
&arena,
encode_path().file_name().unwrap().into(),
source,
encode_path().parent().unwrap().to_path_buf(),
Default::default(),
target_info,
roc_reporting::report::RenderTarget::ColorTerminal,
Threading::AllAvailable,
)
.unwrap();
let mut subs = Subs::new();
let ident_ids = IdentIds::default();
let source_var = synth_input(&mut subs);
let key = get_key(&subs, source_var);
let mut derived_module = unsafe { DerivedModule::from_components(subs, ident_ids) };
let mut exposed_by_module = ExposedByModule::default();
exposed_by_module.insert(
ModuleId::ENCODE,
ExposedModuleTypes {
exposed_types_storage_subs: exposed_encode_types.clone(),
resolved_implementations,
},
);
let (_derived_symbol, derived_def, specialization_lsets) =
derived_module.get_or_insert(&exposed_by_module, key);
let specialization_lsets = specialization_lsets.clone();
let derived_def = derived_def.clone();
let (subs, ident_ids) = derived_module.decompose();
interns.all_ident_ids.insert(DERIVED_MODULE, ident_ids);
DERIVED_MODULE.register_debug_idents(interns.all_ident_ids.get(&DERIVED_MODULE).unwrap());
let ctx = Ctx { interns: &interns };
let derived_program = pretty_print_def(&ctx, &derived_def);
check_derived_typechecks_and_golden(
derived_def,
DERIVED_MODULE,
subs,
&interns,
exposed_encode_types,
abilities_store,
source_var,
&derived_program,
specialization_lsets,
check_golden,
);
}
fn get_key(subs: &Subs, var: Variable) -> DeriveKey {
match Derived::encoding(subs, var) {
Ok(Derived::Key(key)) => key,
_ => unreachable!(),
}
}
fn check_key<S1, S2>(eq: bool, synth1: S1, synth2: S2)
where
S1: FnOnce(&mut Subs) -> Variable,
@ -328,100 +50,6 @@ where
assert_eq!(key, Ok(Derived::Immediate(immediate)));
}
// Writing out the types into content is terrible, so let's use a DSL at least for testing
macro_rules! v {
({ $($field:ident: $make_v:expr,)* $(?$opt_field:ident : $make_opt_v:expr,)* }) => {
|subs: &mut Subs| {
$(let $field = $make_v(subs);)*
$(let $opt_field = $make_opt_v(subs);)*
let fields = vec![
$( (stringify!($field).into(), RecordField::Required($field)) ,)*
$( (stringify!($opt_field).into(), RecordField::Required($opt_field)) ,)*
];
let fields = RecordFields::insert_into_subs(subs, fields);
synth_var(subs, Content::Structure(FlatType::Record(fields, Variable::EMPTY_RECORD)))
}
};
([ $($tag:ident $($payload:expr)*),* ]) => {
|subs: &mut Subs| {
$(
let $tag = vec![ $( $payload(subs), )* ];
)*
let tags = UnionTags::insert_into_subs::<_, Vec<Variable>>(subs, vec![ $( (TagName(stringify!($tag).into()), $tag) ,)* ]);
synth_var(subs, Content::Structure(FlatType::TagUnion(tags, Variable::EMPTY_TAG_UNION)))
}
};
([ $($tag:ident $($payload:expr)*),* ] as $rec_var:ident) => {
|subs: &mut Subs| {
let $rec_var = subs.fresh_unnamed_flex_var();
let rec_name_index =
SubsIndex::push_new(&mut subs.field_names, stringify!($rec).into());
$(
let $tag = vec![ $( $payload(subs), )* ];
)*
let tags = UnionTags::insert_into_subs::<_, Vec<Variable>>(subs, vec![ $( (TagName(stringify!($tag).into()), $tag) ,)* ]);
let tag_union_var = synth_var(subs, Content::Structure(FlatType::RecursiveTagUnion($rec_var, tags, Variable::EMPTY_TAG_UNION)));
subs.set_content(
$rec_var,
Content::RecursionVar {
structure: tag_union_var,
opt_name: Some(rec_name_index),
},
);
tag_union_var
}
};
(Symbol::$sym:ident $($arg:expr)*) => {
|subs: &mut Subs| {
let $sym = vec![ $( $arg(subs) ,)* ];
let var_slice = SubsSlice::insert_into_subs(subs, $sym);
synth_var(subs, Content::Structure(FlatType::Apply(Symbol::$sym, var_slice)))
}
};
(Symbol::$alias:ident $($arg:expr)* => $real_var:expr) => {
|subs: &mut Subs| {
let args = vec![$( $arg(subs) )*];
let alias_variables = AliasVariables::insert_into_subs::<Vec<_>, Vec<_>>(subs, args, vec![]);
let real_var = $real_var(subs);
synth_var(subs, Content::Alias(Symbol::$alias, alias_variables, real_var, AliasKind::Structural))
}
};
(@Symbol::$alias:ident $($arg:expr)* => $real_var:expr) => {
|subs: &mut Subs| {
let args = vec![$( $arg(subs) )*];
let alias_variables = AliasVariables::insert_into_subs::<Vec<_>, Vec<_>>(subs, args, vec![]);
let real_var = $real_var(subs);
synth_var(subs, Content::Alias(Symbol::$alias, alias_variables, real_var, AliasKind::Opaque))
}
};
(*$rec_var:ident) => {
|_: &mut Subs| { $rec_var }
};
($var:ident) => {
|_: &mut Subs| { Variable::$var }
};
}
macro_rules! test_hash_eq {
($($name:ident: $synth1:expr, $synth2:expr)*) => {$(
#[test]
fn $name() {
check_key(true, $synth1, $synth2)
}
)*};
}
macro_rules! test_hash_neq {
($($name:ident: $synth1:expr, $synth2:expr)*) => {$(
#[test]
fn $name() {
check_key(false, $synth1, $synth2)
}
)*};
}
// {{{ hash tests
test_hash_eq! {

View file

@ -3,3 +3,4 @@
mod encoding;
mod pretty_print;
mod util;

View file

@ -0,0 +1,380 @@
use std::path::PathBuf;
use bumpalo::Bump;
use ven_pretty::DocAllocator;
use crate::pretty_print::{pretty_print_def, Ctx};
use roc_can::{
abilities::{AbilitiesStore, SpecializationLambdaSets},
constraint::Constraints,
def::Def,
expr::Declarations,
module::{
ExposedByModule, ExposedForModule, ExposedModuleTypes, ResolvedImplementations,
RigidVariables,
},
};
use roc_collections::VecSet;
use roc_constrain::expr::constrain_decls;
use roc_debug_flags::dbg_do;
use roc_derive::DerivedModule;
use roc_derive_key::{DeriveKey, Derived};
use roc_load_internal::file::{add_imports, default_aliases, LoadedModule, Threading};
use roc_module::symbol::{IdentIds, Interns, ModuleId};
use roc_region::all::LineInfo;
use roc_reporting::report::{type_problem, RocDocAllocator};
use roc_types::{
pretty_print::{name_and_print_var, DebugPrint},
subs::{ExposedTypesStorageSubs, Subs, Variable},
};
const DERIVED_MODULE: ModuleId = ModuleId::DERIVED_SYNTH;
fn encode_path() -> PathBuf {
let repo_root = std::env::var("ROC_WORKSPACE_DIR").expect("are you running with `cargo test`?");
PathBuf::from(repo_root)
.join("compiler")
.join("builtins")
.join("roc")
.join("Encode.roc")
}
/// Writing out the types into content is inconvenient, so we use a DSL for testing.
#[macro_export]
macro_rules! v {
({ $($field:ident: $make_v:expr,)* $(?$opt_field:ident : $make_opt_v:expr,)* }) => {
|subs: &mut Subs| {
$(let $field = $make_v(subs);)*
$(let $opt_field = $make_opt_v(subs);)*
let fields = vec![
$( (stringify!($field).into(), RecordField::Required($field)) ,)*
$( (stringify!($opt_field).into(), RecordField::Required($opt_field)) ,)*
];
let fields = RecordFields::insert_into_subs(subs, fields);
synth_var(subs, Content::Structure(FlatType::Record(fields, Variable::EMPTY_RECORD)))
}
};
([ $($tag:ident $($payload:expr)*),* ]) => {
|subs: &mut Subs| {
$(
let $tag = vec![ $( $payload(subs), )* ];
)*
let tags = UnionTags::insert_into_subs::<_, Vec<Variable>>(subs, vec![ $( (TagName(stringify!($tag).into()), $tag) ,)* ]);
synth_var(subs, Content::Structure(FlatType::TagUnion(tags, Variable::EMPTY_TAG_UNION)))
}
};
([ $($tag:ident $($payload:expr)*),* ] as $rec_var:ident) => {
|subs: &mut Subs| {
let $rec_var = subs.fresh_unnamed_flex_var();
let rec_name_index =
SubsIndex::push_new(&mut subs.field_names, stringify!($rec).into());
$(
let $tag = vec![ $( $payload(subs), )* ];
)*
let tags = UnionTags::insert_into_subs::<_, Vec<Variable>>(subs, vec![ $( (TagName(stringify!($tag).into()), $tag) ,)* ]);
let tag_union_var = synth_var(subs, Content::Structure(FlatType::RecursiveTagUnion($rec_var, tags, Variable::EMPTY_TAG_UNION)));
subs.set_content(
$rec_var,
Content::RecursionVar {
structure: tag_union_var,
opt_name: Some(rec_name_index),
},
);
tag_union_var
}
};
(Symbol::$sym:ident $($arg:expr)*) => {
|subs: &mut Subs| {
let $sym = vec![ $( $arg(subs) ,)* ];
let var_slice = SubsSlice::insert_into_subs(subs, $sym);
synth_var(subs, Content::Structure(FlatType::Apply(Symbol::$sym, var_slice)))
}
};
(Symbol::$alias:ident $($arg:expr)* => $real_var:expr) => {
|subs: &mut Subs| {
let args = vec![$( $arg(subs) )*];
let alias_variables = AliasVariables::insert_into_subs::<Vec<_>, Vec<_>>(subs, args, vec![]);
let real_var = $real_var(subs);
synth_var(subs, Content::Alias(Symbol::$alias, alias_variables, real_var, AliasKind::Structural))
}
};
(@Symbol::$alias:ident $($arg:expr)* => $real_var:expr) => {
|subs: &mut Subs| {
let args = vec![$( $arg(subs) )*];
let alias_variables = AliasVariables::insert_into_subs::<Vec<_>, Vec<_>>(subs, args, vec![]);
let real_var = $real_var(subs);
synth_var(subs, Content::Alias(Symbol::$alias, alias_variables, real_var, AliasKind::Opaque))
}
};
(*$rec_var:ident) => {
|_: &mut Subs| { $rec_var }
};
($var:ident) => {
|_: &mut Subs| { Variable::$var }
};
}
#[macro_export]
macro_rules! test_hash_eq {
($($name:ident: $synth1:expr, $synth2:expr)*) => {$(
#[test]
fn $name() {
check_key(true, $synth1, $synth2)
}
)*};
}
#[macro_export]
macro_rules! test_hash_neq {
($($name:ident: $synth1:expr, $synth2:expr)*) => {$(
#[test]
fn $name() {
check_key(false, $synth1, $synth2)
}
)*};
}
#[allow(clippy::too_many_arguments)]
fn assemble_derived_golden(
subs: &mut Subs,
test_module: ModuleId,
interns: &Interns,
source_var: Variable,
derived_source: &str,
typ: Variable,
specialization_lsets: SpecializationLambdaSets,
) -> String {
let mut print_var = |var: Variable, print_only_under_alias| {
let snapshot = subs.snapshot();
let pretty_type = name_and_print_var(
var,
subs,
test_module,
interns,
DebugPrint {
print_lambda_sets: true,
print_only_under_alias,
},
);
subs.rollback_to(snapshot);
pretty_type
};
let mut pretty_buf = String::new();
pretty_buf.push_str(&format!("# derived for {}\n", print_var(source_var, false)));
let pretty_type = print_var(typ, false);
pretty_buf.push_str(&format!("# {}\n", &pretty_type));
let pretty_type_under_aliases = print_var(typ, true);
pretty_buf.push_str(&format!("# {}\n", &pretty_type_under_aliases));
pretty_buf.push_str("# Specialization lambda sets:\n");
let mut specialization_lsets = specialization_lsets.into_iter().collect::<Vec<_>>();
specialization_lsets.sort_by_key(|(region, _)| *region);
for (region, var) in specialization_lsets {
let pretty_lset = print_var(var, false);
pretty_buf.push_str(&format!("# @<{}>: {}\n", region, pretty_lset));
}
pretty_buf.push_str(derived_source);
pretty_buf
}
#[allow(clippy::too_many_arguments)]
fn check_derived_typechecks_and_golden(
derived_def: Def,
test_module: ModuleId,
mut test_subs: Subs,
interns: &Interns,
exposed_encode_types: ExposedTypesStorageSubs,
encode_abilities_store: AbilitiesStore,
source_var: Variable,
derived_program: &str,
specialization_lsets: SpecializationLambdaSets,
check_golden: impl Fn(&str),
) {
// constrain the derived
let mut constraints = Constraints::new();
let def_var = derived_def.expr_var;
let mut decls = Declarations::new();
decls.push_def(derived_def);
let constr = constrain_decls(&mut constraints, test_module, &decls);
// the derived depends on stuff from Encode, so
// - we need to add those dependencies as imported on the constraint
// - we need to add Encode ability info to a local abilities store
let encode_values_to_import = exposed_encode_types
.stored_vars_by_symbol
.keys()
.copied()
.collect::<VecSet<_>>();
let pending_abilities = encode_abilities_store.closure_from_imported(&encode_values_to_import);
let mut exposed_by_module = ExposedByModule::default();
exposed_by_module.insert(
ModuleId::ENCODE,
ExposedModuleTypes {
exposed_types_storage_subs: exposed_encode_types,
resolved_implementations: ResolvedImplementations::default(),
},
);
let exposed_for_module =
ExposedForModule::new(encode_values_to_import.iter(), exposed_by_module);
let mut def_types = Default::default();
let mut rigid_vars = Default::default();
let (import_variables, abilities_store) = add_imports(
test_module,
&mut test_subs,
pending_abilities,
&exposed_for_module,
&mut def_types,
&mut rigid_vars,
);
let constr =
constraints.let_import_constraint(rigid_vars, def_types, constr, &import_variables);
// run the solver, print and fail if we have errors
dbg_do!(
roc_debug_flags::ROC_PRINT_UNIFICATIONS_DERIVED,
std::env::set_var(roc_debug_flags::ROC_PRINT_UNIFICATIONS_DERIVED, "1")
);
let (mut solved_subs, _, problems, _) = roc_solve::module::run_solve(
test_module,
&constraints,
constr,
RigidVariables::default(),
test_subs,
default_aliases(),
abilities_store,
Default::default(),
&exposed_for_module.exposed_by_module,
Default::default(),
);
let subs = solved_subs.inner_mut();
if !problems.is_empty() {
let filename = PathBuf::from("Test.roc");
let lines = LineInfo::new(" ");
let src_lines = vec![" "];
let mut reports = Vec::new();
let alloc = RocDocAllocator::new(&src_lines, test_module, interns);
for problem in problems.into_iter() {
if let Some(report) = type_problem(&alloc, &lines, filename.clone(), problem.clone()) {
reports.push(report);
}
}
let has_reports = !reports.is_empty();
let doc = alloc
.stack(reports.into_iter().map(|v| v.pretty(&alloc)))
.append(if has_reports {
alloc.line()
} else {
alloc.nil()
});
let mut buf = String::new();
doc.1
.render_raw(80, &mut roc_reporting::report::CiWrite::new(&mut buf))
.unwrap();
panic!(
"Derived does not typecheck:\n{}\nDerived def:\n{}",
buf, derived_program
);
}
let golden = assemble_derived_golden(
subs,
test_module,
interns,
source_var,
derived_program,
def_var,
specialization_lsets,
);
check_golden(&golden)
}
fn get_key(subs: &Subs, var: Variable) -> DeriveKey {
match Derived::encoding(subs, var) {
Ok(Derived::Key(key)) => key,
_ => unreachable!(),
}
}
pub(crate) fn derive_test<S>(synth_input: S, check_golden: impl Fn(&str))
where
S: FnOnce(&mut Subs) -> Variable,
{
let arena = Bump::new();
let source = roc_builtins::roc::module_source(ModuleId::ENCODE);
let target_info = roc_target::TargetInfo::default_x86_64();
let LoadedModule {
mut interns,
exposed_types_storage: exposed_encode_types,
abilities_store,
resolved_implementations,
..
} = roc_load_internal::file::load_and_typecheck_str(
&arena,
encode_path().file_name().unwrap().into(),
source,
encode_path().parent().unwrap().to_path_buf(),
Default::default(),
target_info,
roc_reporting::report::RenderTarget::ColorTerminal,
Threading::AllAvailable,
)
.unwrap();
let mut subs = Subs::new();
let ident_ids = IdentIds::default();
let source_var = synth_input(&mut subs);
let key = get_key(&subs, source_var);
let mut derived_module = unsafe { DerivedModule::from_components(subs, ident_ids) };
let mut exposed_by_module = ExposedByModule::default();
exposed_by_module.insert(
ModuleId::ENCODE,
ExposedModuleTypes {
exposed_types_storage_subs: exposed_encode_types.clone(),
resolved_implementations,
},
);
let (_derived_symbol, derived_def, specialization_lsets) =
derived_module.get_or_insert(&exposed_by_module, key);
let specialization_lsets = specialization_lsets.clone();
let derived_def = derived_def.clone();
let (subs, ident_ids) = derived_module.decompose();
interns.all_ident_ids.insert(DERIVED_MODULE, ident_ids);
DERIVED_MODULE.register_debug_idents(interns.all_ident_ids.get(&DERIVED_MODULE).unwrap());
let ctx = Ctx { interns: &interns };
let derived_program = pretty_print_def(&ctx, &derived_def);
check_derived_typechecks_and_golden(
derived_def,
DERIVED_MODULE,
subs,
&interns,
exposed_encode_types,
abilities_store,
source_var,
&derived_program,
specialization_lsets,
check_golden,
);
}