Wire up dialyzer; address all warnings - #37
Merged
Merged
Conversation
Adds :dialyxir as a dev-only dep with a lib-only PLT (priv/plts/,
gitignored) and a curated .dialyzer_ignore.exs. Not hooked into
precommit — runnable on demand via `mix dialyzer`.
Real type fixes:
- lib/emily/native.ex, lib/emily.ex: narrow `@type dtype` to
Nx.Type.t() (was {atom(), non_neg_integer()}) so callsites stop
widening through wrap/3.
- lib/emily/telemetry.ex:118: capture the unmatched :ets.new/2
return explicitly.
- lib/emily/backend.ex: @dialyzer {:nowarn_function, ...} for the
four genuinely-unimplementable callbacks (from_pointer, to_pointer,
count_leading_zeros, population_count) and for select/4, which
passes Nx's internal {:pred, 1} dtype through Native.astype.
Suppressed false positives (see .dialyzer_ignore.exs for rationale):
- Emily.Backend callback_type_mismatch / callback_arg_type_mismatch
and the related wrap/3 invalid_contract — driven by the map-update
pattern `%T{out | data: ...}` narrowing the inferred return to an
open map, losing :shape / :names / :vectorized_axes field tracking.
The code is correct; dialyzer's inference can't follow the field
types through a single shared wrap helper across ~115 callbacks.
- Emily.Fast invalid_contract — Nx.Defn.Expr.optional/3 has no
upstream @SPEC, so dialyzer infers a sloppy `tuple() | %{...}`
union for our hook functions' return.
- Emily.Quantization / Emily.QuantizedWeight invalid_contract — same
class: explicit %T{} construction from NIF-returned refs gives
dialyzer a wider inferred type than Nx.Tensor.t().
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
:dialyxiras a dev-only dep with a lib-only PLT (priv/plts/, gitignored) — opt-in viamix dialyzer, not hooked intoprecommit.@type dtypeinEmily.Native/EmilytoNx.Type.t(), fixes one:ets.new/2unmatched return inEmily.Telemetry, and suppresses 5 genuinely-raises / one-off NIF-boundary quirks with per-function@dialyzer {:nowarn_function, ...}directives..dialyzer_ignore.exsfor ~123 false-positive callback / contract warnings that stem from dialyzer's inability to trackNx.Tensorstruct fields across the sharedwrap/3map update and throughNx.Defn.Expr.optional/3(unspec'd upstream). Each ignore cluster is commented with its root cause so future readers know why it's there.mix dialyzernow reportsdone (passed successfully)with 123 skipped, 0 unskipped.Test plan
mix dialyzerexits clean (0 unskipped warnings).mix precommitpasses (compile, deps.unlock, format, credo --strict, test).mix test --include conformance --include qwen3_full --include qwen3_quant_full --include vit_full --include whisper_full --include distilbert_full --include training_full --include fast_kernels_full— 449 tests, 76 properties, 1 doctest, 0 failures (151s on my machine).