Skip to content

Type error on Elixir 1.19.0-dev with OTP 28 #14359

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
kipcole9 opened this issue Mar 24, 2025 · 1 comment
Closed

Type error on Elixir 1.19.0-dev with OTP 28 #14359

kipcole9 opened this issue Mar 24, 2025 · 1 comment

Comments

@kipcole9
Copy link
Contributor

kipcole9 commented Mar 24, 2025

Elixir and Erlang/OTP versions

  • OTP 28.0-rc2
  • Elixir 1.19.0-dev

Operating system

MacOS

Current behavior

The following module produces a type warning that (as best I can tell) is not correct. Note that replacing the interpolated value #{known_locale_count} with #{inspect known_locale_count} result in no type warning. Somehow the interpolation is affecting the assumption of the type of known_locale_count - the relevant part of the warning seems to be:

# from: lib/type_check.ex:17
to_string(known_locale_count)

Example module

defmodule TypeCheck do
  @warn_if_greater_than 100

  @locales [
    :ar, :ca, :"ca-ES-valencia", :de, :doi, :en, :"en-001", :"en-AU", :"en-GB",
    :es, :fr, :"fr-CA", :it, :ja, :nb, :no, :pl, :th, :und
  ]

  def install_locales(config) do
    known_locale_count =
      @locales
      |> Enum.count()

    locale_string = if known_locale_count > 1, do: "locales named ", else: "locale named "

    IO.puts(
      "Generating #{inspect(config.backend)} for #{known_locale_count} " <>
        locale_string <>
        "#{inspect(@locales, limit: 5)} with " <>
        "a default locale named #{:en}"
    )

    if known_locale_count > @warn_if_greater_than do
      IO.puts("Please be patient, generating functions for many locales " <> "can take some time")
    end
  end
end

Type message

iex -S mix
Erlang/OTP 28 [RELEASE CANDIDATE 2] [erts-16.0] [source] [64-bit] [smp:10:10] [ds:10:10:10] [async-threads:1] [jit]

    warning: comparison with structs found:

        known_locale_count > 100

    given types:

        dynamic(
          %Date{} or %DateTime{} or %NaiveDateTime{} or %Time{} or %URI{} or %Version{} or
            %Version.Requirement{} or atom() or binary() or float() or integer() or list(term())
        ) > integer()

    where "known_locale_count" was given the type:

        # type: dynamic(
          %Date{} or %DateTime{} or %NaiveDateTime{} or %Time{} or %URI{} or %Version{} or
            %Version.Requirement{} or atom() or binary() or float() or integer() or list(term())
        )
        # from: lib/type_check.ex:17
        to_string(known_locale_count)

    Comparison operators (>, <, >=, <=, min, and max) perform structural and not semantic comparison. Comparing with a struct won't give meaningful results. Structs that can be compared typically define a compare/2 function within their modules that can be used for semantic comparison.

    typing violation found at:
    │
 23 │     if known_locale_count > @warn_if_greater_than do
    │                           ~
    │
    └─ lib/type_check.ex:23:27: TypeCheck.install_locales/1

Expected behavior

No type error is expected since:

    known_locale_count =
      @locales
      |> Enum.count()

is determined by the result of Enum.count/1.

@sabiwara
Copy link
Contributor

Sharing another smaller example for the record

defmodule Foo do
  def foo(x, y) do
    msg = "#{x} > #{y}"
    if x > y do
      IO.puts(msg)
    end
  end
end

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

2 participants