Skip to content

Fix specs that exclude inputs their functions intentionally handle#15571

Merged
josevalim merged 2 commits into
elixir-lang:mainfrom
lukaszsamson:ls-spec-intent-fixes
Jul 10, 2026
Merged

Fix specs that exclude inputs their functions intentionally handle#15571
josevalim merged 2 commits into
elixir-lang:mainfrom
lukaszsamson:ls-spec-intent-fixes

Conversation

@lukaszsamson

Copy link
Copy Markdown
Contributor

Found by re-running the type checker over stdlib function bodies with spec-derived argument domains (the spec-domain body check from #15559):

  • Config.Provider.validate_config_path!/1 was typed by the very type it validates, making its own is_binary check trivially true per the spec. A validator that raises a descriptive error on malformed input must accept term().
  • List.to_float/1 and List.to_integer/1,2 declared charlist(), which admits [], but the underlying BIFs always raise on it. Now nonempty_charlist().
  • Logger.Formatter.prune/1 exists to sanitize invalid chardata (its catch-all clause substitutes the replacement char), yet its spec restricted input to valid IO.chardata(), making that clause dead per the spec. Now accepts term().

Assisted-By: Claude Fable 5

🤖 Generated with Claude Code

Found by re-running the type checker over function bodies with
spec-derived argument domains (elixir-lang#15559):

  * Config.Provider.validate_config_path!/1 was typed by the very type
    it validates, making its own check trivially true. A validator
    that raises a descriptive error on malformed input must accept
    term().

  * List.to_float/1 and List.to_integer/1,2 declared charlist(), which
    admits the empty list, but the underlying BIFs always raise on it.
    Use nonempty_charlist().

  * Logger.Formatter.prune/1 exists to sanitize INVALID chardata (its
    catch-all replaces unprintable data), yet its spec restricted the
    input to valid IO.chardata(). Accept term().

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

Typically called after formatting when the data cannot be printed.
"""
@spec prune(IO.chardata()) :: IO.chardata()

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not convinced about this change

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is wrong as well. It is completely fine for us to say that the input in the spec is a subset of what the function actually handles. The opposite is wrong.

Validates a `t:config_path/0`.
"""
@doc since: "1.9.0"
@spec validate_config_path!(config_path) :: :ok

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not convinced about this change

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, it doesn't look correct to me either.

Comment thread lib/elixir/lib/config/provider.ex Outdated
Comment thread lib/logger/lib/logger/formatter.ex Outdated
Co-authored-by: José Valim <jose.valim@gmail.com>
@josevalim josevalim merged commit 5b21c6a into elixir-lang:main Jul 10, 2026
@josevalim

Copy link
Copy Markdown
Member

💚 💙 💜 💛 ❤️

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

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants