Work around symbol specializations not getting captured

This commit is contained in:
Ayaz Hafiz 2022-09-14 16:44:56 -05:00
parent b797e9c0c8
commit 447e1492e1
No known key found for this signature in database
GPG key ID: 0E2A37416A25EF58

View file

@ -7537,7 +7537,31 @@ where
// if this is an imported symbol, then we must make sure it is
// specialized, and wrap the original in a function pointer.
let mut result = result;
for (_, (variable, left)) in needed_specializations_of_left {
let no_specializations_needed = needed_specializations_of_left.len() == 0;
let needed_specializations_of_left = needed_specializations_of_left
.map(|(_, spec)| Some(spec))
// HACK: sometimes specializations can be lost, for example for `x` in
// x = Bool.true
// p = \_ -> x == 1
// that's because when specializing `p`, we collect specializations for `x`, but then
// drop all of them when leaving the body of `p`, because `x` is an argument of `p` in
// such a case.
// So, if we have no recorded specializations, suppose we are in a case like this, and
// generate the default implementation.
//
// TODO: we should fix this properly. I think the way to do it is to only have proc
// specialization only drop specializations of non-captured symbols. That's because
// captured symbols can only ever be specialized outside the closure.
// After that is done, remove this hack.
.chain(if no_specializations_needed {
[Some((variable, left))]
} else {
[None]
})
.filter_map(std::convert::identity);
for (variable, left) in needed_specializations_of_left {
add_needed_external(procs, env, variable, LambdaName::no_niche(right));
let res_layout = layout_cache.from_var(env.arena, variable, env.subs);