Make sure to report error rather than descending as appropriate

This commit is contained in:
Ayaz Hafiz 2023-03-20 16:48:51 -04:00
parent 3d2642b282
commit 3e83e42195
No known key found for this signature in database
GPG key ID: 0E2A37416A25EF58
5 changed files with 72 additions and 60 deletions

View file

@ -79,7 +79,7 @@ impl FlatDecodable {
FlatType::Func(..) => Err(Underivable),
},
Content::Alias(sym, _, real_var, _) => match from_builtin_symbol(sym) {
Some(lambda) => Ok(lambda),
Some(lambda) => lambda,
// NB: I believe it is okay to unwrap opaques here because derivers are only used
// by the backend, and the backend treats opaques like structural aliases.
None => Self::from_var(subs, real_var),
@ -99,27 +99,28 @@ impl FlatDecodable {
}
pub(crate) fn from_builtin_symbol(symbol: Symbol) -> Result<FlatDecodable, DeriveError> {
from_builtin_symbol(symbol).ok_or(DeriveError::Underivable)
from_builtin_symbol(symbol).unwrap_or(Err(DeriveError::Underivable))
}
}
const fn from_builtin_symbol(symbol: Symbol) -> Option<FlatDecodable> {
const fn from_builtin_symbol(symbol: Symbol) -> Option<Result<FlatDecodable, DeriveError>> {
use FlatDecodable::*;
match symbol {
Symbol::BOOL_BOOL => Some(Immediate(Symbol::DECODE_BOOL)),
Symbol::NUM_U8 | Symbol::NUM_UNSIGNED8 => Some(Immediate(Symbol::DECODE_U8)),
Symbol::NUM_U16 | Symbol::NUM_UNSIGNED16 => Some(Immediate(Symbol::DECODE_U16)),
Symbol::NUM_U32 | Symbol::NUM_UNSIGNED32 => Some(Immediate(Symbol::DECODE_U32)),
Symbol::NUM_U64 | Symbol::NUM_UNSIGNED64 => Some(Immediate(Symbol::DECODE_U64)),
Symbol::NUM_U128 | Symbol::NUM_UNSIGNED128 => Some(Immediate(Symbol::DECODE_U128)),
Symbol::NUM_I8 | Symbol::NUM_SIGNED8 => Some(Immediate(Symbol::DECODE_I8)),
Symbol::NUM_I16 | Symbol::NUM_SIGNED16 => Some(Immediate(Symbol::DECODE_I16)),
Symbol::NUM_I32 | Symbol::NUM_SIGNED32 => Some(Immediate(Symbol::DECODE_I32)),
Symbol::NUM_I64 | Symbol::NUM_SIGNED64 => Some(Immediate(Symbol::DECODE_I64)),
Symbol::NUM_I128 | Symbol::NUM_SIGNED128 => Some(Immediate(Symbol::DECODE_I128)),
Symbol::NUM_DEC | Symbol::NUM_DECIMAL => Some(Immediate(Symbol::DECODE_DEC)),
Symbol::NUM_F32 | Symbol::NUM_BINARY32 => Some(Immediate(Symbol::DECODE_F32)),
Symbol::NUM_F64 | Symbol::NUM_BINARY64 => Some(Immediate(Symbol::DECODE_F64)),
Symbol::BOOL_BOOL => Some(Ok(Immediate(Symbol::DECODE_BOOL))),
Symbol::NUM_U8 | Symbol::NUM_UNSIGNED8 => Some(Ok(Immediate(Symbol::DECODE_U8))),
Symbol::NUM_U16 | Symbol::NUM_UNSIGNED16 => Some(Ok(Immediate(Symbol::DECODE_U16))),
Symbol::NUM_U32 | Symbol::NUM_UNSIGNED32 => Some(Ok(Immediate(Symbol::DECODE_U32))),
Symbol::NUM_U64 | Symbol::NUM_UNSIGNED64 => Some(Ok(Immediate(Symbol::DECODE_U64))),
Symbol::NUM_U128 | Symbol::NUM_UNSIGNED128 => Some(Ok(Immediate(Symbol::DECODE_U128))),
Symbol::NUM_I8 | Symbol::NUM_SIGNED8 => Some(Ok(Immediate(Symbol::DECODE_I8))),
Symbol::NUM_I16 | Symbol::NUM_SIGNED16 => Some(Ok(Immediate(Symbol::DECODE_I16))),
Symbol::NUM_I32 | Symbol::NUM_SIGNED32 => Some(Ok(Immediate(Symbol::DECODE_I32))),
Symbol::NUM_I64 | Symbol::NUM_SIGNED64 => Some(Ok(Immediate(Symbol::DECODE_I64))),
Symbol::NUM_I128 | Symbol::NUM_SIGNED128 => Some(Ok(Immediate(Symbol::DECODE_I128))),
Symbol::NUM_DEC | Symbol::NUM_DECIMAL => Some(Ok(Immediate(Symbol::DECODE_DEC))),
Symbol::NUM_F32 | Symbol::NUM_BINARY32 => Some(Ok(Immediate(Symbol::DECODE_F32))),
Symbol::NUM_F64 | Symbol::NUM_BINARY64 => Some(Ok(Immediate(Symbol::DECODE_F64))),
Symbol::NUM_NAT | Symbol::NUM_NATURAL => Some(Err(DeriveError::Underivable)),
_ => None,
}
}

View file

@ -113,7 +113,7 @@ impl FlatEncodable {
FlatType::Func(..) => Err(Underivable),
},
Content::Alias(sym, _, real_var, _) => match from_builtin_symbol(sym) {
Some(lambda) => Ok(lambda),
Some(lambda) => lambda,
// TODO: I believe it is okay to unwrap opaques here because derivers are only used
// by the backend, and the backend treats opaques like structural aliases.
_ => Self::from_var(subs, real_var),
@ -133,28 +133,28 @@ impl FlatEncodable {
}
pub(crate) fn from_builtin_symbol(symbol: Symbol) -> Result<FlatEncodable, DeriveError> {
from_builtin_symbol(symbol).ok_or(DeriveError::Underivable)
from_builtin_symbol(symbol).unwrap_or(Err(DeriveError::Underivable))
}
}
const fn from_builtin_symbol(symbol: Symbol) -> Option<FlatEncodable> {
const fn from_builtin_symbol(symbol: Symbol) -> Option<Result<FlatEncodable, DeriveError>> {
use FlatEncodable::*;
match symbol {
Symbol::BOOL_BOOL => Some(Immediate(Symbol::ENCODE_BOOL)),
Symbol::NUM_U8 | Symbol::NUM_UNSIGNED8 => Some(Immediate(Symbol::ENCODE_U8)),
Symbol::NUM_U16 | Symbol::NUM_UNSIGNED16 => Some(Immediate(Symbol::ENCODE_U16)),
Symbol::NUM_U32 | Symbol::NUM_UNSIGNED32 => Some(Immediate(Symbol::ENCODE_U32)),
Symbol::NUM_U64 | Symbol::NUM_UNSIGNED64 => Some(Immediate(Symbol::ENCODE_U64)),
Symbol::NUM_U128 | Symbol::NUM_UNSIGNED128 => Some(Immediate(Symbol::ENCODE_U128)),
Symbol::NUM_I8 | Symbol::NUM_SIGNED8 => Some(Immediate(Symbol::ENCODE_I8)),
Symbol::NUM_I16 | Symbol::NUM_SIGNED16 => Some(Immediate(Symbol::ENCODE_I16)),
Symbol::NUM_I32 | Symbol::NUM_SIGNED32 => Some(Immediate(Symbol::ENCODE_I32)),
Symbol::NUM_I64 | Symbol::NUM_SIGNED64 => Some(Immediate(Symbol::ENCODE_I64)),
Symbol::NUM_I128 | Symbol::NUM_SIGNED128 => Some(Immediate(Symbol::ENCODE_I128)),
Symbol::NUM_DEC | Symbol::NUM_DECIMAL => Some(Immediate(Symbol::ENCODE_DEC)),
Symbol::NUM_F32 | Symbol::NUM_BINARY32 => Some(Immediate(Symbol::ENCODE_F32)),
Symbol::NUM_F64 | Symbol::NUM_BINARY64 => Some(Immediate(Symbol::ENCODE_F64)),
Symbol::NUM_NAT | Symbol::NUM_NATURAL => None,
Symbol::BOOL_BOOL => Some(Ok(Immediate(Symbol::ENCODE_BOOL))),
Symbol::NUM_U8 | Symbol::NUM_UNSIGNED8 => Some(Ok(Immediate(Symbol::ENCODE_U8))),
Symbol::NUM_U16 | Symbol::NUM_UNSIGNED16 => Some(Ok(Immediate(Symbol::ENCODE_U16))),
Symbol::NUM_U32 | Symbol::NUM_UNSIGNED32 => Some(Ok(Immediate(Symbol::ENCODE_U32))),
Symbol::NUM_U64 | Symbol::NUM_UNSIGNED64 => Some(Ok(Immediate(Symbol::ENCODE_U64))),
Symbol::NUM_U128 | Symbol::NUM_UNSIGNED128 => Some(Ok(Immediate(Symbol::ENCODE_U128))),
Symbol::NUM_I8 | Symbol::NUM_SIGNED8 => Some(Ok(Immediate(Symbol::ENCODE_I8))),
Symbol::NUM_I16 | Symbol::NUM_SIGNED16 => Some(Ok(Immediate(Symbol::ENCODE_I16))),
Symbol::NUM_I32 | Symbol::NUM_SIGNED32 => Some(Ok(Immediate(Symbol::ENCODE_I32))),
Symbol::NUM_I64 | Symbol::NUM_SIGNED64 => Some(Ok(Immediate(Symbol::ENCODE_I64))),
Symbol::NUM_I128 | Symbol::NUM_SIGNED128 => Some(Ok(Immediate(Symbol::ENCODE_I128))),
Symbol::NUM_DEC | Symbol::NUM_DECIMAL => Some(Ok(Immediate(Symbol::ENCODE_DEC))),
Symbol::NUM_F32 | Symbol::NUM_BINARY32 => Some(Ok(Immediate(Symbol::ENCODE_F32))),
Symbol::NUM_F64 | Symbol::NUM_BINARY64 => Some(Ok(Immediate(Symbol::ENCODE_F64))),
Symbol::NUM_NAT | Symbol::NUM_NATURAL => Some(Err(DeriveError::Underivable)),
_ => None,
}
}

View file

@ -20,7 +20,7 @@ use roc_types::types::Polarity;
use roc_unify::unify::MetaCollector;
use roc_unify::unify::{Env, Mode, Unified};
pub use roc_solve::ability::Resolved;
pub use roc_solve::ability::{ResolveError, Resolved};
pub use roc_types::subs::instantiate_rigids;
pub mod storage;
@ -161,7 +161,7 @@ pub fn resolve_ability_specialization(
abilities: &AbilitiesView,
ability_member: Symbol,
specialization_var: Variable,
) -> Option<Resolved> {
) -> Result<Resolved, ResolveError> {
let late_resolver = LateResolver { home, abilities };
roc_solve::ability::resolve_ability_specialization(
subs,

View file

@ -4,7 +4,7 @@ use roc_collections::{VecMap, VecSet};
use roc_debug_flags::dbg_do;
#[cfg(debug_assertions)]
use roc_debug_flags::ROC_PRINT_UNDERIVABLE;
use roc_derive_key::Derived;
use roc_derive_key::{DeriveError, Derived};
use roc_error_macros::internal_error;
use roc_module::symbol::{ModuleId, Symbol};
use roc_region::all::{Loc, Region};
@ -1353,12 +1353,25 @@ pub(crate) fn builtin_module_with_unlisted_ability_impl(module_id: ModuleId) ->
matches!(module_id, ModuleId::NUM | ModuleId::BOOL)
}
#[derive(Debug)]
pub enum ResolveError {
NonDerivableAbility(Symbol),
DeriveError(DeriveError),
NoTypeImplementingSpecialization,
}
impl From<DeriveError> for ResolveError {
fn from(e: DeriveError) -> Self {
Self::DeriveError(e)
}
}
pub fn resolve_ability_specialization<R: AbilityResolver>(
subs: &mut Subs,
resolver: &R,
ability_member: Symbol,
specialization_var: Variable,
) -> Option<Resolved> {
) -> Result<Resolved, ResolveError> {
use roc_unify::unify::{unify, Mode};
let (parent_ability, signature_var) = resolver
@ -1382,18 +1395,18 @@ pub fn resolve_ability_specialization<R: AbilityResolver>(
subs.rollback_to(snapshot);
let obligated = type_implementing_specialization(&must_implement_ability, parent_ability)?;
use ResolveError::*;
let obligated = type_implementing_specialization(&must_implement_ability, parent_ability)
.ok_or(NoTypeImplementingSpecialization)?;
let resolved = match obligated {
Obligated::Opaque(symbol) => {
if builtin_module_with_unlisted_ability_impl(symbol.module_id()) {
let derive_key = roc_derive_key::Derived::builtin_with_builtin_symbol(
ability_member
.try_into()
.expect("derived symbols must be builtins"),
ability_member.try_into().map_err(NonDerivableAbility)?,
symbol,
)
.expect("specialization var not derivable!");
)?;
Resolved::Derive(derive_key)
} else {
@ -1402,7 +1415,10 @@ pub fn resolve_ability_specialization<R: AbilityResolver>(
ability_member,
};
match resolver.get_implementation(impl_key)? {
match resolver
.get_implementation(impl_key)
.ok_or(NoTypeImplementingSpecialization)?
{
roc_types::types::MemberImpl::Impl(spec_symbol) => {
Resolved::Specialization(spec_symbol)
}
@ -1416,17 +1432,14 @@ pub fn resolve_ability_specialization<R: AbilityResolver>(
}
Obligated::Adhoc(variable) => {
let derive_key = roc_derive_key::Derived::builtin(
ability_member
.try_into()
.expect("derived symbols must be builtins"),
ability_member.try_into().map_err(NonDerivableAbility)?,
subs,
variable,
)
.expect("specialization var not derivable!");
)?;
Resolved::Derive(derive_key)
}
};
Some(resolved)
Ok(resolved)
}

View file

@ -1718,14 +1718,12 @@ fn solve(
member,
specialization_id,
}) => {
if let Some(Resolved::Specialization(specialization)) =
resolve_ability_specialization(
subs,
abilities_store,
member,
specialization_variable,
)
{
if let Ok(Resolved::Specialization(specialization)) = resolve_ability_specialization(
subs,
abilities_store,
member,
specialization_variable,
) {
abilities_store.insert_resolved(specialization_id, specialization);
}