From 3fb87a73f05a34a943fc19d8535bd69b6dac08cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eric=20Meadows-J=C3=B6nsson?= Date: Fri, 14 Aug 2026 14:29:22 +0200 Subject: [PATCH 1/2] Optimize comparison of parsed versions --- lib/elixir/lib/version.ex | 11 +++++++++++ lib/elixir/test/elixir/version_test.exs | 20 ++++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/lib/elixir/lib/version.ex b/lib/elixir/lib/version.ex index 076964b3000..8dbaf264642 100644 --- a/lib/elixir/lib/version.ex +++ b/lib/elixir/lib/version.ex @@ -362,11 +362,22 @@ defmodule Version do """ @spec compare(version, version) :: :gt | :eq | :lt + def compare( + %Version{major: major1, minor: minor1, patch: patch1, pre: pre1}, + %Version{major: major2, minor: minor2, patch: patch2, pre: pre2} + ) do + do_compare(major1, minor1, patch1, pre1, major2, minor2, patch2, pre2) + end + def compare(version1, version2) do do_compare(to_matchable(version1, true), to_matchable(version2, true)) end defp do_compare({major1, minor1, patch1, pre1, _}, {major2, minor2, patch2, pre2, _}) do + do_compare(major1, minor1, patch1, pre1, major2, minor2, patch2, pre2) + end + + defp do_compare(major1, minor1, patch1, pre1, major2, minor2, patch2, pre2) do cond do major1 > major2 -> :gt major1 < major2 -> :lt diff --git a/lib/elixir/test/elixir/version_test.exs b/lib/elixir/test/elixir/version_test.exs index 6de54b01eb5..3b7844a5c6e 100644 --- a/lib/elixir/test/elixir/version_test.exs +++ b/lib/elixir/test/elixir/version_test.exs @@ -38,6 +38,26 @@ defmodule VersionTest do assert Version.compare("1.5.0-rc.0", "1.5.0-rc0") == :lt end + test "compare/2 with Version structs" do + large_major = Bitwise.bsl(1, 256) + large_pre = Bitwise.bsl(1, 128) + left = %Version{major: large_major, minor: 2, patch: 3, pre: ["alpha", large_pre]} + right = %Version{major: large_major, minor: 2, patch: 3, pre: ["alpha", large_pre + 1]} + + assert Version.compare(left, right) == :lt + assert Version.compare(right, left) == :gt + assert Version.compare(left, %{left | major: large_major + 1}) == :lt + assert Version.compare(%{left | minor: 1}, %{left | minor: 2}) == :lt + assert Version.compare(%{left | patch: 2}, %{left | patch: 3}) == :lt + assert Version.compare(%{left | pre: [1]}, %{left | pre: ["alpha"]}) == :lt + assert Version.compare(%{left | pre: ["alpha"]}, %{left | pre: ["alpha", 1]}) == :lt + assert Version.compare(%{left | pre: ["alpha"]}, %{left | pre: []}) == :lt + assert Version.compare(%{left | pre: []}, %{left | pre: ["alpha"]}) == :gt + assert Version.compare(%{left | build: "left"}, %{left | build: "right"}) == :eq + assert Version.compare(%{left | major: 1}, "2.0.0") == :lt + assert Version.compare("2.0.0", %{left | major: 1}) == :gt + end + test "compare/2 with invalid versions" do assert_raise Version.InvalidVersionError, fn -> Version.compare("1.0", "1.0.0") From cdfc35498b06f405c92531c43676e4c8fc077c00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eric=20Meadows-J=C3=B6nsson?= Date: Fri, 14 Aug 2026 15:45:38 +0200 Subject: [PATCH 2/2] Simplify version comparison fallback --- lib/elixir/lib/version.ex | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/elixir/lib/version.ex b/lib/elixir/lib/version.ex index 8dbaf264642..ec359f93d26 100644 --- a/lib/elixir/lib/version.ex +++ b/lib/elixir/lib/version.ex @@ -370,10 +370,9 @@ defmodule Version do end def compare(version1, version2) do - do_compare(to_matchable(version1, true), to_matchable(version2, true)) - end + {major1, minor1, patch1, pre1, _} = to_matchable(version1, true) + {major2, minor2, patch2, pre2, _} = to_matchable(version2, true) - defp do_compare({major1, minor1, patch1, pre1, _}, {major2, minor2, patch2, pre2, _}) do do_compare(major1, minor1, patch1, pre1, major2, minor2, patch2, pre2) end