From 8269a1987c81a0a214b9c4b69ba7bb36618ddbb6 Mon Sep 17 00:00:00 2001 From: Martin Holters Date: Tue, 19 Oct 2021 14:18:14 +0200 Subject: [PATCH] Simplify `_isequal`, `_isless`, `__inc`, and `__dec` ...by removing unnecessary type checks/assertions. This basically restores the function bodies to what they looked like prior to #40594 and only keeps the changed signatures (with the additional changes to circumvent #39088. (cherry picked from commit df81a0d33d81e54c662932fd482cab9c67a09e39) --- base/multidimensional.jl | 18 ++++++------------ base/tuple.jl | 7 ++----- test/tuple.jl | 9 +++++++++ 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/base/multidimensional.jl b/base/multidimensional.jl index 25688edbe8f82..d93d2ddaae250 100644 --- a/base/multidimensional.jl +++ b/base/multidimensional.jl @@ -125,11 +125,9 @@ module IteratorsMD # comparison @inline isless(I1::CartesianIndex{N}, I2::CartesianIndex{N}) where {N} = _isless(0, I1.I, I2.I) - @inline function _isless(ret, I1::Tuple{Int,Vararg{Int,N}}, I2::Tuple{Int,Vararg{Int,N}}) where {N} + @inline function _isless(ret, I1::Tuple{Int,Vararg{Int}}, I2::Tuple{Int,Vararg{Int}}) newret = ifelse(ret==0, icmp(last(I1), last(I2)), ret) - t1, t2 = Base.front(I1), Base.front(I2) - # avoid dynamic dispatch by telling the compiler relational invariants - return isa(t1, Tuple{}) ? _isless(newret, (), ()) : _isless(newret, t1, t2::Tuple{Int,Vararg{Int}}) + return _isless(newret, Base.front(I1), Base.front(I2)) end _isless(ret, ::Tuple{}, ::Tuple{}) = ifelse(ret==1, true, false) icmp(a, b) = ifelse(isless(a,b), 1, ifelse(a==b, 0, -1)) @@ -409,15 +407,13 @@ module IteratorsMD valid = __is_valid_range(I, rng) && state[1] != last(rng) return valid, (I, ) end - @inline function __inc(state::Tuple{Int,Int,Vararg{Int,N}}, indices::Tuple{OrdinalRangeInt,OrdinalRangeInt,Vararg{OrdinalRangeInt,N}}) where {N} + @inline function __inc(state::Tuple{Int,Int,Vararg{Int}}, indices::Tuple{OrdinalRangeInt,OrdinalRangeInt,Vararg{OrdinalRangeInt}}) rng = indices[1] I = state[1] + step(rng) if __is_valid_range(I, rng) && state[1] != last(rng) return true, (I, tail(state)...) end - t1, t2 = tail(state), tail(indices) - # avoid dynamic dispatch by telling the compiler relational invariants - valid, I = isa(t1, Tuple{Int}) ? __inc(t1, t2::Tuple{OrdinalRangeInt}) : __inc(t1, t2::Tuple{OrdinalRangeInt,OrdinalRangeInt,Vararg{OrdinalRangeInt}}) + valid, I = __inc(tail(state), tail(indices)) return valid, (first(rng), I...) end @@ -522,15 +518,13 @@ module IteratorsMD valid = __is_valid_range(I, rng) && state[1] != first(rng) return valid, (I,) end - @inline function __dec(state::Tuple{Int,Int,Vararg{Int,N}}, indices::Tuple{OrdinalRangeInt,OrdinalRangeInt,Vararg{OrdinalRangeInt,N}}) where {N} + @inline function __dec(state::Tuple{Int,Int,Vararg{Int}}, indices::Tuple{OrdinalRangeInt,OrdinalRangeInt,Vararg{OrdinalRangeInt}}) rng = indices[1] I = state[1] - step(rng) if __is_valid_range(I, rng) && state[1] != first(rng) return true, (I, tail(state)...) end - t1, t2 = tail(state), tail(indices) - # avoid dynamic dispatch by telling the compiler relational invariants - valid, I = isa(t1, Tuple{Int}) ? __dec(t1, t2::Tuple{OrdinalRangeInt}) : __dec(t1, t2::Tuple{OrdinalRangeInt,OrdinalRangeInt,Vararg{OrdinalRangeInt}}) + valid, I = __dec(tail(state), tail(indices)) return valid, (last(rng), I...) end diff --git a/base/tuple.jl b/base/tuple.jl index 1abcccef3dab5..15132ec38c145 100644 --- a/base/tuple.jl +++ b/base/tuple.jl @@ -366,11 +366,8 @@ filter(f, t::Tuple) = length(t) < 32 ? filter_rec(f, t) : Tuple(filter(f, collec isequal(t1::Tuple, t2::Tuple) = length(t1) == length(t2) && _isequal(t1, t2) _isequal(::Tuple{}, ::Tuple{}) = true -function _isequal(t1::Tuple{Any,Vararg{Any,N}}, t2::Tuple{Any,Vararg{Any,N}}) where {N} - isequal(t1[1], t2[1]) || return false - t1, t2 = tail(t1), tail(t2) - # avoid dynamic dispatch by telling the compiler relational invariants - return isa(t1, Tuple{}) ? true : _isequal(t1, t2::Tuple{Any,Vararg{Any}}) +function _isequal(t1::Tuple{Any,Vararg{Any}}, t2::Tuple{Any,Vararg{Any}}) + return isequal(t1[1], t2[1]) && _isequal(tail(t1), tail(t2)) end function _isequal(t1::Any32, t2::Any32) for i = 1:length(t1) diff --git a/test/tuple.jl b/test/tuple.jl index 6087253d19167..a1582e8916dd8 100644 --- a/test/tuple.jl +++ b/test/tuple.jl @@ -636,3 +636,12 @@ end # https://github.com/JuliaLang/julia/issues/40814 @test Base.return_types(NTuple{3,Int}, (Vector{Int},)) == Any[NTuple{3,Int}] + +# issue #42457 +f42457(a::NTuple{3,Int}, b::Tuple)::Bool = Base.isequal(a, Base.inferencebarrier(b)::Tuple) +@test f42457((1, 1, 1), (1, 1, 1)) +@test !isempty(methods(Base._isequal, (NTuple{3, Int}, Tuple))) +g42457(a, b) = Base.isequal(a, b) ? 1 : 2.0 +@test only(Base.return_types(g42457, (NTuple{3, Int}, Tuple))) === Union{Float64, Int} +@test only(Base.return_types(g42457, (NTuple{3, Int}, NTuple))) === Union{Float64, Int} +@test only(Base.return_types(g42457, (NTuple{3, Int}, NTuple{4}))) === Float64