mirror of
https://github.com/roc-lang/roc.git
synced 2025-07-24 06:55:15 +00:00
Make sure to report error rather than descending as appropriate
This commit is contained in:
parent
3d2642b282
commit
3e83e42195
5 changed files with 72 additions and 60 deletions
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue