Represent "able" variables with slices of abilities

This commit is contained in:
Ayaz Hafiz 2022-10-12 14:52:38 -05:00
parent 0f0678ce73
commit 229548571b
No known key found for this signature in database
GPG key ID: 0E2A37416A25EF58
10 changed files with 163 additions and 85 deletions

View file

@ -10,7 +10,8 @@ use roc_solve_problem::{
};
use roc_types::num::NumericRange;
use roc_types::subs::{
instantiate_rigids, Content, FlatType, GetSubsSlice, Rank, RecordFields, Subs, Variable,
instantiate_rigids, Content, FlatType, GetSubsSlice, Rank, RecordFields, Subs, SubsSlice,
Variable,
};
use roc_types::types::{AliasKind, Category, MemberImpl, PatternCategory};
use roc_unify::unify::{Env, MustImplementConstraints};
@ -486,6 +487,7 @@ struct Descend(bool);
trait DerivableVisitor {
const ABILITY: Symbol;
const ABILITY_SLICE: SubsSlice<Symbol>;
#[inline(always)]
fn is_derivable_builtin_opaque(_symbol: Symbol) -> bool {
@ -493,8 +495,9 @@ trait DerivableVisitor {
}
#[inline(always)]
fn visit_flex_able(var: Variable, ability: Symbol) -> Result<(), NotDerivable> {
if ability != Self::ABILITY {
fn visit_flex_able(var: Variable, abilities: &[Symbol]) -> Result<(), NotDerivable> {
// TODO(multi-abilities) flex-able can inherit other abilities
if abilities != [Self::ABILITY] {
Err(NotDerivable {
var,
context: NotDerivableContext::NoContext,
@ -505,8 +508,8 @@ trait DerivableVisitor {
}
#[inline(always)]
fn visit_rigid_able(var: Variable, ability: Symbol) -> Result<(), NotDerivable> {
if ability != Self::ABILITY {
fn visit_rigid_able(var: Variable, abilities: &[Symbol]) -> Result<(), NotDerivable> {
if abilities != [Self::ABILITY] {
Err(NotDerivable {
var,
context: NotDerivableContext::NoContext,
@ -636,7 +639,7 @@ trait DerivableVisitor {
match *content {
FlexVar(opt_name) => {
// Promote the flex var to be bound to the ability.
subs.set_content(var, Content::FlexAbleVar(opt_name, Self::ABILITY));
subs.set_content(var, Content::FlexAbleVar(opt_name, Self::ABILITY_SLICE));
}
RigidVar(_) => {
return Err(NotDerivable {
@ -644,8 +647,12 @@ trait DerivableVisitor {
context: NotDerivableContext::NoContext,
})
}
FlexAbleVar(_, ability) => Self::visit_flex_able(var, ability)?,
RigidAbleVar(_, ability) => Self::visit_rigid_able(var, ability)?,
FlexAbleVar(_, abilities) => {
Self::visit_flex_able(var, subs.get_subs_slice(abilities))?
}
RigidAbleVar(_, abilities) => {
Self::visit_rigid_able(var, subs.get_subs_slice(abilities))?
}
RecursionVar {
structure,
opt_name: _,
@ -771,6 +778,7 @@ trait DerivableVisitor {
struct DeriveEncoding;
impl DerivableVisitor for DeriveEncoding {
const ABILITY: Symbol = Symbol::ENCODE_ENCODING;
const ABILITY_SLICE: SubsSlice<Symbol> = Subs::AB_ENCODING;
#[inline(always)]
fn is_derivable_builtin_opaque(symbol: Symbol) -> bool {
@ -849,6 +857,7 @@ impl DerivableVisitor for DeriveEncoding {
struct DeriveDecoding;
impl DerivableVisitor for DeriveDecoding {
const ABILITY: Symbol = Symbol::DECODE_DECODING;
const ABILITY_SLICE: SubsSlice<Symbol> = Subs::AB_DECODING;
#[inline(always)]
fn is_derivable_builtin_opaque(symbol: Symbol) -> bool {
@ -938,6 +947,7 @@ impl DerivableVisitor for DeriveDecoding {
struct DeriveHash;
impl DerivableVisitor for DeriveHash {
const ABILITY: Symbol = Symbol::HASH_HASH_ABILITY;
const ABILITY_SLICE: SubsSlice<Symbol> = Subs::AB_HASH;
#[inline(always)]
fn is_derivable_builtin_opaque(symbol: Symbol) -> bool {

View file

@ -2601,17 +2601,17 @@ fn type_to_variable<'a>(
let copy_var = match opt_abilities {
None => helper!(typ),
Some(abilities) => {
// TODO(abilities)
let ability = abilities[0];
// If this type argument is marked as being bound to an ability, we must
// now correctly instantiate it as so.
match RegisterVariable::from_type(subs, rank, pools, arena, typ) {
RegisterVariable::Direct(var) => {
use Content::*;
match *subs.get_content_without_compacting(var) {
FlexVar(opt_name) => subs
.set_content(var, FlexAbleVar(opt_name, ability)),
FlexVar(opt_name) => {
// TODO(multi-abilities): check run cache
let abilities_slice = SubsSlice::extend_new(&mut subs.symbol_names, abilities.iter().copied());
subs.set_content(var, FlexAbleVar(opt_name, abilities_slice))
},
RigidVar(..) => internal_error!("Rigid var in type arg for {:?} - this is a bug in the solver, or our understanding", actual),
RigidAbleVar(..) | FlexAbleVar(..) => internal_error!("Able var in type arg for {:?} - this is a bug in the solver, or our understanding", actual),
_ => {