From f197598f0e9eda3a2bd6d8045d61ffefb0fed430 Mon Sep 17 00:00:00 2001 From: Lukasz Samson Date: Thu, 9 Jul 2026 23:27:08 +0200 Subject: [PATCH] Add missing calendar key to Calendar.time() and fix truncate spec Found by re-running the type checker over function bodies with spec-derived argument domains (#15559): Calendar.time() was the only calendar-family type without a calendar: field (date, naive_datetime and datetime all declare it), yet virtually every Time function taking Calendar.time() destructures the field in its head -- to_string/1, to_iso8601/2, add/3, compare/2, shift/2, diff/3. A map conforming to the declared type therefore raised FunctionClauseError. Declare calendar: calendar like the sibling types. NaiveDateTime.truncate/2's second clause deliberately accepts any naive-datetime-compatible map (e.g. a DateTime), the same convention as add/3, to_date/1 and compare/2 -- but its spec said t(), making that clause unreachable per the spec. Accept Calendar.naive_datetime() like its siblings. Co-Authored-By: Claude Fable 5 --- lib/elixir/lib/calendar.ex | 1 + lib/elixir/lib/calendar/naive_datetime.ex | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/elixir/lib/calendar.ex b/lib/elixir/lib/calendar.ex index bd74afa23f..94aa09b624 100644 --- a/lib/elixir/lib/calendar.ex +++ b/lib/elixir/lib/calendar.ex @@ -106,6 +106,7 @@ defmodule Calendar do @typedoc "Any map or struct that contains the time fields." @type time :: %{ optional(any) => any, + calendar: calendar, hour: hour, minute: minute, second: second, diff --git a/lib/elixir/lib/calendar/naive_datetime.ex b/lib/elixir/lib/calendar/naive_datetime.ex index 7a2e5e972c..df37473ee0 100644 --- a/lib/elixir/lib/calendar/naive_datetime.ex +++ b/lib/elixir/lib/calendar/naive_datetime.ex @@ -672,7 +672,7 @@ defmodule NaiveDateTime do """ @doc since: "1.6.0" - @spec truncate(t(), :microsecond | :millisecond | :second) :: t() + @spec truncate(Calendar.naive_datetime(), :microsecond | :millisecond | :second) :: t() def truncate(%NaiveDateTime{microsecond: microsecond} = naive_datetime, precision) do %{naive_datetime | microsecond: Calendar.truncate(microsecond, precision)} end