diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8d51182..00257f5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,7 +22,10 @@ jobs: fail-fast: false matrix: version: - - '1.9' # Replace this with the minimum Julia version that your package supports. E.g. if your package requires Julia 1.5 or higher, change this to '1.5'. + - '1.6' + - '1.7' + - '1.8' + - '1.9' - '1' # Leave this line unchanged. '1' will automatically expand to the latest stable 1.x release of Julia. os: - ubuntu-latest diff --git a/Project.toml b/Project.toml index 4402efe..c70bdb6 100644 --- a/Project.toml +++ b/Project.toml @@ -4,6 +4,7 @@ authors = ["Sukera "] version = "0.9.1" [deps] +Compat = "34da2185-b29b-5c13-b0c7-acf172513d20" InteractiveUtils = "b77e0a4c-d291-57a0-90e8-8db25a27a240" Logging = "56ddb016-857b-54e1-b83d-db4d58db5568" Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" @@ -17,5 +18,6 @@ AbstractTrees = "1520ce14-60c1-5f80-bbc7-55ef81b5835c" ATExt = "AbstractTrees" [compat] +Compat = "3.35, 4" RequiredInterfaces = "0.1" julia = "1.9" diff --git a/src/PropCheck.jl b/src/PropCheck.jl index 820371f..5eb8d0b 100644 --- a/src/PropCheck.jl +++ b/src/PropCheck.jl @@ -1,5 +1,7 @@ module PropCheck +using Compat: Returns + using Base: Signed using Test using InteractiveUtils: subtypes diff --git a/src/integrated.jl b/src/integrated.jl index 2458ca0..71936a5 100644 --- a/src/integrated.jl +++ b/src/integrated.jl @@ -136,7 +136,7 @@ shrink according to `shrink`. mutable struct IntegratedUnique{T,ElT,S} <: AbstractIntegrated{T} els::Vector{ElT} cache::Vector{ElT} - const shrink::S + @constfield shrink::S function IntegratedUnique(vec::Vector{T}, shrink::S) where {T,S} treeType = integratorType(T) diff --git a/src/util.jl b/src/util.jl index 1316cc5..e8564b0 100644 --- a/src/util.jl +++ b/src/util.jl @@ -1,3 +1,19 @@ +""" + @constfield foo::Int + +A macro providing compatibility for `const` fields in mutable structs. +Gives a `const` `Expr` if supported, otherwise is a noop and just returns the field. +""" +macro constfield(ex::Expr) + ex.head != :(::) || length(ex.args) != 2 || throw(ArgumentError("`@constfield` only supports expressions of the form `field::Type`!")) + ex = esc(ex) + if VERSION < v"1.8" + ex + else + Expr(:const, ex) + end +end + function getSubtypes(T=Any)::Vector{DataType} T isa Union && return getSubUnions!(DataType[], T) subs = subtypes(T) diff --git a/test/runtests.jl b/test/runtests.jl index 317cf1b..1de3cd1 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -120,7 +120,13 @@ const numTypes = union(getSubtypes(Integer), getSubtypes(AbstractFloat)) end @testset "numsToZero" begin @testset "$T" for T in numTypes - @test numsToZero(T) broken=(T == BigInt || T == BigFloat) + if VERSION >= v"1.7" + @test numsToZero(T) broken=(T == BigInt || T == BigFloat) + else + if T != BigInt && T != BigFloat + @test numsToZero(T) + end + end end end @testset "filter predicates hold for shrunk values" begin @@ -147,12 +153,20 @@ const numTypes = union(getSubtypes(Integer), getSubtypes(AbstractFloat)) @testset "throwing properties still shrink" begin @test check(throwingProperty, itype(UInt8)) == (0x05, ArgumentError("x not smaller than 5")) end - @testset stringsFromTypeToEmpty() + @testset "stringsFromTypeToEmpty" begin + stringsFromTypeToEmpty() + end @testset "interleave preserves invariants" begin - @testset interleaveFilterInvariant() - @testset interleaveMapInvariant() + @testset "interleaveFilterInvariant" begin + interleaveFilterInvariant() + end + @testset "interleaveMapInvariant" begin + interleaveMapInvariant() + end + end + @testset "initialVectorLengthIsboundedByRange" begin + initialVectorLengthIsBoundedByRange() end - @testset initialVectorLengthIsBoundedByRange() @testset "`Integrated` can be `collect`ed" begin @test all(x -> x isa Tree{Int}, collect(Iterators.take(itype(Int), 5))) end @@ -163,13 +177,16 @@ const numTypes = union(getSubtypes(Integer), getSubtypes(AbstractFloat)) @test eltype(itr) == Tree{T} @test eltype(collect(itr)) == Tree{T} end - @testset "type unstable constructors" begin - grade = map(Base.splat(Pair), PropCheck.interleave(itype(String), isample(0:100))) - # it's type unstable because the empty dispatch returns `Dict{Any,Any}`! - # I'd love to propagate the lowerbound of `1` to make this type stable, but that is hard. - # maybe that needs dependent types? - gradegen = map(Base.splat(Dict), PropCheck.tuple(isample(0:10), grade)) - @test eltype(gradegen) == Union{PropCheck.Tree{Dict{Any, Any}}, PropCheck.Tree{Dict{String, Int64}}} + if VERSION >= v"1.9" + # this sadly doesn't infer before then, so we can't really test it :/ + @testset "type unstable constructors" begin + grade = map(Base.splat(Pair), PropCheck.interleave(itype(String), isample(0:100))) + # it's type unstable because the empty dispatch returns `Dict{Any,Any}`! + # I'd love to propagate the lowerbound of `1` to make this type stable, but that is hard. + # maybe that needs dependent types? + gradegen = map(Base.splat(Dict), PropCheck.tuple(isample(0:10), grade)) + @test eltype(gradegen) == Union{PropCheck.Tree{Dict{Any, Any}}, PropCheck.Tree{Dict{String, Int64}}} + end end @testset "$f preserves invariants" for f in (PropCheck.str, PropCheck.vector) # 3 hex characters is plenty - this is already 3^11 == 177147 possible strings