From f8fb3a6f58782503e63d8726f2a6454fa22a3624 Mon Sep 17 00:00:00 2001 From: Neven Sajko Date: Sat, 8 Feb 2025 04:05:29 +0100 Subject: [PATCH 1/2] some type safety for `Fix` Disallows any type `Fix{x}` where `!(x isa Int) || (x < 0)`. Follows up on PR #54653. The goals are similar as in the closed PR #56518, but less ambitious. I hope it's not too late in the release cycle to consider this change as it seems not to be invasive or disruptive. --- base/operators.jl | 14 ++++++-------- test/functional.jl | 6 ++++-- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/base/operators.jl b/base/operators.jl index d01902e302359..ec3f61c635782 100644 --- a/base/operators.jl +++ b/base/operators.jl @@ -1170,17 +1170,15 @@ A type representing a partially-applied version of a function `f`, with the argu `Fix{1}(Fix{2}(f, 4), 4)` fixes the first and second arg, while `Fix{2}(Fix{1}(f, 4), 4)` fixes the first and third arg. """ -struct Fix{N,F,T} <: Function +struct Fix{N,F,T,NTuple{N,Nothing}<:NTup<:NTuple{N,Nothing}} <: Function f::F x::T function Fix{N}(f::F, x) where {N,F} - if !(N isa Int) - throw(ArgumentError(LazyString("expected type parameter in `Fix` to be `Int`, but got `", N, "::", typeof(N), "`"))) - elseif N < 1 - throw(ArgumentError(LazyString("expected `N` in `Fix{N}` to be integer greater than 0, but got ", N))) + if N < 1 + throw(ArgumentError("expected `N` in `Fix{N}` to be integer greater than 0, but got 0")) end - new{N,_stable_typeof(f),_stable_typeof(x)}(f, x) + new{N,_stable_typeof(f),_stable_typeof(x),NTuple{N,Nothing}}(f, x) end end @@ -1196,12 +1194,12 @@ end """ Alias for `Fix{1}`. See [`Fix`](@ref Base.Fix). """ -const Fix1{F,T} = Fix{1,F,T} +const Fix1{F,T} = Fix{1,F,T,NTuple{1,Nothing}} """ Alias for `Fix{2}`. See [`Fix`](@ref Base.Fix). """ -const Fix2{F,T} = Fix{2,F,T} +const Fix2{F,T} = Fix{2,F,T,NTuple{2,Nothing}} """ diff --git a/test/functional.jl b/test/functional.jl index 84c4098308ebd..9a0c159dfe043 100644 --- a/test/functional.jl +++ b/test/functional.jl @@ -348,9 +348,11 @@ end @test f() == 'a' end @testset "Dummy-proofing" begin + @test_throws TypeError Fix{1, <:Any, <:Any, Union{}} + @test_throws Exception Fix{-1} @test_throws ArgumentError("expected `N` in `Fix{N}` to be integer greater than 0, but got 0") Fix{0}(>, 1) - @test_throws ArgumentError("expected type parameter in `Fix` to be `Int`, but got `0.5::Float64`") Fix{0.5}(>, 1) - @test_throws ArgumentError("expected type parameter in `Fix` to be `Int`, but got `1::UInt64`") Fix{UInt64(1)}(>, 1) + @test_throws TypeError Fix{0.5} + @test_throws TypeError Fix{UInt64(1)} end @testset "Specialize to structs not in `Base`" begin struct MyStruct From eaa8a83f4be2a2ce83dbb06fa02370077a762109 Mon Sep 17 00:00:00 2001 From: Neven Sajko <4944410+nsajko@users.noreply.github.com> Date: Sat, 8 Feb 2025 04:42:51 +0100 Subject: [PATCH 2/2] add test --- test/functional.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/test/functional.jl b/test/functional.jl index 9a0c159dfe043..8ab52cf263081 100644 --- a/test/functional.jl +++ b/test/functional.jl @@ -348,6 +348,7 @@ end @test f() == 'a' end @testset "Dummy-proofing" begin + @test_throws TypeError Fix{Int} @test_throws TypeError Fix{1, <:Any, <:Any, Union{}} @test_throws Exception Fix{-1} @test_throws ArgumentError("expected `N` in `Fix{N}` to be integer greater than 0, but got 0") Fix{0}(>, 1)