mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-24 20:42:29 +00:00
Get first inspect for non-Inspect-implementing opaques specialized
This commit is contained in:
parent
c87e3e7413
commit
5c805ce80f
6 changed files with 75 additions and 44 deletions
|
@ -15,6 +15,7 @@ interface Inspect
|
||||||
record,
|
record,
|
||||||
bool,
|
bool,
|
||||||
str,
|
str,
|
||||||
|
function,
|
||||||
opaque,
|
opaque,
|
||||||
u8,
|
u8,
|
||||||
i8,
|
i8,
|
||||||
|
@ -33,13 +34,10 @@ interface Inspect
|
||||||
custom,
|
custom,
|
||||||
apply,
|
apply,
|
||||||
toInspector,
|
toInspector,
|
||||||
# TODO don't expose these - there's some way to do this!
|
|
||||||
inspectFn,
|
|
||||||
inspectOpaque,
|
|
||||||
]
|
]
|
||||||
imports [
|
imports [
|
||||||
Bool.{ Bool },
|
Bool.{ Bool },
|
||||||
Num.{ U8, U16, U32, U64, U128, I8, I16, I32, I64, I128, F32, F64, Dec },
|
Num.{ U8, U16, U32, U64, U128, I8, I16, I32, I64, I128, F32, F64, Dec, Nat },
|
||||||
List,
|
List,
|
||||||
Str,
|
Str,
|
||||||
]
|
]
|
||||||
|
@ -61,10 +59,10 @@ InspectFormatter implements
|
||||||
dict : dict, KeyValWalker state dict key value, (key -> Inspector f), (value -> Inspector f) -> Inspector f where f implements InspectFormatter
|
dict : dict, KeyValWalker state dict key value, (key -> Inspector f), (value -> Inspector f) -> Inspector f where f implements InspectFormatter
|
||||||
|
|
||||||
# In text, this would render as `<opaque>`
|
# In text, this would render as `<opaque>`
|
||||||
opaque : Inspector f where f implements InspectFormatter
|
opaque : * -> Inspector f where f implements InspectFormatter
|
||||||
|
|
||||||
# In text, this would render as `<function>`
|
# In text, this would render as `<function>`
|
||||||
function : Inspector f where f implements InspectFormatter
|
function : * -> Inspector f where f implements InspectFormatter
|
||||||
|
|
||||||
u8 : U8 -> Inspector f where f implements InspectFormatter
|
u8 : U8 -> Inspector f where f implements InspectFormatter
|
||||||
i8 : I8 -> Inspector f where f implements InspectFormatter
|
i8 : I8 -> Inspector f where f implements InspectFormatter
|
||||||
|
@ -96,11 +94,3 @@ inspect : val -> f where val implements Inspect, f implements InspectFormatter
|
||||||
inspect = \val ->
|
inspect = \val ->
|
||||||
(@Inspector valFn) = toInspector val
|
(@Inspector valFn) = toInspector val
|
||||||
valFn (init {})
|
valFn (init {})
|
||||||
|
|
||||||
## Should not be exposed, only used in auto-deriving
|
|
||||||
inspectFn : * -> Inspector f where f implements InspectFormatter
|
|
||||||
inspectFn = \_ -> function
|
|
||||||
|
|
||||||
## Should not be exposed, only used in auto-deriving
|
|
||||||
inspectOpaque : * -> Inspector f where f implements InspectFormatter
|
|
||||||
inspectOpaque = \_ -> opaque
|
|
||||||
|
|
|
@ -718,6 +718,7 @@ fn canonicalize_opaque<'a>(
|
||||||
|
|
||||||
let ability_region = ability.region;
|
let ability_region = ability.region;
|
||||||
|
|
||||||
|
// Op := {} has [Eq]
|
||||||
let (ability, members) = match ability.value {
|
let (ability, members) = match ability.value {
|
||||||
ast::TypeAnnotation::Apply(module_name, ident, []) => {
|
ast::TypeAnnotation::Apply(module_name, ident, []) => {
|
||||||
match make_apply_symbol(env, region, scope, module_name, ident) {
|
match make_apply_symbol(env, region, scope, module_name, ident) {
|
||||||
|
|
|
@ -2,7 +2,10 @@ use roc_module::{
|
||||||
ident::{Lowercase, TagName},
|
ident::{Lowercase, TagName},
|
||||||
symbol::Symbol,
|
symbol::Symbol,
|
||||||
};
|
};
|
||||||
use roc_types::subs::{Content, FlatType, GetSubsSlice, Subs, Variable};
|
use roc_types::{
|
||||||
|
subs::{Content, FlatType, GetSubsSlice, Subs, Variable},
|
||||||
|
types::AliasKind,
|
||||||
|
};
|
||||||
|
|
||||||
use crate::util::{
|
use crate::util::{
|
||||||
check_derivable_ext_var, debug_name_fn, debug_name_record, debug_name_tag, debug_name_tuple,
|
check_derivable_ext_var, debug_name_fn, debug_name_record, debug_name_tag, debug_name_tuple,
|
||||||
|
@ -125,18 +128,41 @@ impl FlatInspectable {
|
||||||
}
|
}
|
||||||
FlatType::EmptyRecord => Key(FlatInspectableKey::Record(Vec::new())),
|
FlatType::EmptyRecord => Key(FlatInspectableKey::Record(Vec::new())),
|
||||||
FlatType::EmptyTagUnion => Key(FlatInspectableKey::TagUnion(Vec::new())),
|
FlatType::EmptyTagUnion => Key(FlatInspectableKey::TagUnion(Vec::new())),
|
||||||
FlatType::Func(slice, ..) => {
|
FlatType::Func(..) => {
|
||||||
let arity = subs.get_subs_slice(slice).len();
|
Immediate(Symbol::INSPECT_FUNCTION)
|
||||||
|
|
||||||
Key(FlatInspectableKey::Function(arity as u32))
|
|
||||||
}
|
}
|
||||||
FlatType::EmptyTuple => unreachable!("Somehow Inspect derivation got an expression that's an empty tuple, which shouldn't be possible!"),
|
FlatType::EmptyTuple => unreachable!("Somehow Inspect derivation got an expression that's an empty tuple, which shouldn't be possible!"),
|
||||||
},
|
},
|
||||||
Content::Alias(sym, _, real_var, _) => match Self::from_builtin_alias(sym) {
|
Content::Alias(sym, _, real_var, kind) => match Self::from_builtin_alias(sym) {
|
||||||
Some(lambda) => 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),
|
match kind {
|
||||||
|
AliasKind::Structural => {
|
||||||
|
Self::from_var(subs, real_var)
|
||||||
|
}
|
||||||
|
AliasKind::Opaque => {
|
||||||
|
// There are two cases in which `Inspect` can be derived for an opaque
|
||||||
|
// type.
|
||||||
|
// 1. An opaque type claims to implement `Inspect` and asks us to
|
||||||
|
// auto-derive it. E.g.
|
||||||
|
//
|
||||||
|
// ```text
|
||||||
|
// Op := {} implements [Inspect]
|
||||||
|
// ```
|
||||||
|
//
|
||||||
|
// In this case, we generate a synthetic implementation during
|
||||||
|
// canonicalization that defers to `inspect`ing the inner type. As
|
||||||
|
// such, this case is never reached in this branch.
|
||||||
|
//
|
||||||
|
// 2. An opaque type does not explicitly claim to implement
|
||||||
|
// `Inspect`. In this case, we print a default opaque string for
|
||||||
|
// the opaque type.
|
||||||
|
Immediate(Symbol::INSPECT_OPAQUE)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
Content::RangedNumber(range) => {
|
Content::RangedNumber(range) => {
|
||||||
Self::from_var(subs, range.default_compilation_variable())
|
Self::from_var(subs, range.default_compilation_variable())
|
||||||
|
|
|
@ -1610,25 +1610,24 @@ define_builtins! {
|
||||||
13 INSPECT_BOOL: "bool"
|
13 INSPECT_BOOL: "bool"
|
||||||
14 INSPECT_STR: "str"
|
14 INSPECT_STR: "str"
|
||||||
15 INSPECT_OPAQUE: "opaque"
|
15 INSPECT_OPAQUE: "opaque"
|
||||||
16 INSPECT_U8: "u8"
|
16 INSPECT_FUNCTION: "function"
|
||||||
17 INSPECT_I8: "i8"
|
17 INSPECT_U8: "u8"
|
||||||
18 INSPECT_U16: "u16"
|
18 INSPECT_I8: "i8"
|
||||||
19 INSPECT_I16: "i16"
|
19 INSPECT_U16: "u16"
|
||||||
20 INSPECT_U32: "u32"
|
20 INSPECT_I16: "i16"
|
||||||
21 INSPECT_I32: "i32"
|
21 INSPECT_U32: "u32"
|
||||||
22 INSPECT_U64: "u64"
|
22 INSPECT_I32: "i32"
|
||||||
23 INSPECT_I64: "i64"
|
23 INSPECT_U64: "u64"
|
||||||
24 INSPECT_U128: "u128"
|
24 INSPECT_I64: "i64"
|
||||||
25 INSPECT_I128: "i128"
|
25 INSPECT_U128: "u128"
|
||||||
26 INSPECT_F32: "f32"
|
26 INSPECT_I128: "i128"
|
||||||
27 INSPECT_F64: "f64"
|
27 INSPECT_F32: "f32"
|
||||||
28 INSPECT_DEC: "dec"
|
28 INSPECT_F64: "f64"
|
||||||
29 INSPECT_CUSTOM: "custom"
|
29 INSPECT_DEC: "dec"
|
||||||
30 INSPECT_APPLY: "apply"
|
30 INSPECT_CUSTOM: "custom"
|
||||||
31 INSPECT_TO_INSPECTOR: "toInspector"
|
31 INSPECT_APPLY: "apply"
|
||||||
32 INSPECT_NAT: "nat"
|
32 INSPECT_TO_INSPECTOR: "toInspector"
|
||||||
33 INSPECT_INSPECT_FN: "inspectFn"
|
33 INSPECT_NAT: "nat"
|
||||||
34 INSPECT_INSPECT_OPAQUE: "inspectOpaque"
|
|
||||||
}
|
}
|
||||||
15 JSON: "TotallyNotJson" => {
|
15 JSON: "TotallyNotJson" => {
|
||||||
0 JSON_JSON: "TotallyNotJson"
|
0 JSON_JSON: "TotallyNotJson"
|
||||||
|
|
|
@ -634,8 +634,17 @@ fn make_specialization_decision<P: Phase>(
|
||||||
};
|
};
|
||||||
match abilities_store.get_implementation(impl_key) {
|
match abilities_store.get_implementation(impl_key) {
|
||||||
None => {
|
None => {
|
||||||
// Doesn't specialize; an error will already be reported for this.
|
match ability_member {
|
||||||
SpecializeDecision::Drop
|
// Inspect is special - if there is no implementation for the
|
||||||
|
// opaque type, we always emit a default implementation.
|
||||||
|
Symbol::INSPECT_TO_INSPECTOR => SpecializeDecision::Specialize(
|
||||||
|
Immediate(Symbol::INSPECT_OPAQUE),
|
||||||
|
),
|
||||||
|
_ => {
|
||||||
|
// Doesn't specialize; an error will already be reported for this.
|
||||||
|
SpecializeDecision::Drop
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Some(MemberImpl::Error) => {
|
Some(MemberImpl::Error) => {
|
||||||
// TODO: probably not right, we may want to choose a derive decision!
|
// TODO: probably not right, we may want to choose a derive decision!
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
app "test" provides [main] to "./platform"
|
||||||
|
|
||||||
|
Op := {}
|
||||||
|
|
||||||
|
main = Inspect.toInspector (@Op {})
|
||||||
|
# ^^^^^^^^^^^^^^^^^^^ Inspect#Inspect.toInspector(32): Op -[[] + f:Inspect.opaque(15):1]-> Inspector f where f implements InspectFormatter
|
Loading…
Add table
Add a link
Reference in a new issue