From b62c9d1faa405a02b2e515ff59899d1bd79be32d Mon Sep 17 00:00:00 2001 From: Ayaz Hafiz Date: Wed, 3 Aug 2022 10:16:22 -0500 Subject: [PATCH] Support specialization of ability members that don't decay to functions --- Cargo.lock | 1 + crates/compiler/derive/src/lib.rs | 1 + crates/compiler/mono/Cargo.toml | 1 + crates/compiler/mono/src/ir.rs | 20 +++++++++++++++++--- crates/compiler/solve/src/ability.rs | 14 ++++++++------ 5 files changed, 28 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8885228fe1..384b8fc04b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3859,6 +3859,7 @@ dependencies = [ "roc_collections", "roc_debug_flags", "roc_derive", + "roc_derive_key", "roc_error_macros", "roc_exhaustive", "roc_late_solve", diff --git a/crates/compiler/derive/src/lib.rs b/crates/compiler/derive/src/lib.rs index 41c1a3b8ad..59f6447146 100644 --- a/crates/compiler/derive/src/lib.rs +++ b/crates/compiler/derive/src/lib.rs @@ -16,6 +16,7 @@ use roc_types::subs::{ }; use util::Env; +mod decoding; mod encoding; mod util; diff --git a/crates/compiler/mono/Cargo.toml b/crates/compiler/mono/Cargo.toml index c1fa81d366..3fec3f6ab7 100644 --- a/crates/compiler/mono/Cargo.toml +++ b/crates/compiler/mono/Cargo.toml @@ -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 } diff --git a/crates/compiler/mono/src/ir.rs b/crates/compiler/mono/src/ir.rs index 681ab3508e..454ab40609 100644 --- a/crates/compiler/mono/src/ir.rs +++ b/crates/compiler/mono/src/ir.rs @@ -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") + } + } } } } diff --git a/crates/compiler/solve/src/ability.rs b/crates/compiler/solve/src/ability.rs index 0d02cbb21d..dc88e6a877 100644 --- a/crates/compiler/solve/src/ability.rs +++ b/crates/compiler/solve/src/ability.rs @@ -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( 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) } };