mirror of
https://github.com/roc-lang/roc.git
synced 2025-08-03 11:52:19 +00:00
Attempt occurs checks for recursive lambda sets only during monomorphization
This commit is contained in:
parent
5d31ec762d
commit
086f7a7e9d
2 changed files with 22 additions and 9 deletions
|
@ -156,6 +156,7 @@ pub trait MetaCollector: Default + std::fmt::Debug {
|
|||
/// be kept around, and the record `(member, 1) => specialization-lambda-set` will be
|
||||
/// associated via [`Self::record_specialization_lambda_set`].
|
||||
const UNIFYING_SPECIALIZATION: bool;
|
||||
const IS_LATE: bool;
|
||||
|
||||
fn record_specialization_lambda_set(&mut self, member: Symbol, region: u8, var: Variable);
|
||||
|
||||
|
@ -168,6 +169,7 @@ pub trait MetaCollector: Default + std::fmt::Debug {
|
|||
pub struct NoCollector;
|
||||
impl MetaCollector for NoCollector {
|
||||
const UNIFYING_SPECIALIZATION: bool = false;
|
||||
const IS_LATE: bool = false;
|
||||
|
||||
#[inline(always)]
|
||||
fn record_specialization_lambda_set(&mut self, _member: Symbol, _region: u8, _var: Variable) {}
|
||||
|
@ -184,6 +186,7 @@ pub struct SpecializationLsetCollector(pub VecMap<(Symbol, u8), Variable>);
|
|||
|
||||
impl MetaCollector for SpecializationLsetCollector {
|
||||
const UNIFYING_SPECIALIZATION: bool = true;
|
||||
const IS_LATE: bool = false;
|
||||
|
||||
#[inline(always)]
|
||||
fn record_specialization_lambda_set(&mut self, member: Symbol, region: u8, var: Variable) {
|
||||
|
@ -1240,15 +1243,24 @@ fn separate_union_lambdas<M: MetaCollector>(
|
|||
for (var1, var2) in (left_slice.into_iter()).zip(right_slice.into_iter()) {
|
||||
let (var1, var2) = (env.subs[var1], env.subs[var2]);
|
||||
|
||||
// Lambda sets are effectively tags under another name, and their usage can also result
|
||||
// in the arguments of a lambda name being recursive. It very well may happen that
|
||||
// during unification, a lambda set previously marked as not recursive becomes
|
||||
// recursive. See the docs of [LambdaSet] for one example, or https://github.com/roc-lang/roc/pull/2307.
|
||||
//
|
||||
// Like with tag unions, if it has, we'll always pass through this branch. So, take
|
||||
// this opportunity to promote the lambda set to recursive if need be.
|
||||
maybe_mark_union_recursive(env, var1);
|
||||
maybe_mark_union_recursive(env, var2);
|
||||
if M::IS_LATE {
|
||||
// Lambda sets are effectively tags under another name, and their usage can also result
|
||||
// in the arguments of a lambda name being recursive. It very well may happen that
|
||||
// during unification, a lambda set previously marked as not recursive becomes
|
||||
// recursive. See the docs of [LambdaSet] for one example, or https://github.com/roc-lang/roc/pull/2307.
|
||||
//
|
||||
// Like with tag unions, if it is, we'll always pass through this branch. So, take
|
||||
// this opportunity to promote the lambda set to recursive if need be.
|
||||
//
|
||||
// THEORY: observe that this check only happens in late unification
|
||||
// (i.e. code generation, typically). We believe this to be correct
|
||||
// because while recursive lambda sets must be collapsed to the
|
||||
// code generator, we have not yet observed a case where they must
|
||||
// collapsed to the type checker of the surface syntax.
|
||||
// It is possible this assumption will be invalidated!
|
||||
maybe_mark_union_recursive(env, var1);
|
||||
maybe_mark_union_recursive(env, var2);
|
||||
}
|
||||
|
||||
// Check whether the two type variables in the closure set are
|
||||
// unifiable. If they are, we can unify them and continue on assuming
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue