Compile lambdas that have an empty lambda set

Closes #3224

This should also fix a number of other issues often observed when a
lambda is never actually called, but we fail to codegen because it has
an empty lambda set.
This commit is contained in:
ayazhafiz 2022-07-05 23:35:41 -04:00 committed by Ayaz Hafiz
parent 7365da6f69
commit 937b73b797
No known key found for this signature in database
GPG key ID: 0E2A37416A25EF58
6 changed files with 89 additions and 14 deletions

View file

@ -15,6 +15,7 @@ use roc_debug_flags::dbg_do;
#[cfg(debug_assertions)]
use roc_debug_flags::{
ROC_PRINT_IR_AFTER_REFCOUNT, ROC_PRINT_IR_AFTER_RESET_REUSE, ROC_PRINT_IR_AFTER_SPECIALIZATION,
ROC_PRINT_RUNTIME_ERROR_GEN,
};
use roc_derive_key::GlobalDerivedSymbols;
use roc_error_macros::{internal_error, todo_abilities};
@ -2807,10 +2808,12 @@ fn generate_runtime_error_function<'a>(
)
.unwrap();
eprintln!(
"emitted runtime error function {:?} for layout {:?}",
&msg, layout
);
dbg_do!(ROC_PRINT_RUNTIME_ERROR_GEN, {
eprintln!(
"emitted runtime error function {:?} for layout {:?}",
&msg, layout
);
});
let runtime_error = Stmt::RuntimeError(msg.into_bump_str());
@ -2878,6 +2881,15 @@ fn specialize_external<'a>(
let specialized =
build_specialized_proc_from_var(env, layout_cache, lambda_name, pattern_symbols, fn_var)?;
let recursivity = if partial_proc.is_self_recursive {
SelfRecursive::SelfRecursive(JoinPointId(env.unique_symbol()))
} else {
SelfRecursive::NotSelfRecursive
};
let body = partial_proc.body.clone();
let body_var = partial_proc.body_var;
// determine the layout of aliases/rigids exposed to the host
let host_exposed_layouts = if host_exposed_variables.is_empty() {
HostExposedLayouts::NotHostExposed
@ -2922,6 +2934,7 @@ fn specialize_external<'a>(
let body = match_on_lambda_set(
env,
procs,
lambda_set,
Symbol::ARG_CLOSURE,
argument_symbols.into_bump_slice(),
@ -2965,15 +2978,7 @@ fn specialize_external<'a>(
}
};
let recursivity = if partial_proc.is_self_recursive {
SelfRecursive::SelfRecursive(JoinPointId(env.unique_symbol()))
} else {
SelfRecursive::NotSelfRecursive
};
let body = partial_proc.body.clone();
let mut specialized_body = from_can(env, partial_proc.body_var, body, procs, layout_cache);
let mut specialized_body = from_can(env, body_var, body, procs, layout_cache);
match specialized {
SpecializedLayout::FunctionPointerBody {
@ -4712,6 +4717,7 @@ pub fn with_hole<'a>(
result = match_on_lambda_set(
env,
procs,
lambda_set,
closure_data_symbol,
arg_symbols,
@ -4752,6 +4758,7 @@ pub fn with_hole<'a>(
result = match_on_lambda_set(
env,
procs,
lambda_set,
closure_data_symbol,
arg_symbols,
@ -4809,6 +4816,7 @@ pub fn with_hole<'a>(
result = match_on_lambda_set(
env,
procs,
lambda_set,
closure_data_symbol,
arg_symbols,
@ -7485,6 +7493,7 @@ fn call_by_name<'a>(
let result = match_on_lambda_set(
env,
procs,
lambda_set,
closure_data_symbol,
arg_symbols,
@ -8045,6 +8054,7 @@ fn call_specialized_proc<'a>(
let new_hole = match_on_lambda_set(
env,
procs,
lambda_set,
closure_data_symbol,
field_symbols,
@ -9118,6 +9128,7 @@ where
#[allow(clippy::too_many_arguments)]
fn match_on_lambda_set<'a>(
env: &mut Env<'a, '_>,
procs: &mut Procs<'a>,
lambda_set: LambdaSet<'a>,
closure_data_symbol: Symbol,
argument_symbols: &'a [Symbol],
@ -9161,7 +9172,22 @@ fn match_on_lambda_set<'a>(
field_layouts,
field_order_hash,
} => {
let function_symbol = lambda_set.iter_set().next().unwrap();
let function_symbol = match lambda_set.iter_set().next() {
Some(function_symbol) => function_symbol,
None => {
// Lambda set is empty, so this function is never called; synthesize a function
// that always yields a runtime error.
let name = env.unique_symbol();
let function_layout =
RawFunctionLayout::Function(argument_layouts, lambda_set, return_layout);
let proc = generate_runtime_error_function(env, name, function_layout);
let top_level =
ProcLayout::from_raw(env.arena, function_layout, CapturesNiche::no_niche());
procs.specialized.insert_specialized(name, top_level, proc);
LambdaName::no_niche(name)
}
};
let closure_info = match field_layouts {
[] => ClosureInfo::DoesNotCapture,