-
Notifications
You must be signed in to change notification settings - Fork 3.5k
Closed
Labels
Description
Erlang/OTP 24 [erts-12.2.1] [source] [64-bit] [smp:16:16] [ds:16:16:10] [async-threads:1] [jit]
Elixir 1.13.3 (compiled with Erlang/OTP 24)
Please have a look at this demo code, notably the defguard
call and how it is used:
defmodule SomeGood do
defstruct dummy: nil
end
defmodule Demo do
@good_modules [Somegood]
defguard is_good(mod_or_struct)
when (is_atom(mod_or_struct) and mod_or_struct in @good_modules) or
(is_map(mod_or_struct) and is_map_key(mod_or_struct, :__struct__) and
:erlang.map_get(:__struct__, mod_or_struct) in @good_modules)
defguard is_bad(mod_or_struct) when not is_good(mod_or_struct)
end
defmodule Worker do
import Demo
def work(%contract{}) when is_good(contract) do
:alright
end
def work(_) do
:nope
end
def a_case(data) do
case data do
%contract{} when is_good(contract) -> :good_contract
data when is_good(data) -> :good_data
_other -> :bad_data
end
end
end
defmodule Dependent do
require Demo
def get_fun do
fn
%contract{} when Demo.is_bad(contract) -> :nope
_ -> :alright
end
end
end
It produces the following warnings:
warning: expected Kernel.is_map_key/2 to have signature:
:__struct__, atom() -> dynamic()
but it has signature:
dynamic(), %{optional(dynamic()) => dynamic()} -> dynamic()
in expression:
# lib/demo.ex:41
is_map_key(contract, :__struct__)
Conflict found at
lib/demo.ex:41: Dependent.get_fun/0
warning: incompatible types:
atom() !~ map()
in expression:
# lib/demo.ex:19
is_map(contract)
where "contract" was given the type atom() in:
# lib/demo.ex:19
%contract{}
where "contract" was given the type map() in:
# lib/demo.ex:19
is_map(contract)
Conflict found at
lib/demo.ex:19: Worker.work/1
warning: incompatible types:
atom() !~ map()
in expression:
# lib/demo.ex:29
is_map(contract)
where "contract" was given the type atom() in:
# lib/demo.ex:29
%contract{}
where "contract" was given the type map() in:
# lib/demo.ex:29
is_map(contract)
Conflict found at
lib/demo.ex:29: Worker.a_case/1
But to me it looks like the guards are fine.
The main guard is defined as is instead of using is_struct
because I was trying to find why there was such warnings.
The warning about expected Kernel.is_map_key/2 to have signature
is caused by the usage of the guard defined as defguard is_bad(mod_or_struct) when not is_good(mod_or_struct)
only.