mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-01 15:51:12 +00:00
Split up unify_rigid into unify_rigid, unify_rigid_able
This commit is contained in:
parent
bef83324da
commit
5f5f025e4c
1 changed files with 73 additions and 35 deletions
|
@ -379,9 +379,9 @@ fn unify_context(subs: &mut Subs, pool: &mut Pool, ctx: Context) -> Outcome {
|
||||||
*structure,
|
*structure,
|
||||||
&ctx.second_desc.content,
|
&ctx.second_desc.content,
|
||||||
),
|
),
|
||||||
RigidVar(name) => unify_rigid(subs, &ctx, name, None, &ctx.second_desc.content),
|
RigidVar(name) => unify_rigid(subs, &ctx, name, &ctx.second_desc.content),
|
||||||
RigidAbleVar(name, ability) => {
|
RigidAbleVar(name, ability) => {
|
||||||
unify_rigid(subs, &ctx, name, Some(*ability), &ctx.second_desc.content)
|
unify_rigid_able(subs, &ctx, name, *ability, &ctx.second_desc.content)
|
||||||
}
|
}
|
||||||
Structure(flat_type) => {
|
Structure(flat_type) => {
|
||||||
unify_structure(subs, pool, &ctx, flat_type, &ctx.second_desc.content)
|
unify_structure(subs, pool, &ctx, flat_type, &ctx.second_desc.content)
|
||||||
|
@ -1912,7 +1912,6 @@ fn unify_rigid(
|
||||||
subs: &mut Subs,
|
subs: &mut Subs,
|
||||||
ctx: &Context,
|
ctx: &Context,
|
||||||
name: &SubsIndex<Lowercase>,
|
name: &SubsIndex<Lowercase>,
|
||||||
opt_able_bound: Option<Symbol>,
|
|
||||||
other: &Content,
|
other: &Content,
|
||||||
) -> Outcome {
|
) -> Outcome {
|
||||||
match other {
|
match other {
|
||||||
|
@ -1921,31 +1920,73 @@ fn unify_rigid(
|
||||||
merge(subs, ctx, RigidVar(*name))
|
merge(subs, ctx, RigidVar(*name))
|
||||||
}
|
}
|
||||||
FlexAbleVar(_, other_ability) => {
|
FlexAbleVar(_, other_ability) => {
|
||||||
match opt_able_bound {
|
// Mismatch - Rigid can unify with FlexAble only when the Rigid has an ability
|
||||||
Some(ability) => {
|
// bound as well, otherwise the user failed to correctly annotate the bound.
|
||||||
if ability == *other_ability {
|
mismatch!(
|
||||||
// The ability bounds are the same, so rigid wins!
|
%not_able, ctx.first, *other_ability,
|
||||||
merge(subs, ctx, RigidAbleVar(*name, ability))
|
"Rigid {:?} with FlexAble {:?}", ctx.first, other
|
||||||
} else {
|
)
|
||||||
// Mismatch for now.
|
}
|
||||||
// TODO check ability hierarchies.
|
|
||||||
mismatch!(
|
RigidVar(_)
|
||||||
%not_able, ctx.second, ability,
|
| RecursionVar { .. }
|
||||||
"RigidAble {:?} with ability {:?} not compatible with ability {:?}",
|
| Structure(_)
|
||||||
ctx.first,
|
| Alias(_, _, _, _)
|
||||||
ability,
|
| RangedNumber(..)
|
||||||
other_ability
|
| LambdaSet(..)
|
||||||
)
|
if ctx.mode.contains(Mode::RIGID_AS_FLEX) =>
|
||||||
}
|
{
|
||||||
}
|
// Usually rigids can only unify with flex, but the mode indicates we are treating
|
||||||
None => {
|
// rigid vars as flex, so admit this.
|
||||||
// Mismatch - Rigid can unify with FlexAble only when the Rigid has an ability
|
merge(subs, ctx, *other)
|
||||||
// bound as well, otherwise the user failed to correctly annotate the bound.
|
}
|
||||||
mismatch!(
|
|
||||||
%not_able, ctx.first, *other_ability,
|
RigidVar(_)
|
||||||
"Rigid {:?} with FlexAble {:?}", ctx.first, other
|
| RigidAbleVar(..)
|
||||||
)
|
| RecursionVar { .. }
|
||||||
}
|
| Structure(_)
|
||||||
|
| Alias(..)
|
||||||
|
| RangedNumber(..)
|
||||||
|
| LambdaSet(..) => {
|
||||||
|
// Type mismatch! Rigid can only unify with flex, even if the
|
||||||
|
// rigid names are the same.
|
||||||
|
mismatch!("Rigid {:?} with {:?}", ctx.first, &other)
|
||||||
|
}
|
||||||
|
|
||||||
|
Error => {
|
||||||
|
// Error propagates.
|
||||||
|
merge(subs, ctx, Error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn unify_rigid_able(
|
||||||
|
subs: &mut Subs,
|
||||||
|
ctx: &Context,
|
||||||
|
name: &SubsIndex<Lowercase>,
|
||||||
|
ability: Symbol,
|
||||||
|
other: &Content,
|
||||||
|
) -> Outcome {
|
||||||
|
match other {
|
||||||
|
FlexVar(_) => {
|
||||||
|
// If the other is flex, rigid wins!
|
||||||
|
merge(subs, ctx, RigidVar(*name))
|
||||||
|
}
|
||||||
|
FlexAbleVar(_, other_ability) => {
|
||||||
|
if ability == *other_ability {
|
||||||
|
// The ability bounds are the same, so rigid wins!
|
||||||
|
merge(subs, ctx, RigidAbleVar(*name, ability))
|
||||||
|
} else {
|
||||||
|
// Mismatch for now.
|
||||||
|
// TODO check ability hierarchies.
|
||||||
|
mismatch!(
|
||||||
|
%not_able, ctx.second, ability,
|
||||||
|
"RigidAble {:?} with ability {:?} not compatible with ability {:?}",
|
||||||
|
ctx.first,
|
||||||
|
ability,
|
||||||
|
other_ability
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1959,11 +2000,8 @@ fn unify_rigid(
|
||||||
{
|
{
|
||||||
// Usually rigids can only unify with flex, but the mode indicates we are treating
|
// Usually rigids can only unify with flex, but the mode indicates we are treating
|
||||||
// rigid vars as flex, so admit this.
|
// rigid vars as flex, so admit this.
|
||||||
match (opt_able_bound, other) {
|
match other {
|
||||||
(None, other) => merge(subs, ctx, *other),
|
Alias(opaque_name, vars, _real_var, AliasKind::Opaque) if vars.is_empty() => {
|
||||||
(Some(ability), Alias(opaque_name, vars, _real_var, AliasKind::Opaque))
|
|
||||||
if vars.is_empty() =>
|
|
||||||
{
|
|
||||||
let mut output = merge(subs, ctx, *other);
|
let mut output = merge(subs, ctx, *other);
|
||||||
let must_implement_ability = MustImplementAbility {
|
let must_implement_ability = MustImplementAbility {
|
||||||
typ: Obligated::Opaque(*opaque_name),
|
typ: Obligated::Opaque(*opaque_name),
|
||||||
|
@ -1974,10 +2012,10 @@ fn unify_rigid(
|
||||||
}
|
}
|
||||||
|
|
||||||
// these have underscores because they're unused in --release builds
|
// these have underscores because they're unused in --release builds
|
||||||
(Some(_ability), _other) => {
|
_other => {
|
||||||
// For now, only allow opaque types with no type variables to implement abilities.
|
// For now, only allow opaque types with no type variables to implement abilities.
|
||||||
mismatch!(
|
mismatch!(
|
||||||
%not_able, ctx.second, _ability,
|
%not_able, ctx.second, ability,
|
||||||
"RigidAble {:?} with non-opaque or opaque with type variables {:?}",
|
"RigidAble {:?} with non-opaque or opaque with type variables {:?}",
|
||||||
ctx.first,
|
ctx.first,
|
||||||
&_other
|
&_other
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue