diff --git a/base/compiler/tfuncs.jl b/base/compiler/tfuncs.jl index d67f6f7ccc4356..fb4d8549295af1 100644 --- a/base/compiler/tfuncs.jl +++ b/base/compiler/tfuncs.jl @@ -876,12 +876,12 @@ function _fieldtype_nothrow(@nospecialize(s), exact::Bool, name::Const) isa(fld, Int) || return false ftypes = datatype_fieldtypes(u) nf = length(ftypes) - (fld >= 1 && fld <= nf) || return false if u.name === Tuple.name && fld >= nf && isvarargtype(ftypes[nf]) - # The length of the tuple will be determined at runtime, we can't say - # anything - return false + # If we don't know the exact type, the length of the tuple will be determined + # at runtime and we can't say anything. + return exact end + (fld >= 1 && fld <= nf) || return false return true end diff --git a/base/essentials.jl b/base/essentials.jl index e5870bdb9b893f..6a74e99c32a24a 100644 --- a/base/essentials.jl +++ b/base/essentials.jl @@ -205,7 +205,7 @@ ERROR: ArgumentError: Cannot call tail on an empty tuple. tail(x::Tuple) = argtail(x...) tail(::Tuple{}) = throw(ArgumentError("Cannot call tail on an empty tuple.")) -tuple_type_head(T::Type) = (@_pure_meta; fieldtype(T::Type{<:Tuple}, 1)) +tuple_type_head(T::Type) = (@_pure_meta; fieldtype(T, 1)) function tuple_type_tail(T::Type) @_pure_meta diff --git a/base/multidimensional.jl b/base/multidimensional.jl index 03b1d151f23b4f..51de7184cb92f6 100644 --- a/base/multidimensional.jl +++ b/base/multidimensional.jl @@ -758,8 +758,7 @@ function _unsafe_getindex(::IndexStyle, A::AbstractArray, I::Vararg{Union{Real, return dest end -# Always index with the exactly indices provided. -@generated function _unsafe_getindex!(dest::AbstractArray, src::AbstractArray, I::Vararg{Union{Real, AbstractArray}, N}) where N +function _generate_unsafe_getindex!_body(N::Int) quote @_inline_meta D = eachindex(dest) @@ -776,6 +775,20 @@ end end end +# Always index with the exactly indices provided. +@generated function _unsafe_getindex!(dest::AbstractArray, src::AbstractArray, I::Vararg{Union{Real, AbstractArray}, N}) where N + _generate_unsafe_getindex!_body(N) +end + +# manually written-out specializations for 1 and 2 arguments to save compile time +@eval function _unsafe_getindex!(dest::AbstractArray, src::AbstractArray, I::Vararg{Union{Real, AbstractArray},1}) + $(_generate_unsafe_getindex!_body(1)) +end + +@eval function _unsafe_getindex!(dest::AbstractArray, src::AbstractArray, I::Vararg{Union{Real, AbstractArray},2}) + $(_generate_unsafe_getindex!_body(2)) +end + @noinline throw_checksize_error(A, sz) = throw(DimensionMismatch("output array is the wrong size; expected $sz, got $(size(A))")) ## setindex! ## @@ -786,8 +799,7 @@ function _setindex!(l::IndexStyle, A::AbstractArray, x, I::Union{Real, AbstractA A end -@generated function _unsafe_setindex!(::IndexStyle, A::AbstractArray, x, I::Union{Real,AbstractArray}...) - N = length(I) +function _generate_unsafe_setindex!_body(N::Int) quote x′ = unalias(A, x) @nexprs $N d->(I_d = unalias(A, I[d])) @@ -806,6 +818,18 @@ end end end +@generated function _unsafe_setindex!(::IndexStyle, A::AbstractArray, x, I::Vararg{Union{Real,AbstractArray}, N}) where N + _generate_unsafe_setindex!_body(N) +end + +@eval function _unsafe_setindex!(::IndexStyle, A::AbstractArray, x, I::Vararg{Union{Real,AbstractArray},1}) + $(_generate_unsafe_setindex!_body(1)) +end + +@eval function _unsafe_setindex!(::IndexStyle, A::AbstractArray, x, I::Vararg{Union{Real,AbstractArray},2}) + $(_generate_unsafe_setindex!_body(2)) +end + diff(a::AbstractVector) = diff(a, dims=1) """ diff --git a/base/namedtuple.jl b/base/namedtuple.jl index f315be36256c73..f341291a7f00e1 100644 --- a/base/namedtuple.jl +++ b/base/namedtuple.jl @@ -248,7 +248,9 @@ function merge(a::NamedTuple{an}, b::NamedTuple{bn}) where {an, bn} end end -merge(a::NamedTuple{()}, b::NamedTuple) = b +merge(a::NamedTuple, b::NamedTuple{()}) = a +merge(a::NamedTuple{()}, b::NamedTuple{()}) = a +merge(a::NamedTuple{()}, b::NamedTuple) = b merge(a::NamedTuple, b::Iterators.Pairs{<:Any,<:Any,<:Any,<:NamedTuple}) = merge(a, b.data) @@ -320,6 +322,8 @@ function structdiff(a::NamedTuple{an}, b::Union{NamedTuple{bn}, Type{NamedTuple{ end end +structdiff(a::NamedTuple{an}, b::Union{NamedTuple{an}, Type{NamedTuple{an}}}) where {an} = (;) + """ setindex(nt::NamedTuple, val, key::Symbol) diff --git a/test/compiler/inference.jl b/test/compiler/inference.jl index 23767ae32fadc5..7092b8fc38e972 100644 --- a/test/compiler/inference.jl +++ b/test/compiler/inference.jl @@ -655,6 +655,9 @@ let fieldtype_tfunc = Core.Compiler.fieldtype_tfunc, @test fieldtype_nothrow(Union{Type{Base.RefValue{<:Real}}, Type{Base.RefValue{Any}}}, Const(:x)) @test fieldtype_nothrow(Const(Union{Base.RefValue{<:Real}, Base.RefValue{Any}}), Const(:x)) @test fieldtype_nothrow(Type{Union{Base.RefValue{T}, Base.RefValue{Any}}} where {T<:Real}, Const(:x)) + @test fieldtype_nothrow(Type{Tuple{Vararg{Int}}}, Const(1)) + @test fieldtype_nothrow(Type{Tuple{Vararg{Int}}}, Const(42)) + @test !fieldtype_nothrow(Type{<:Tuple{Vararg{Int}}}, Const(1)) end # issue #11480