Help with Dialyzer Output

Could be that do_validate_locale is returning {:ok, String.t()} or {:error, reason} where reason could be generated from locale_error
or other function not satisfying {:error, {module(), String.t()}}, ? which I think the type module() is an alias for atom()

Really appreciate all the suggestions. Really. locale_error/1 I’m pretty sure isn’t the issue. It’s just:

  @spec locale_error(locale_name() | LanguageTag.t()) :: {Cldr.UnknownLocaleError, String.t()}
  def locale_error(%LanguageTag{requested_locale_name: requested_locale_name}) do
    locale_error(requested_locale_name)
  end

  def locale_error(locale_name) do
    {Cldr.UnknownLocaleError, "The locale #{inspect(locale_name)} is not known."}
  end

And I think thats the end of the rabbit hole. I’m out of ideas. But I’ll try to create a minimal failing case and see what that tells me.

2 Likes

Kind of fun to re-read this old thread - especially since somewhere in the last year I solved the issue (and I don’t really know when). I thought my dialyzer-fu was quite reasonable now but then this issue cropped up today (after a couple of weeks work so I can’t trace when it appeared).

Help very much appreciated!

Dialyzer Error:

lib/cldr/backend/cldr.ex:52:call
The function call will not succeed.

Cldr.Locale.put_gettext_locale_name(
  %Cldr.LanguageTag{
    :canonical_locale_name => <<101, 110, 45, 76, 97, 116, 110, 45, 85, 83>>,
    :cldr_locale_name => <<101, 110>>,
    :extensions => %{},
    :gettext_locale_name => nil,
    :language => <<101, 110>>,
    :language_subtags => [],
    :language_variant => nil,
    :locale => %{},
    :private_use => [],
    :rbnf_locale_name => <<101, 110>>,
    :requested_locale_name => <<101, 110>>,
    :script => <<76, 97, 116, 110>>,
    :territory => :US,
    :transform => %{}
  },
  MyApp.Cldr
)

will never return since it differs in arguments with
positions 1st from the success typing arguments:

(
  %Cldr.LanguageTag{
    :canonical_locale_name => binary(),
    :cldr_locale_name => nil | binary(),
    :extensions => map(),
    :gettext_locale_name => nil | binary(),
    :language => binary(),
    :language_subtags => [binary()],
    :language_variant => nil | binary(),
    :locale => map(),
    :private_use => [binary()],
    :rbnf_locale_name => nil | binary(),
    :requested_locale_name => binary(),
    :script => nil | binary(),
    :territory => nil,
    :transform => map()
  },
  atom()
)

Observations

The only difference between the function call and the success typing is:

# Call
    :script => <<76, 97, 116, 110>>,
    :territory => :US,
    :transform => %{}

# Success type
    :script => nil | binary(),
    :territory => nil,
    :transform => map()

In which the types for :territory would seem to mismatch. However if I look into my types:

  # This is the type for Cldr.LanguageTag
  @type territory :: atom()
  @type t :: %__MODULE__{
          language: String.t(),
          language_subtags: [String.t()] | [],
          script: String.t() | nil,
          territory: Cldr.territory(),
          language_variant: String.t() | nil,
          locale: Cldr.LanguageTag.U.t(),
          transform: map(),
          extensions: map(),
          private_use: [String.t()] | [],
          requested_locale_name: String.t(),
          canonical_locale_name: String.t(),
          cldr_locale_name: String.t() | nil,
          rbnf_locale_name: String.t() | nil,
          gettext_locale_name: String.t() | nil
        }

So I’m perplexed why the success type for :territory is nil not atom(). The called site is:

  @spec put_gettext_locale_name(Cldr.LanguageTag.t(), Cldr.backend()) :: Cldr.LanguageTag.t()
  def put_gettext_locale_name(%LanguageTag{} = language_tag, backend) do
    gettext_locale_name = gettext_locale_name(language_tag, backend)
    %{language_tag | gettext_locale_name: gettext_locale_name}
  end

Which doesn’t obviously disturb the success type I would have thought?

Any and all suggestions welcome!

you have functions in the called site file where territory is fetched from the struct and passed to other functions where territory() type from this file is referenced, which is a String.t() | nil. The only atom() for which this makes sense is nil

1 Like

BTW this can be simply private_use: [String.t()], and the same for language_subtags

Thanks very much, greatly appreciated! I’ll go diving some more. I had already adjusted the :private_use and :language_subtags types.

Yea I am running this on CI which is using the MIX_ENV=test, is it preferable to be running this on a different environment?

Um, running what? And with what error? Tricky to help without this information. Typically shouldn’t matter what environment you are running dialyzer in.