Content variant ErasedLambda

This commit is contained in:
Ayaz Hafiz 2023-06-23 15:53:08 -05:00
parent c459757062
commit 6e5a308557
No known key found for this signature in database
GPG key ID: 0E2A37416A25EF58
20 changed files with 147 additions and 93 deletions

View file

@ -5,7 +5,7 @@ use roc_debug_flags::{dbg_do, dbg_set};
use roc_debug_flags::{
ROC_PRINT_MISMATCHES, ROC_PRINT_UNIFICATIONS, ROC_VERIFY_OCCURS_ONE_RECURSION,
};
use roc_error_macros::internal_error;
use roc_error_macros::{internal_error, todo_lambda_erasure};
use roc_module::ident::{Lowercase, TagName};
use roc_module::symbol::{ModuleId, Symbol};
use roc_types::num::{FloatWidth, IntLitWidth, NumericRange};
@ -611,6 +611,7 @@ fn unify_context<M: MetaCollector>(env: &mut Env, pool: &mut Pool, ctx: Context)
unify_opaque(env, pool, &ctx, *symbol, *args, *real_var)
}
LambdaSet(lset) => unify_lambda_set(env, pool, &ctx, *lset, &ctx.second_desc.content),
ErasedLambda => unify_erased_lambda(env, pool, &ctx, &ctx.second_desc.content),
&RangedNumber(range_vars) => unify_ranged_number(env, pool, &ctx, range_vars),
Error => {
// Error propagates. Whatever we're comparing it to doesn't matter!
@ -680,7 +681,7 @@ fn unify_ranged_number<M: MetaCollector>(
Some(range) => merge(env, ctx, RangedNumber(range)),
None => not_in_range_mismatch(),
},
LambdaSet(..) => mismatch!(),
LambdaSet(..) | ErasedLambda => mismatch!(),
Error => merge(env, ctx, Error),
}
}
@ -1004,6 +1005,7 @@ fn unify_alias<M: MetaCollector>(
check_and_merge_valid_range(env, pool, ctx, ctx.second, *other_range_vars, ctx.first)
}
LambdaSet(..) => mismatch!("cannot unify alias {:?} with lambda set {:?}: lambda sets should never be directly behind an alias!", ctx.first, other_content),
ErasedLambda => mismatch!("cannot unify alias {:?} with an erased lambda!", ctx.first),
Error => merge(env, ctx, Error),
}
}
@ -1198,10 +1200,9 @@ fn unify_structure<M: MetaCollector>(
"Cannot unify structure \n{:?} \nwith lambda set\n {:?}",
roc_types::subs::SubsFmtContent(&Content::Structure(*flat_type), env.subs),
roc_types::subs::SubsFmtContent(other, env.subs),
// &flat_type,
// other
)
}
ErasedLambda => mismatch!(),
RangedNumber(other_range_vars) => {
check_and_merge_valid_range(env, pool, ctx, ctx.second, *other_range_vars, ctx.first)
}
@ -1209,6 +1210,38 @@ fn unify_structure<M: MetaCollector>(
}
}
#[inline(always)]
#[must_use]
fn unify_erased_lambda<M: MetaCollector>(
env: &mut Env,
pool: &mut Pool,
ctx: &Context,
other: &Content,
) -> Outcome<M> {
match other {
FlexVar(_) => {
if M::UNIFYING_SPECIALIZATION {
todo_lambda_erasure!()
}
merge(env, ctx, Content::ErasedLambda)
}
Content::LambdaSet(..) => {
if M::UNIFYING_SPECIALIZATION {
todo_lambda_erasure!()
}
merge(env, ctx, Content::ErasedLambda)
}
ErasedLambda => merge(env, ctx, Content::ErasedLambda),
RecursionVar { structure, .. } => unify_pool(env, pool, ctx.first, *structure, ctx.mode),
RigidVar(..) | RigidAbleVar(..) => mismatch!("Lambda sets never unify with rigid"),
FlexAbleVar(..) => mismatch!("Lambda sets should never have abilities attached to them"),
Structure(..) => mismatch!("Lambda set cannot unify with non-lambda set structure"),
RangedNumber(..) => mismatch!("Lambda sets are never numbers"),
Alias(..) => mismatch!("Lambda set can never be directly under an alias!"),
Error => merge(env, ctx, Error),
}
}
#[inline(always)]
#[must_use]
fn unify_lambda_set<M: MetaCollector>(
@ -1254,6 +1287,7 @@ fn unify_lambda_set<M: MetaCollector>(
env.remove_recursion_pair(ctx.first, ctx.second);
outcome
}
ErasedLambda => merge(env, ctx, ErasedLambda),
RigidVar(..) | RigidAbleVar(..) => mismatch!("Lambda sets never unify with rigid"),
FlexAbleVar(..) => mismatch!("Lambda sets should never have abilities attached to them"),
Structure(..) => mismatch!("Lambda set cannot unify with non-lambda set structure"),
@ -1862,28 +1896,6 @@ fn unify_unspecialized_lambdas<M: MetaCollector>(
))
}
fn is_erased_lambda(subs: &Subs, lambda_set: UnionLambdas) -> bool {
let labels = lambda_set.labels();
if labels.start == Subs::LAMBDA_NAME_ERASED.start
&& labels.len() == Subs::LAMBDA_NAME_ERASED.len()
{
return true;
}
#[cfg(debug_assertions)]
{
let content_has_erased = lambda_set
.iter_all()
.any(|(lambda, _)| subs[lambda] == Symbol::ERASED_LAMBDA);
assert!(
!content_has_erased,
"lambda set contains erased lambda, but it is not marked as erased!"
);
}
false
}
#[must_use]
fn unify_lambda_set_help<M: MetaCollector>(
env: &mut Env,
@ -1920,20 +1932,6 @@ fn unify_lambda_set_help<M: MetaCollector>(
"Recursion var is present, but it doesn't have a recursive content!"
);
// Fast path: if either set is the erased lambda, they are both erased.
if is_erased_lambda(env.subs, solved1) || is_erased_lambda(env.subs, solved2) {
return merge(
env,
ctx,
Content::LambdaSet(LambdaSet {
solved: UnionLabels::from_tag_name_index(Subs::LAMBDA_NAME_ERASED_INDEX),
recursion_var: OptVariable::NONE,
unspecialized: SubsSlice::empty(),
ambient_function: ambient_function_var,
}),
);
}
let (
mut whole_outcome,
SeparatedUnionLambdas {
@ -3557,7 +3555,8 @@ fn unify_rigid<M: MetaCollector>(
| RecursionVar { .. }
| Structure(_)
| Alias(..)
| LambdaSet(..) => {
| LambdaSet(..)
| ErasedLambda => {
// Type mismatch! Rigid can only unify with flex, even if the
// rigid names are the same.
mismatch!("Rigid {:?} with {:?}", ctx.first, &other)
@ -3617,7 +3616,8 @@ fn unify_rigid_able<M: MetaCollector>(
| Structure(_)
| Alias(..)
| RangedNumber(..)
| LambdaSet(..) => {
| LambdaSet(..)
| ErasedLambda => {
// Type mismatch! Rigid can only unify with flex, even if the
// rigid names are the same.
mismatch!("Rigid {:?} with {:?}", ctx.first, &other)
@ -3657,7 +3657,8 @@ fn unify_flex<M: MetaCollector>(
| Structure(_)
| Alias(_, _, _, _)
| RangedNumber(..)
| LambdaSet(..) => {
| LambdaSet(..)
| ErasedLambda => {
// TODO special-case boolean here
// In all other cases, if left is flex, defer to right.
merge(env, ctx, *other)
@ -3752,7 +3753,7 @@ fn unify_flex_able<M: MetaCollector>(
}
RigidVar(_) => mismatch!("FlexAble can never unify with non-able Rigid"),
LambdaSet(..) => mismatch!("FlexAble with LambdaSet"),
LambdaSet(..) | ErasedLambda => mismatch!("FlexAble with LambdaSet"),
Alias(name, _args, _real_var, AliasKind::Opaque) => {
// Opaque type wins
@ -3921,6 +3922,8 @@ fn unify_recursion<M: MetaCollector>(
unify_pool(env, pool, structure, ctx.second, ctx.mode)
}
ErasedLambda => mismatch!(),
Error => merge(env, ctx, Error),
};