fix: don't use :same return type for most operators

fix: don't use returns as basis type unless explicitly allowed
This commit is contained in:
Zach Daniel 2024-07-14 11:22:20 -04:00
parent a665a17c59
commit c5b118a37c
4 changed files with 34 additions and 10 deletions

View file

@ -835,14 +835,9 @@ defmodule Ash.Expr do
{type, constraints} {type, constraints}
end end
def determine_types(mod, values, returns) do def determine_types(mod, values, known_result) do
Code.ensure_compiled(mod) Code.ensure_compiled(mod)
basis =
if returns && returns != [:any, :same, {:array, :any}, {:array, :same}] do
returns
end
name = name =
cond do cond do
function_exported?(mod, :operator, 0) -> function_exported?(mod, :operator, 0) ->
@ -893,6 +888,27 @@ defmodule Ash.Expr do
length(typeset) == length(values) length(typeset) == length(values)
end) end)
|> Enum.find_value({Enum.map(values, fn _ -> nil end), nil}, fn {typeset, returns} -> |> Enum.find_value({Enum.map(values, fn _ -> nil end), nil}, fn {typeset, returns} ->
basis =
cond do
!returns ->
nil
returns == :same ->
known_result
returns == {:array, :same} ->
case known_result do
{:array, type} ->
type
_ ->
nil
end
true ->
nil
end
types_and_values = types_and_values =
if typeset == :same do if typeset == :same do
Enum.map(values, &{:same, &1}) Enum.map(values, &{:same, &1})

View file

@ -20,7 +20,8 @@ defmodule Ash.Query.Operator.Basic do
div: [ div: [
symbol: :/, symbol: :/,
no_nils: true, no_nils: true,
evaluate_types: :numbers evaluate_types: :numbers,
returns: [:float]
], ],
concat: [ concat: [
symbol: :<>, symbol: :<>,

View file

@ -11,8 +11,7 @@ defmodule Ash.Query.Operator.Eq do
operator: :==, operator: :==,
name: :eq, name: :eq,
predicate?: true, predicate?: true,
types: [:any, :same], types: [:any, :same]
returns: [:boolean]
def new(left, right) do def new(left, right) do
{:ok, struct(__MODULE__, left: left, right: right)} {:ok, struct(__MODULE__, left: left, right: right)}

View file

@ -399,7 +399,15 @@ defmodule Ash.Query.Operator do
def predicate?, do: unquote(opts[:predicate?] || false) def predicate?, do: unquote(opts[:predicate?] || false)
@impl Ash.Query.Operator @impl Ash.Query.Operator
def returns, do: unquote(opts[:returns] || [:same]) if unquote(opts[:predicate?]) do
def returns do
Enum.map(List.wrap(unquote(opts[:types])), fn _ -> :boolean end)
end
else
def returns do
unquote(opts[:returns] || :unknown)
end
end
@impl Ash.Query.Operator @impl Ash.Query.Operator
def types do def types do