diff --git a/lib/ash/expr/expr.ex b/lib/ash/expr/expr.ex index ec78ddd1..a5a2615e 100644 --- a/lib/ash/expr/expr.ex +++ b/lib/ash/expr/expr.ex @@ -835,14 +835,9 @@ defmodule Ash.Expr do {type, constraints} end - def determine_types(mod, values, returns) do + def determine_types(mod, values, known_result) do Code.ensure_compiled(mod) - basis = - if returns && returns != [:any, :same, {:array, :any}, {:array, :same}] do - returns - end - name = cond do function_exported?(mod, :operator, 0) -> @@ -893,6 +888,27 @@ defmodule Ash.Expr do length(typeset) == length(values) end) |> 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 = if typeset == :same do Enum.map(values, &{:same, &1}) diff --git a/lib/ash/query/operator/basic.ex b/lib/ash/query/operator/basic.ex index acbb6436..640f82e2 100644 --- a/lib/ash/query/operator/basic.ex +++ b/lib/ash/query/operator/basic.ex @@ -20,7 +20,8 @@ defmodule Ash.Query.Operator.Basic do div: [ symbol: :/, no_nils: true, - evaluate_types: :numbers + evaluate_types: :numbers, + returns: [:float] ], concat: [ symbol: :<>, diff --git a/lib/ash/query/operator/eq.ex b/lib/ash/query/operator/eq.ex index 31bdb0a8..c8e4e134 100644 --- a/lib/ash/query/operator/eq.ex +++ b/lib/ash/query/operator/eq.ex @@ -11,8 +11,7 @@ defmodule Ash.Query.Operator.Eq do operator: :==, name: :eq, predicate?: true, - types: [:any, :same], - returns: [:boolean] + types: [:any, :same] def new(left, right) do {:ok, struct(__MODULE__, left: left, right: right)} diff --git a/lib/ash/query/operator/operator.ex b/lib/ash/query/operator/operator.ex index bfd06282..77d7181b 100644 --- a/lib/ash/query/operator/operator.ex +++ b/lib/ash/query/operator/operator.ex @@ -399,7 +399,15 @@ defmodule Ash.Query.Operator do def predicate?, do: unquote(opts[:predicate?] || false) @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 def types do