From 99a240844940cde9ff6b65a1969403f98f912bbd Mon Sep 17 00:00:00 2001 From: mtfishman Date: Fri, 7 Feb 2025 10:06:08 -0500 Subject: [PATCH 1/2] Remove generic `AbstractArray` fallbacks for `position` --- Project.toml | 2 +- src/base/abstractarray.jl | 12 ------------ src/base/array.jl | 22 ++++++++++++++++++++++ 3 files changed, 23 insertions(+), 13 deletions(-) diff --git a/Project.toml b/Project.toml index ee4adef..0e05aec 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "TypeParameterAccessors" uuid = "7e5a90cf-f82e-492e-a09b-e3e26432c138" authors = ["ITensor developers and contributors"] -version = "0.2.2" +version = "0.3.0" [deps] LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" diff --git a/src/base/abstractarray.jl b/src/base/abstractarray.jl index bc408c9..0d5a39e 100644 --- a/src/base/abstractarray.jl +++ b/src/base/abstractarray.jl @@ -70,18 +70,6 @@ end return set_type_parameters(type, eltype, param) end -# These are generic fallback definitions. By convention, -# this is very commonly true of `AbstractArray` subtypes -# but it may not be correct, but it is very convenient -# to define this to make more operations "just work" -# on most AbstractArrays. -# TODO: evaluate if this is actually the case, and weigh up the benefits of ease of use -# against not having a helpful error thrown -position(type::Type{<:AbstractArray}, ::typeof(eltype)) = Position(1) -position(type::Type{<:AbstractArray}, ::typeof(ndims)) = Position(2) - -default_type_parameters(::Type{<:AbstractArray}) = (Float64, 1) - for wrapper in [:PermutedDimsArray, :(Base.ReshapedArray), :SubArray] @eval begin position(type::Type{<:$wrapper}, ::typeof(eltype)) = Position(1) diff --git a/src/base/array.jl b/src/base/array.jl index 247c73b..1c2d4c6 100644 --- a/src/base/array.jl +++ b/src/base/array.jl @@ -1,2 +1,24 @@ +# TODO: Is this the best way to handle this? +# The idea is to be able to write functions that accept inputs of the form: +# ```julia +# f(AbstractArray) +# f(AbstractArray{Float64}) +# f(AbstractMatrix{Float64}) +# ``` +# etc. +const AbstractArrayType{T,N} = Union{ + Type{AbstractArray}, + Type{AbstractArray{T}}, + Type{AbstractArray{<:Any,N}}, + Type{AbstractArray{T,N}}, +} +position(::AbstractArrayType, ::typeof(eltype)) = Position(1) +position(::AbstractArrayType, ::typeof(ndims)) = Position(2) +default_type_parameters(::AbstractArrayType) = (Float64, 1) + position(::Type{<:Array}, ::typeof(eltype)) = Position(1) position(::Type{<:Array}, ::typeof(ndims)) = Position(2) +default_type_parameters(::Type{<:Array}) = (Float64, 1) + +position(::Type{<:BitArray}, ::typeof(ndims)) = Position(1) +default_type_parameters(::Type{<:BitArray}) = (1,) From 6964e47cd689eb35949dacb5663d3db18bb87c04 Mon Sep 17 00:00:00 2001 From: mtfishman Date: Fri, 7 Feb 2025 13:37:33 -0500 Subject: [PATCH 2/2] Unwrap type in position --- src/TypeParameterAccessors.jl | 1 - src/base/abstractarray.jl | 11 +++++++++ src/base/array.jl | 24 ------------------- src/type_parameters.jl | 6 ++++- test/{extensions => }/test_fillarrays.jl | 0 test/{extensions => }/test_stridedviews.jl | 0 test/utils/test_inferred.jl | 28 ---------------------- 7 files changed, 16 insertions(+), 54 deletions(-) delete mode 100644 src/base/array.jl rename test/{extensions => }/test_fillarrays.jl (100%) rename test/{extensions => }/test_stridedviews.jl (100%) delete mode 100644 test/utils/test_inferred.jl diff --git a/src/TypeParameterAccessors.jl b/src/TypeParameterAccessors.jl index cbee221..0a51102 100644 --- a/src/TypeParameterAccessors.jl +++ b/src/TypeParameterAccessors.jl @@ -18,7 +18,6 @@ include("type_parameters.jl") include("ndims.jl") include("base/abstractarray.jl") include("base/similartype.jl") -include("base/array.jl") include("base/linearalgebra.jl") end diff --git a/src/base/abstractarray.jl b/src/base/abstractarray.jl index 0d5a39e..0316e3c 100644 --- a/src/base/abstractarray.jl +++ b/src/base/abstractarray.jl @@ -1,3 +1,14 @@ +position(::Type{AbstractArray}, ::typeof(eltype)) = Position(1) +position(::Type{AbstractArray}, ::typeof(ndims)) = Position(2) +default_type_parameters(::Type{AbstractArray}) = (Float64, 1) + +position(::Type{<:Array}, ::typeof(eltype)) = Position(1) +position(::Type{<:Array}, ::typeof(ndims)) = Position(2) +default_type_parameters(::Type{<:Array}) = (Float64, 1) + +position(::Type{<:BitArray}, ::typeof(ndims)) = Position(1) +default_type_parameters(::Type{<:BitArray}) = (1,) + struct Self end position(a, ::Self) = Position(0) position(::Type{T}, ::Self) where {T} = Position(0) diff --git a/src/base/array.jl b/src/base/array.jl deleted file mode 100644 index 1c2d4c6..0000000 --- a/src/base/array.jl +++ /dev/null @@ -1,24 +0,0 @@ -# TODO: Is this the best way to handle this? -# The idea is to be able to write functions that accept inputs of the form: -# ```julia -# f(AbstractArray) -# f(AbstractArray{Float64}) -# f(AbstractMatrix{Float64}) -# ``` -# etc. -const AbstractArrayType{T,N} = Union{ - Type{AbstractArray}, - Type{AbstractArray{T}}, - Type{AbstractArray{<:Any,N}}, - Type{AbstractArray{T,N}}, -} -position(::AbstractArrayType, ::typeof(eltype)) = Position(1) -position(::AbstractArrayType, ::typeof(ndims)) = Position(2) -default_type_parameters(::AbstractArrayType) = (Float64, 1) - -position(::Type{<:Array}, ::typeof(eltype)) = Position(1) -position(::Type{<:Array}, ::typeof(ndims)) = Position(2) -default_type_parameters(::Type{<:Array}) = (Float64, 1) - -position(::Type{<:BitArray}, ::typeof(ndims)) = Position(1) -default_type_parameters(::Type{<:BitArray}) = (1,) diff --git a/src/type_parameters.jl b/src/type_parameters.jl index 3c7d8ad..31e6ca0 100644 --- a/src/type_parameters.jl +++ b/src/type_parameters.jl @@ -27,7 +27,11 @@ function position end position(object, name) = position(typeof(object), name) position(::Type, pos::Int) = Position(pos) position(::Type, pos::Position) = pos -position(type::Type, pos) = throw(MethodError(position, (type, pos))) +function position(type::Type, name) + base_type = unspecify_type_parameters(type) + base_type === type && error("`position` not defined for $type and $name.") + return position(base_type, name) +end function positions(::Type{T}, pos::Tuple) where {T} return ntuple(length(pos)) do i diff --git a/test/extensions/test_fillarrays.jl b/test/test_fillarrays.jl similarity index 100% rename from test/extensions/test_fillarrays.jl rename to test/test_fillarrays.jl diff --git a/test/extensions/test_stridedviews.jl b/test/test_stridedviews.jl similarity index 100% rename from test/extensions/test_stridedviews.jl rename to test/test_stridedviews.jl diff --git a/test/utils/test_inferred.jl b/test/utils/test_inferred.jl deleted file mode 100644 index 755c31e..0000000 --- a/test/utils/test_inferred.jl +++ /dev/null @@ -1,28 +0,0 @@ -using Test: @inferred, @test - -macro test_inferred(ex, kws...) - @assert ex.head in [:call, :(<:)] - first_arg = ex.head === :(<:) ? 1 : 2 - @assert length(ex.args[first_arg:end]) == 2 - # Collect the broken/skip keywords and remove them from the rest of keywords - @assert all(kw -> kw.head === :(=), kws) - inferreds = [kw.args[2] for kw in kws if kw.args[1] === :inferred] - inferred = isempty(inferreds) ? true : only(inferreds) - wrappeds = [kw.args[2] for kw in kws if kw.args[1] === :wrapped] - wrapped = isempty(wrappeds) ? false : only(wrappeds) - kws = filter(kw -> kw.args[1] ∉ (:inferred, :wrapped), kws) - arg1 = ex.args[first_arg] - arg1 = quote - if $inferred - if $wrapped - @inferred((() -> $arg1)()) - else - @inferred($arg1) - end - else - $arg1 - end - end - ex.args[first_arg] = arg1 - return Expr(:macrocall, Symbol("@test"), :(), esc(ex), kws...) -end