diff --git a/lib/elixir/lib/range.ex b/lib/elixir/lib/range.ex index 58886331864..759d21b2f93 100644 --- a/lib/elixir/lib/range.ex +++ b/lib/elixir/lib/range.ex @@ -476,8 +476,8 @@ defmodule Range do """ @doc since: "1.8.0" @spec disjoint?(t, t) :: boolean - def disjoint?(first1..last1//step1 = range1, first2..last2//step2 = range2) do - if size(range1) == 0 or size(range2) == 0 do + def disjoint?(first1..last1//step1, first2..last2//step2) do + if empty?(first1, last1, step1) or empty?(first2, last2, step2) do true else {first1, last1, step1} = normalize(first1, last1, step1) @@ -513,7 +513,14 @@ defmodule Range do end end - @compile inline: [normalize: 3] + @compile inline: [empty?: 3, normalize: 3] + defp empty?(first, last, step) do + case step > 0 do + true -> first > last + false -> first < last + end + end + defp normalize(first, last, step) when first > last, do: {first - abs(div(first - last, step) * step), first, -step} diff --git a/lib/elixir/test/elixir/range_test.exs b/lib/elixir/test/elixir/range_test.exs index 508d2d29178..6ffc68482ff 100644 --- a/lib/elixir/test/elixir/range_test.exs +++ b/lib/elixir/test/elixir/range_test.exs @@ -82,6 +82,14 @@ defmodule RangeTest do end describe "disjoint?" do + test "empty ranges are disjoint" do + for empty <- [10..0//1, 10..0//2, 0..10//-1, 0..10//-2, 0..-1//1] do + assert Range.disjoint?(empty, 0..10) + assert Range.disjoint?(0..10, empty) + assert Range.disjoint?(empty, empty) + end + end + test "returns true for disjoint ranges" do assert_disjoint(1..5, 6..9) assert_disjoint(-3..1, 2..3)