mirror of
https://github.com/roc-lang/roc.git
synced 2025-08-04 12:18:19 +00:00
Compile derived structural equality
This commit is contained in:
parent
54e977be2d
commit
3674f6861e
7 changed files with 41 additions and 1 deletions
|
@ -3,6 +3,7 @@ interface Eq
|
|||
Eq,
|
||||
isEq,
|
||||
isNotEq,
|
||||
structuralEq,
|
||||
]
|
||||
imports [
|
||||
Bool,
|
||||
|
@ -37,3 +38,7 @@ Eq has
|
|||
## `a != b` is shorthand for `Eq.isNotEq a b`.
|
||||
isNotEq : a, a -> Bool | a has Eq
|
||||
isNotEq = \a, b -> Bool.not (isEq a b)
|
||||
|
||||
# INTERNAL COMPILER USE ONLY: used to lower calls to `isEq` to structural
|
||||
# equality via the `Eq` low-level for derived types.
|
||||
structuralEq : a, a -> Bool
|
||||
|
|
|
@ -70,6 +70,7 @@ macro_rules! map_symbol_to_lowlevel_and_arity {
|
|||
// Below, we explicitly handle some exceptions to the pattern where a lowlevel maps
|
||||
// directly to a symbol. If you are unsure if your lowlevel is an exception, assume
|
||||
// that it isn't and just see if that works.
|
||||
#[allow(unreachable_patterns)] // TODO: remove after we replace `BOOL_EQ` with `EQ_EQ` wholly
|
||||
match lowlevel {
|
||||
$(
|
||||
LowLevel::$lowlevel => Symbol::$symbol,
|
||||
|
@ -192,6 +193,7 @@ map_symbol_to_lowlevel_and_arity! {
|
|||
NumToStr; NUM_TO_STR; 1,
|
||||
|
||||
Eq; BOOL_EQ; 2,
|
||||
Eq; EQ_STRUCTURAL_EQ; 2,
|
||||
NotEq; BOOL_NEQ; 2,
|
||||
And; BOOL_AND; 2,
|
||||
Or; BOOL_OR; 2,
|
||||
|
|
|
@ -374,6 +374,7 @@ pub fn canonicalize_module_defs<'a>(
|
|||
if !output.references.has_type_or_value_lookup(symbol)
|
||||
&& !exposed_symbols.contains(&symbol)
|
||||
&& !scope.abilities_store.is_specialization_name(symbol)
|
||||
&& !symbol.is_exposed_for_builtin_derivers()
|
||||
{
|
||||
env.problem(Problem::UnusedDef(symbol, region));
|
||||
}
|
||||
|
|
|
@ -4469,7 +4469,11 @@ fn run_solve_solve(
|
|||
// ability.
|
||||
let exposed_vars_by_symbol: Vec<_> = solved_env
|
||||
.vars_by_symbol()
|
||||
.filter(|(k, _)| exposed_symbols.contains(k) || is_specialization_symbol(*k))
|
||||
.filter(|(k, _)| {
|
||||
exposed_symbols.contains(k)
|
||||
|| is_specialization_symbol(*k)
|
||||
|| k.is_exposed_for_builtin_derivers()
|
||||
})
|
||||
.collect();
|
||||
|
||||
(
|
||||
|
|
|
@ -184,6 +184,7 @@ macro_rules! map_symbol_to_lowlevel {
|
|||
// Below, we explicitly handle some exceptions to the pattern where a lowlevel maps
|
||||
// directly to a symbol. If you are unsure if your lowlevel is an exception, assume
|
||||
// that it isn't and just see if that works.
|
||||
#[allow(unreachable_patterns)] // TODO: remove after we replace `BOOL_EQ` with `EQ_EQ` wholly
|
||||
match lowlevel {
|
||||
$(
|
||||
LowLevel::$lowlevel => Symbol::$symbol,
|
||||
|
@ -310,6 +311,7 @@ map_symbol_to_lowlevel! {
|
|||
NumShiftRightZfBy <= NUM_SHIFT_RIGHT_ZERO_FILL,
|
||||
NumToStr <= NUM_TO_STR,
|
||||
Eq <= BOOL_EQ,
|
||||
Eq <= EQ_STRUCTURAL_EQ,
|
||||
NotEq <= BOOL_NEQ,
|
||||
And <= BOOL_AND,
|
||||
Or <= BOOL_OR,
|
||||
|
|
|
@ -99,6 +99,17 @@ impl Symbol {
|
|||
DERIVABLE_ABILITIES.iter().find(|(name, _)| *name == self)
|
||||
}
|
||||
|
||||
/// A symbol that should never be exposed to userspace, but needs to be exposed
|
||||
/// to compiled modules for deriving abilities for structural types.
|
||||
pub fn is_exposed_for_builtin_derivers(&self) -> bool {
|
||||
matches!(
|
||||
self,
|
||||
// The `structuralEq` call used deriving structural equality, which will wrap the `Eq`
|
||||
// low-level implementation.
|
||||
&Self::EQ_STRUCTURAL_EQ
|
||||
) && false
|
||||
}
|
||||
|
||||
pub fn module_string<'a>(&self, interns: &'a Interns) -> &'a ModuleName {
|
||||
interns
|
||||
.module_ids
|
||||
|
|
|
@ -1639,4 +1639,19 @@ mod eq {
|
|||
RocStr
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn derive_structural_eq() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
app "test" provides [main] to "./platform"
|
||||
|
||||
main = Eq.isEq 10u8 10u8
|
||||
"#
|
||||
),
|
||||
true,
|
||||
bool
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue