Skip to content

:erlang.size/1 cannot be used in guard clauses in 1.10  #9789

@joseph-lozano

Description

@joseph-lozano

Precheck

  • Do not use the issue tracker for help or support (try Elixir Forum, Stack Overflow, IRC, etc.)
  • For proposing a new feature, please start a discussion on the Elixir Core mailing list: https://groups.google.com/group/elixir-lang-core
  • For bugs, do a quick search and make sure the bug has not yet been reported
  • Please disclose security vulnerabilities privately at elixir-security@googlegroups.com
  • Finally, be nice and have fun!

Environment

  • Elixir & Erlang/OTP versions (elixir --version): 1.10
  • Operating system: MacOS

Current behavior

:erlang.size/1 cannot be used in guard clauses. Instead, when trying to use the function, the below error gets emitted. While I understand that byte_size could be used instead. I have dependencies that use :erlang.size and so I am prevented from upgrading.

** (EXIT from #PID<0.92.0>) an exception was raised:
    ** (KeyError) key {:size, 1} not found in: %{{:ceil, 1} => {[:number], :integer}, {:<, 2} => {[:dynamic, :dynamic], :boolean}, {:floor, 1} => {[:number], :integer}, {:byte_size, 1} => {[:binary], :integer}, {:bxor, 2} => {[:integer, :integer], :integer}, {:is_tuple, 1} => {[:tuple], :boolean}, {:is_function, 1} => {[:fun], :boolean}, {:bit_size, 1} => {[:binary], :integer}, {:is_integer, 1} => {[:integer], :boolean}, {:bor, 2} => {[:integer, :integer], :integer}, {:+, 1} => {[:number], :number}, {:is_map_key, 2} => {[:dynamic, {:map, []}], :dynamic}, {:+, 2} => {[:number, :number], :number}, {:"=/=", 2} => {[:dynamic, :dynamic], :boolean}, {:hd, 1} => {[list: :dynamic], :dynamic}, {:xor, 2} => {[:boolean, :boolean], :boolean}, {:>, 2} => {[:dynamic, :dynamic], :boolean}, {:-, 2} => {[:number, :number], :number}, {:==, 2} => {[:dynamic, :dynamic], :boolean}, {:length, 1} => {[list: :dynamic], :integer}, {:is_reference, 1} => {[:reference], :boolean}, {:*, 2} => {[:number, :number], :number}, {:bnot, 1} => {[:integer], :integer}, {:node, 1} => {[union: [:pid, :reference, :port]], :atom}, {:band, 2} => {[:integer, :integer], :integer}, {:bsl, 2} => {[:integer, :integer], :integer}, {:is_float, 1} => {[:float], :boolean}, {:not, 1} => {[:boolean], :boolean}, {:is_pid, 1} => {[:pid], :boolean}, {:is_list, 1} => {[list: :dynamic], :boolean}, {:element, 2} => {[:integer, :tuple], :dynamic}, {:tl, 1} => {[list: :dynamic], :dynamic}, {:is_map, 1} => {[map: []], :boolean}, {:"=:=", 2} => {[:dynamic, :dynamic], :boolean}, {:"/=", 2} => {[:dynamic, :dynamic], :boolean}, {:-, 1} => {[:number], :number}, {:trunc, 1} => {[:number], :integer}, {:"=<", 2} => {[:dynamic, :dynamic], :boolean}, {:abs, 1} => {[:number], :number}, {:bsr, 2} => {[:integer, :integer], :integer}, {:map_size, 1} => {[map: []], :integer}, {:is_binary, 1} => {[:binary], :boolean}, {:div, 2} => {[:integer, :integer], :integer}, {:is_boolean, 1} => {[:boolean], :boolean}, {:is_function, 2} => {[:fun, :integer], :boolean}, {:is_bitstring, 1} => {[:binary], :boolean}, {:binary_part, 3} => {[:binary, :integer, ...], :binary}, {:round, 1} => {[:number], :integer}, {:rem, ...} => {[...], ...}, {...} => {...}, ...}

Expected behavior

In previous versions of elixir, (verified on 1.9.4), using :erlang.size could be used in guard clauses. I didn't see anything about this change in the changelog and believe it to be unintentional.

Code example

Run the below code as an exs script to produce the error in 1.10, or in 1.9.4 to see it working as intended.

defmodule Foo do
  def test(bar) when :erlang.size(bar) == 2 do
    :ok
  end

  def test(_) do
    :not_ok
  end
end

Foo.test("a") |> IO.inspect()
Foo.test("ab") |> IO.inspect()

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions