elixir-mongo / mongodb

MongoDB driver for Elixir
Apache License 2.0
571 stars 156 forks source link

Improper definition of @type result(t) #335

Closed fireproofsocks closed 3 years ago

fireproofsocks commented 4 years ago

I believe that the @type result(t) definition should be changed from this:

@type result(t) :: :ok | {:ok, t} | {:error, Mongo.Error.t()}

to this:

@type result(t) :: :ok | {:ok, t} | {:error, Mongo.Error.t()} | {:error, Mongo.WriteError.t()}

I'm not an expert with types or with dialyzer, but I think that this discrepancy is causing dialyzer to flag errors on functions that rely on Mongo.insert_many/4 and do pattern matching based on {:error, %Mongo.WriteError{}}

joeapearson commented 3 years ago

@fireproofsocks sounds like you might be right; thanks for reporting! Can you check against the latest master branch since some signatures have changed since you originally made this report.

fireproofsocks commented 3 years ago

Yep, the typing for the Mongo.insert_many/4 has been updated, so it no longer issues any dialyzer errors (it now uses a write_result() type).

On master there is no only 1 dialyzer error:

lib/bson/encoder.ex:36:call
The function call will not succeed.

NaiveDateTime.from_erl!(
  {{non_neg_integer(), 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12, 1..255},
   {0, 0, 0}},
  0,
  Calendar.ISO
)

will never return since the success typing is:
(
  {{non_neg_integer(), 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12, 1..255},
   {byte(), byte(), byte()}},
  {non_neg_integer(), non_neg_integer()},
  atom()
) :: %NaiveDateTime{
  :calendar => atom(),
  :day => pos_integer(),
  :hour => non_neg_integer(),
  :microsecond => {non_neg_integer(), non_neg_integer()},
  :minute => non_neg_integer(),
  :month => pos_integer(),
  :second => non_neg_integer(),
  :year => integer()
}

and the contract is
(:calendar.datetime(), Calendar.microsecond(), Calendar.calendar()) :: t()

however this appears to be a red-herring since the referenced function does return properly:

iex> d = %Date{year: 2021, month: 10, day: 1}
~D[2021-10-01]
iex> BSON.Encoder.encode(d)
<<0, 140, 38, 57, 124, 1, 0, 0>>