mirror of
https://github.com/roc-lang/roc.git
synced 2025-08-31 09:07:21 +00:00
Content variant ErasedLambda
This commit is contained in:
parent
c459757062
commit
6e5a308557
20 changed files with 147 additions and 93 deletions
|
@ -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),
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue