Support specialization of ability members that don't decay to functions

This commit is contained in:
Ayaz Hafiz 2022-08-03 10:16:22 -05:00
parent b4e7ae0654
commit b62c9d1faa
No known key found for this signature in database
GPG key ID: 0E2A37416A25EF58
5 changed files with 28 additions and 9 deletions

View file

@ -16,6 +16,7 @@ use roc_types::subs::{
};
use util::Env;
mod decoding;
mod encoding;
mod util;

View file

@ -12,6 +12,7 @@ roc_region = { path = "../region" }
roc_module = { path = "../module" }
roc_types = { path = "../types" }
roc_can = { path = "../can" }
roc_derive_key = { path = "../derive_key" }
roc_derive = { path = "../derive" }
roc_late_solve = { path = "../late_solve" }
roc_std = { path = "../../roc_std", default-features = false }

View file

@ -4921,7 +4921,7 @@ pub fn with_hole<'a>(
let resolved_proc = match resolved_proc {
Resolved::Specialization(symbol) => symbol,
Resolved::NeedsGenerated => {
Resolved::NeedsGenerated(_) => {
todo_abilities!("Generate impls for structural types")
}
};
@ -5236,8 +5236,22 @@ fn late_resolve_ability_specialization<'a>(
match specialization {
Resolved::Specialization(symbol) => symbol,
Resolved::NeedsGenerated => {
todo_abilities!("Generate impls for structural types")
Resolved::NeedsGenerated(var) => {
let derive_key = roc_derive_key::Derived::builtin(
roc_derive_key::DeriveBuiltin::Decoder,
env.subs,
var,
)
.expect("not a builtin");
match derive_key {
roc_derive_key::Derived::Immediate(imm) => {
// The immediate is an ability member itself, so it must be resolved!
late_resolve_ability_specialization(env, imm, None, specialization_var)
}
roc_derive_key::Derived::Key(_) => {
todo_abilities!("support derived specializations that aren't immediates")
}
}
}
}
}

View file

@ -1,7 +1,7 @@
use roc_can::abilities::AbilitiesStore;
use roc_can::expr::PendingDerives;
use roc_collections::{VecMap, VecSet};
use roc_error_macros::internal_error;
use roc_error_macros::{internal_error, todo_abilities};
use roc_module::symbol::Symbol;
use roc_region::all::{Loc, Region};
use roc_solve_problem::{TypeError, UnderivableReason, Unfulfilled};
@ -825,8 +825,8 @@ pub fn type_implementing_specialization(
pub enum Resolved {
/// A user-defined specialization should be used.
Specialization(Symbol),
/// A specialization must be generated.
NeedsGenerated,
/// A specialization must be generated for the given type variable.
NeedsGenerated(Variable),
}
/// An [`AbilityResolver`] is a shell of an abilities store that answers questions needed for
@ -910,15 +910,17 @@ pub fn resolve_ability_specialization<R: AbilityResolver>(
roc_types::types::MemberImpl::Impl(spec_symbol) => {
Resolved::Specialization(spec_symbol)
}
roc_types::types::MemberImpl::Derived => Resolved::NeedsGenerated,
roc_types::types::MemberImpl::Derived => {
todo_abilities!("get type from obligated opaque")
}
// TODO this is not correct. We can replace `Resolved` with `MemberImpl` entirely,
// which will make this simpler.
roc_types::types::MemberImpl::Error => Resolved::Specialization(Symbol::UNDERSCORE),
}
}
Obligated::Adhoc(_) => {
Obligated::Adhoc(variable) => {
// TODO: more rules need to be validated here, like is this a builtin ability?
Resolved::NeedsGenerated
Resolved::NeedsGenerated(variable)
}
};