diff --git a/base/indices.jl b/base/indices.jl index 8cea043569ae6..d3daeca2b4d58 100644 --- a/base/indices.jl +++ b/base/indices.jl @@ -320,6 +320,26 @@ which they index. To support those cases, `to_indices(A, I)` calls `to_indices(A, axes(A), I)`, which then recursively walks through both the given tuple of indices and the dimensional indices of `A` in tandem. As such, not all index types are guaranteed to propagate to `Base.to_index`. + +# Examples +```jldoctest +julia> A = zeros(1,2,3,4); + +julia> to_indices(A, (1,1,2,2)) +(1, 1, 2, 2) + +julia> to_indices(A, (1,1,2,20)) # no bounds checking +(1, 1, 2, 20) + +julia> to_indices(A, (CartesianIndex((1,)), 2, CartesianIndex((3,4)))) # exotic index +(1, 2, 3, 4) + +julia> to_indices(A, ([1,1], 1:2, 3, 4)) +([1, 1], 1:2, 3, 4) + +julia> to_indices(A, (1,2)) # no shape checking +(1, 2) +``` """ to_indices(A, I::Tuple) = (@inline; to_indices(A, axes(A), I)) to_indices(A, I::Tuple{Any}) = (@inline; to_indices(A, (eachindex(IndexLinear(), A),), I)) diff --git a/base/iterators.jl b/base/iterators.jl index 188f7cae83fb4..1156821ac7200 100644 --- a/base/iterators.jl +++ b/base/iterators.jl @@ -55,7 +55,10 @@ _min_length(a, b, A, B) = min(length(a),length(b)) _diff_length(a, b, A, ::IsInfinite) = 0 _diff_length(a, b, ::IsInfinite, ::IsInfinite) = 0 _diff_length(a, b, ::IsInfinite, B) = length(a) # inherit behaviour, error -_diff_length(a, b, A, B) = max(length(a)-length(b), 0) +function _diff_length(a, b, A, B) + m, n = length(a), length(b) + return m > n ? m - n : zero(n - m) +end and_iteratorsize(isz::T, ::T) where {T} = isz and_iteratorsize(::HasLength, ::HasShape) = HasLength() diff --git a/base/loading.jl b/base/loading.jl index 740c2f922259e..0b498cf8811f1 100644 --- a/base/loading.jl +++ b/base/loading.jl @@ -419,6 +419,9 @@ or `nothing` if `m` was not imported from a package. Optionally further path component strings can be provided to construct a path within the package root. +To get the root directory of the package that imported the current module +the form `pkgdir(@__MODULE__)` can be used. + ```julia-repl julia> pkgdir(Foo) "/path/to/Foo.jl" @@ -447,6 +450,9 @@ from a package without a version field set. The version is read from the package's Project.toml during package load. +To get the version of the package that imported the current module +the form `pkgversion(@__MODULE__)` can be used. + !!! compat "Julia 1.9" This function was introduced in Julia 1.9. """ @@ -2069,11 +2075,13 @@ get_compiletime_preferences(::Nothing) = String[] end for chi in includes f, ftime_req = chi.filename, chi.mtime - # Issue #13606: compensate for Docker images rounding mtimes - # Issue #20837: compensate for GlusterFS truncating mtimes to microseconds - # The `ftime != 1.0` condition below provides compatibility with Nix mtime. ftime = mtime(f) - if ftime != ftime_req && ftime != floor(ftime_req) && ftime != trunc(ftime_req, digits=6) && ftime != 1.0 + is_stale = ( ftime != ftime_req ) && + ( ftime != floor(ftime_req) ) && # Issue #13606, PR #13613: compensate for Docker images rounding mtimes + ( ftime != trunc(ftime_req, digits=6) ) && # Issue #20837, PR #20840: compensate for GlusterFS truncating mtimes to microseconds + ( ftime != 1.0 ) && # PR #43090: provide compatibility with Nix mtime. + !( 0 < (ftime_req - ftime) < 1e-6 ) # PR #45552: Compensate for Windows tar giving mtimes that may be incorrect by up to one microsecond + if is_stale @debug "Rejecting stale cache file $cachefile (mtime $ftime_req) because file $f (mtime $ftime) has changed" return true end diff --git a/base/rational.jl b/base/rational.jl index 9e887bdaefa91..782b05e587e1b 100644 --- a/base/rational.jl +++ b/base/rational.jl @@ -95,6 +95,20 @@ end function write(s::IO, z::Rational) write(s,numerator(z),denominator(z)) end +function parse(::Type{Rational{T}}, s::AbstractString) where T<:Integer + ss = split(s, '/'; limit = 2) + if isone(length(ss)) + return Rational{T}(parse(T, s)) + end + @inbounds ns, ds = ss[1], ss[2] + if startswith(ds, '/') + ds = chop(ds; head = 1, tail = 0) + end + n = parse(T, ns) + d = parse(T, ds) + return n//d +end + function Rational{T}(x::Rational) where T<:Integer unsafe_rational(T, convert(T, x.num), convert(T, x.den)) diff --git a/base/sort.jl b/base/sort.jl index a9ae30f4aa475..7c87c764c342f 100644 --- a/base/sort.jl +++ b/base/sort.jl @@ -5,7 +5,7 @@ module Sort import ..@__MODULE__, ..parentmodule const Base = parentmodule(@__MODULE__) using .Base.Order -using .Base: copymutable, LinearIndices, length, (:), iterate, elsize, +using .Base: copymutable, LinearIndices, length, (:), iterate, OneTo, eachindex, axes, first, last, similar, zip, OrdinalRange, firstindex, lastindex, AbstractVector, @inbounds, AbstractRange, @eval, @inline, Vector, @noinline, AbstractMatrix, AbstractUnitRange, isless, identity, eltype, >, <, <=, >=, |, +, -, *, !, @@ -605,7 +605,10 @@ function sort!(v::AbstractVector{T}, lo::Integer, hi::Integer, a::MergeSortAlg, hi-lo <= SMALL_THRESHOLD && return sort!(v, lo, hi, SMALL_ALGORITHM, o) m = midpoint(lo, hi) - t = workspace(v, t0, m-lo+1) + + t = t0 === nothing ? similar(v, m-lo+1) : t0 + length(t) < m-lo+1 && resize!(t, m-lo+1) + Base.require_one_based_indexing(t) sort!(v, lo, m, a, o, t) sort!(v, m+1, hi, a, o, t) @@ -683,7 +686,7 @@ function radix_sort!(v::AbstractVector{U}, lo::Integer, hi::Integer, bits::Unsig t::AbstractVector{U}, chunk_size=radix_chunk_size_heuristic(lo, hi, bits)) where U <: Unsigned # bits is unsigned for performance reasons. mask = UInt(1) << chunk_size - 1 - counts = Vector{UInt}(undef, mask+2) + counts = Vector{Int}(undef, mask+2) @inbounds for shift in 0:chunk_size:bits-1 @@ -732,6 +735,7 @@ end # For AbstractVector{Bool}, counting sort is always best. # This is an implementation of counting sort specialized for Bools. +# Accepts unused workspace to avoid method ambiguity. function sort!(v::AbstractVector{B}, lo::Integer, hi::Integer, a::AdaptiveSort, o::Ordering, t::Union{AbstractVector{B}, Nothing}=nothing) where {B <: Bool} first = lt(o, false, true) ? false : lt(o, true, false) ? true : return v @@ -746,10 +750,6 @@ function sort!(v::AbstractVector{B}, lo::Integer, hi::Integer, a::AdaptiveSort, v end -workspace(v::AbstractVector, ::Nothing, len::Integer) = similar(v, len) -function workspace(v::AbstractVector{T}, t::AbstractVector{T}, len::Integer) where T - length(t) < len ? resize!(t, len) : t -end maybe_unsigned(x::Integer) = x # this is necessary to avoid calling unsigned on BigInt maybe_unsigned(x::BitSigned) = unsigned(x) function _extrema(v::AbstractVector, lo::Integer, hi::Integer, o::Ordering) @@ -856,8 +856,18 @@ function sort!(v::AbstractVector{T}, lo::Integer, hi::Integer, a::AdaptiveSort, u[i] -= u_min end - u2 = radix_sort!(u, lo, hi, bits, reinterpret(U, workspace(v, t, hi))) - uint_unmap!(v, u2, lo, hi, o, u_min) + if t !== nothing && checkbounds(Bool, t, lo:hi) # Fully preallocated and aligned workspace + u2 = radix_sort!(u, lo, hi, bits, reinterpret(U, t)) + uint_unmap!(v, u2, lo, hi, o, u_min) + elseif t !== nothing && (applicable(resize!, t) || length(t) >= hi-lo+1) # Viable workspace + length(t) >= hi-lo+1 || resize!(t, hi-lo+1) + t1 = axes(t, 1) isa OneTo ? t : view(t, firstindex(t):lastindex(t)) + u2 = radix_sort!(view(u, lo:hi), 1, hi-lo+1, bits, reinterpret(U, t1)) + uint_unmap!(view(v, lo:hi), u2, 1, hi-lo+1, o, u_min) + else # No viable workspace + u2 = radix_sort!(u, lo, hi, bits, similar(u)) + uint_unmap!(v, u2, lo, hi, o, u_min) + end end ## generic sorting methods ## @@ -1113,7 +1123,7 @@ function sortperm(v::AbstractVector; by=identity, rev::Union{Bool,Nothing}=nothing, order::Ordering=Forward, - workspace::Union{AbstractVector, Nothing}=nothing) + workspace::Union{AbstractVector{<:Integer}, Nothing}=nothing) ordr = ord(lt,by,rev,order) if ordr === Forward && isa(v,Vector) && eltype(v)<:Integer n = length(v) @@ -1235,7 +1245,7 @@ function sort(A::AbstractArray{T}; by=identity, rev::Union{Bool,Nothing}=nothing, order::Ordering=Forward, - workspace::Union{AbstractVector{T}, Nothing}=similar(A, 0)) where T + workspace::Union{AbstractVector{T}, Nothing}=similar(A, size(A, dims))) where T dim = dims order = ord(lt,by,rev,order) n = length(axes(A, dim)) @@ -1296,7 +1306,7 @@ function sort!(A::AbstractArray{T}; by=identity, rev::Union{Bool,Nothing}=nothing, order::Ordering=Forward, - workspace::Union{AbstractVector{T}, Nothing}=nothing) where T + workspace::Union{AbstractVector{T}, Nothing}=similar(A, size(A, dims))) where T ordr = ord(lt, by, rev, order) nd = ndims(A) k = dims @@ -1523,8 +1533,8 @@ issignleft(o::ForwardOrdering, x::Floats) = lt(o, x, zero(x)) issignleft(o::ReverseOrdering, x::Floats) = lt(o, x, -zero(x)) issignleft(o::Perm, i::Integer) = issignleft(o.order, o.data[i]) -function fpsort!(v::AbstractVector, a::Algorithm, o::Ordering, - t::Union{AbstractVector, Nothing}=nothing) +function fpsort!(v::AbstractVector{T}, a::Algorithm, o::Ordering, + t::Union{AbstractVector{T}, Nothing}=nothing) where T # fpsort!'s optimizations speed up comparisons, of which there are O(nlogn). # The overhead is O(n). For n < 10, it's not worth it. length(v) < 10 && return sort!(v, firstindex(v), lastindex(v), SMALL_ALGORITHM, o, t) @@ -1550,8 +1560,8 @@ function sort!(v::FPSortable, a::Algorithm, o::DirectOrdering, t::Union{FPSortable, Nothing}=nothing) fpsort!(v, a, o, t) end -function sort!(v::AbstractVector{<:Union{Signed, Unsigned}}, a::Algorithm, - o::Perm{<:DirectOrdering,<:FPSortable}, t::Union{AbstractVector, Nothing}=nothing) +function sort!(v::AbstractVector{T}, a::Algorithm, o::Perm{<:DirectOrdering,<:FPSortable}, + t::Union{AbstractVector{T}, Nothing}=nothing) where T <: Union{Signed, Unsigned} fpsort!(v, a, o, t) end diff --git a/deps/checksums/Pkg-201cbe2a50c06db65b1e7a30f64d4875042f2d4d.tar.gz/md5 b/deps/checksums/Pkg-201cbe2a50c06db65b1e7a30f64d4875042f2d4d.tar.gz/md5 deleted file mode 100644 index 88830e41d93ea..0000000000000 --- a/deps/checksums/Pkg-201cbe2a50c06db65b1e7a30f64d4875042f2d4d.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -c89009d5d31fd05f57c0f09e7303dd99 diff --git a/deps/checksums/Pkg-201cbe2a50c06db65b1e7a30f64d4875042f2d4d.tar.gz/sha512 b/deps/checksums/Pkg-201cbe2a50c06db65b1e7a30f64d4875042f2d4d.tar.gz/sha512 deleted file mode 100644 index a9d334f46fce9..0000000000000 --- a/deps/checksums/Pkg-201cbe2a50c06db65b1e7a30f64d4875042f2d4d.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -30ec5d0fec022d638dc62725053609269fb07bdfae5a07adb9367afc881c2e9147ffbf7e446be9fff76d3c9a19857e2b3a1edb22dad0a4a54c57627e2af8ab7f diff --git a/deps/checksums/Pkg-98d0cc276cc59817eb9c2e18e747fe027d7282a2.tar.gz/md5 b/deps/checksums/Pkg-98d0cc276cc59817eb9c2e18e747fe027d7282a2.tar.gz/md5 new file mode 100644 index 0000000000000..927835aebd23b --- /dev/null +++ b/deps/checksums/Pkg-98d0cc276cc59817eb9c2e18e747fe027d7282a2.tar.gz/md5 @@ -0,0 +1 @@ +8c6bc28980648ed4b7315544c79c8b75 diff --git a/deps/checksums/Pkg-98d0cc276cc59817eb9c2e18e747fe027d7282a2.tar.gz/sha512 b/deps/checksums/Pkg-98d0cc276cc59817eb9c2e18e747fe027d7282a2.tar.gz/sha512 new file mode 100644 index 0000000000000..ec9e546ace65a --- /dev/null +++ b/deps/checksums/Pkg-98d0cc276cc59817eb9c2e18e747fe027d7282a2.tar.gz/sha512 @@ -0,0 +1 @@ +84b8345212bb08e8801e049f2b2678edcde05bba7223965f2d75c902381b842555ea737ab084af2faa3804a7047c4b2cf9be533b153941c3dc761ddd459b4c43 diff --git a/src/codegen.cpp b/src/codegen.cpp index 466056542dd0b..55c57b162b1ff 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -6362,10 +6362,10 @@ static Function *gen_invoke_wrapper(jl_method_instance_t *lam, jl_value_t *jlret } else { Value *argPtr = ctx.builder.CreateConstInBoundsGEP1_32(ctx.types().T_prjlvalue, argArray, i - 1); - theArg = maybe_mark_load_dereferenceable( + theArg = tbaa_decorate(ctx.tbaa().tbaa_const, maybe_mark_load_dereferenceable( ctx.builder.CreateAlignedLoad(ctx.types().T_prjlvalue, argPtr, Align(sizeof(void*))), false, - ty); + ty)); } if (!isboxed) { theArg = decay_derived(ctx, emit_bitcast(ctx, theArg, PointerType::get(lty, 0))); @@ -7157,10 +7157,10 @@ static jl_llvm_functions_t argType : vi.value.typ); } else { - Value *argPtr = ctx.builder.CreateInBoundsGEP(ctx.types().T_prjlvalue, argArray, ConstantInt::get(getSizeTy(ctx.builder.getContext()), i-1)); - Value *load = maybe_mark_load_dereferenceable( + Value *argPtr = ctx.builder.CreateConstInBoundsGEP1_32(ctx.types().T_prjlvalue, argArray, i - 1); + Value *load = tbaa_decorate(ctx.tbaa().tbaa_const, maybe_mark_load_dereferenceable( ctx.builder.CreateAlignedLoad(ctx.types().T_prjlvalue, argPtr, Align(sizeof(void*))), - false, vi.value.typ); + false, vi.value.typ)); theArg = mark_julia_type(ctx, load, true, vi.value.typ); if (ctx.debug_enabled && vi.dinfo && !vi.boxroot && !vi.value.V) { SmallVector addr; diff --git a/src/gf.c b/src/gf.c index 3fc75f862500a..af841930fb99e 100644 --- a/src/gf.c +++ b/src/gf.c @@ -1946,7 +1946,8 @@ jl_method_instance_t *jl_method_lookup(jl_value_t **args, size_t nargs, size_t w // full is a boolean indicating if that method fully covers the input // // lim is the max # of methods to return. if there are more, returns jl_false. -// -1 for no limit. +// Negative values stand for no limit. +// Unless lim == -1, remove matches that are unambiguously covered by earler ones JL_DLLEXPORT jl_value_t *jl_matching_methods(jl_tupletype_t *types, jl_value_t *mt, int lim, int include_ambiguous, size_t world, size_t *min_valid, size_t *max_valid, int *ambig) { @@ -3036,7 +3037,7 @@ static jl_value_t *ml_matches(jl_methtable_t *mt, if (!subt2 && subt) break; if (subt == subt2) { - if (lim >= 0) { + if (lim != -1) { if (subt || !jl_has_empty_intersection(m->sig, m2->sig)) if (!jl_type_morespecific((jl_value_t*)m->sig, (jl_value_t*)m2->sig)) break; @@ -3190,7 +3191,7 @@ static jl_value_t *ml_matches(jl_methtable_t *mt, } } // when limited, skip matches that are covered by earlier ones (and aren't perhaps ambiguous with them) - if (lim >= 0) { + if (lim != -1) { for (i = 0; i < len; i++) { if (skip[i]) continue; diff --git a/src/signals-unix.c b/src/signals-unix.c index 8249c1c1e6ea0..c6f6a4eb842e0 100644 --- a/src/signals-unix.c +++ b/src/signals-unix.c @@ -361,7 +361,7 @@ static void segv_handler(int sig, siginfo_t *info, void *context) } #if !defined(JL_DISABLE_LIBUNWIND) -static unw_context_t *volatile signal_context; +static unw_context_t *signal_context; pthread_mutex_t in_signal_lock; static pthread_cond_t exit_signal_cond; static pthread_cond_t signal_caught_cond; @@ -384,13 +384,21 @@ static void jl_thread_suspend_and_get_state(int tid, unw_context_t **ctx) pthread_mutex_unlock(&in_signal_lock); return; } + // Request is either now 0 (meaning the other thread is waiting for + // exit_signal_cond already), + // Or it is now -1 (meaning the other thread + // is waiting for in_signal_lock, and we need to release that lock + // here for a bit, until the other thread has a chance to get to the + // exit_signal_cond) if (request == -1) { err = pthread_cond_wait(&signal_caught_cond, &in_signal_lock); assert(!err); } } + // Now the other thread is waiting on exit_signal_cond (verify that here by + // checking it is 0, and add an acquire barrier for good measure) int request = jl_atomic_load_acquire(&ptls2->signal_request); - assert(request == 0 || request == -1); (void) request; + assert(request == 0); (void) request; *ctx = signal_context; } @@ -400,8 +408,10 @@ static void jl_thread_resume(int tid, int sig) jl_atomic_store_release(&ptls2->signal_request, sig == -1 ? 3 : 1); pthread_cond_broadcast(&exit_signal_cond); pthread_cond_wait(&signal_caught_cond, &in_signal_lock); // wait for thread to acknowledge + // The other thread is waiting to leave exit_signal_cond (verify that here by + // checking it is 0, and add an acquire barrier for good measure) int request = jl_atomic_load_acquire(&ptls2->signal_request); - assert(request == 0 || request == -1); (void) request; + assert(request == 0); (void) request; pthread_mutex_unlock(&in_signal_lock); } #endif @@ -475,22 +485,26 @@ void usr2_handler(int sig, siginfo_t *info, void *ctx) if (ptls == NULL) return; int errno_save = errno; + // acknowledge that we saw the signal_request sig_atomic_t request = jl_atomic_exchange(&ptls->signal_request, -1); #if !defined(JL_DISABLE_LIBUNWIND) if (request == 1) { - signal_context = jl_to_bt_context(ctx); - jl_atomic_exchange(&ptls->signal_request, 0); - pthread_mutex_lock(&in_signal_lock); + signal_context = jl_to_bt_context(ctx); + // acknowledge that we set the signal_caught_cond broadcast + request = jl_atomic_exchange(&ptls->signal_request, 0); + assert(request == -1); (void) request; pthread_cond_broadcast(&signal_caught_cond); pthread_cond_wait(&exit_signal_cond, &in_signal_lock); request = jl_atomic_exchange(&ptls->signal_request, 0); assert(request == 1 || request == 3); + // acknowledge that we got the resume signal pthread_cond_broadcast(&signal_caught_cond); pthread_mutex_unlock(&in_signal_lock); } + else #endif - jl_atomic_exchange(&ptls->signal_request, 0); + jl_atomic_exchange(&ptls->signal_request, 0); // returns -1 if (request == 2) { int force = jl_check_force_sigint(); if (force || (!ptls->defer_signal && ptls->io_wait)) { diff --git a/stdlib/Pkg.version b/stdlib/Pkg.version index 44b8e0ac15e5e..079244a98a4ae 100644 --- a/stdlib/Pkg.version +++ b/stdlib/Pkg.version @@ -1,4 +1,4 @@ PKG_BRANCH = master -PKG_SHA1 = 201cbe2a50c06db65b1e7a30f64d4875042f2d4d +PKG_SHA1 = 98d0cc276cc59817eb9c2e18e747fe027d7282a2 PKG_GIT_URL := https://github.com/JuliaLang/Pkg.jl.git PKG_TAR_URL = https://api.github.com/repos/JuliaLang/Pkg.jl/tarball/$1 diff --git a/stdlib/REPL/src/REPLCompletions.jl b/stdlib/REPL/src/REPLCompletions.jl index 76482e96dd299..295fd5ae64229 100644 --- a/stdlib/REPL/src/REPLCompletions.jl +++ b/stdlib/REPL/src/REPLCompletions.jl @@ -530,14 +530,14 @@ end # Method completion on function call expression that look like :(max(1)) MAX_METHOD_COMPLETIONS::Int = 40 -function complete_methods(ex_org::Expr, context_module::Module=Main) +function complete_methods(ex_org::Expr, context_module::Module=Main, shift::Bool=false) out = Completion[] funct, found = get_type(ex_org.args[1], context_module)::Tuple{Any,Bool} !found && return out args_ex, kwargs_ex = complete_methods_args(ex_org.args[2:end], ex_org, context_module, true, true) push!(args_ex, Vararg{Any}) - complete_methods!(out, funct, args_ex, kwargs_ex, MAX_METHOD_COMPLETIONS) + complete_methods!(out, funct, args_ex, kwargs_ex, shift ? -2 : MAX_METHOD_COMPLETIONS) return out end @@ -626,7 +626,7 @@ function complete_methods!(out::Vector{Completion}, @nospecialize(funct), args_e m = Base._methods_by_ftype(t_in, nothing, max_method_completions, Base.get_world_counter(), #=ambig=# true, Ref(typemin(UInt)), Ref(typemax(UInt)), Ptr{Int32}(C_NULL)) if m === false - push!(out, TextCompletion(sprint(Base.show_signature_function, funct) * "( too many methods to show )")) + push!(out, TextCompletion(sprint(Base.show_signature_function, funct) * "( too many methods, use SHIFT-TAB to show )")) end m isa Vector || return for match in m @@ -835,9 +835,9 @@ function completions(string::String, pos::Int, context_module::Module=Main, shif if isa(ex, Expr) if ex.head === :call - return complete_methods(ex, context_module), first(frange):method_name_end, false + return complete_methods(ex, context_module, shift), first(frange):method_name_end, false elseif ex.head === :. && ex.args[2] isa Expr && (ex.args[2]::Expr).head === :tuple - return complete_methods(ex, context_module), first(frange):(method_name_end - 1), false + return complete_methods(ex, context_module, shift), first(frange):(method_name_end - 1), false end end elseif inc_tag === :comment diff --git a/stdlib/REPL/test/replcompletions.jl b/stdlib/REPL/test/replcompletions.jl index 6dc9d9b8b2883..f584569519c22 100644 --- a/stdlib/REPL/test/replcompletions.jl +++ b/stdlib/REPL/test/replcompletions.jl @@ -514,6 +514,17 @@ let s = """CompletionFoo.test4("\\"",""" @test length(c) == 2 end +# Test max method suggestions +let s = "convert(" + c, _, res = test_complete_noshift(s) + @test !res + @test only(c) == "convert( too many methods, use SHIFT-TAB to show )" + c2, _, res2 = test_complete(s) + @test !res2 + @test any(==(string(first(methods(convert)))), c2) + @test length(c2) > REPL.REPLCompletions.MAX_METHOD_COMPLETIONS +end + ########## Test where the current inference logic fails ######## # Fails due to inference fails to determine a concrete type for arg 1 # But it returns AbstractArray{T,N} and hence is able to remove test5(x::Float64) from the suggestions diff --git a/test/iterators.jl b/test/iterators.jl index 7ce47233f2ed5..453f27ca8885c 100644 --- a/test/iterators.jl +++ b/test/iterators.jl @@ -187,6 +187,8 @@ end @test isempty(collect(drop(0:2:10, 100))) @test_throws ArgumentError drop(0:2:8, -1) @test length(drop(1:3,typemax(Int))) == 0 +@test length(drop(UInt(1):2, 3)) == 0 +@test length(drop(StepRangeLen(1, 1, UInt(2)), 3)) == 0 @test Base.IteratorSize(drop(countfrom(1),3)) == Base.IsInfinite() @test_throws MethodError length(drop(countfrom(1), 3)) @test Base.IteratorSize(Iterators.drop(Iterators.filter(i -> i>0, 1:10), 2)) == Base.SizeUnknown() diff --git a/test/rational.jl b/test/rational.jl index 1618156212af7..9f47f2cb9dd16 100644 --- a/test/rational.jl +++ b/test/rational.jl @@ -265,6 +265,88 @@ end @test read(io2, typeof(rational2)) == rational2 end end +@testset "parse" begin + # Non-negative Int in which parsing is expected to work + @test parse(Rational{Int}, string(10)) == 10 // 1 + @test parse(Rational{Int}, "100/10" ) == 10 // 1 + @test parse(Rational{Int}, "100 / 10") == 10 // 1 + @test parse(Rational{Int}, "0 / 10") == 0 // 1 + @test parse(Rational{Int}, "100//10" ) == 10 // 1 + @test parse(Rational{Int}, "100 // 10") == 10 // 1 + @test parse(Rational{Int}, "0 // 10") == 0 // 1 + + # Variations of the separator that should throw errors + @test_throws ArgumentError parse(Rational{Int}, "100\\10" ) + @test_throws ArgumentError parse(Rational{Int}, "100 \\ 10") + @test_throws ArgumentError parse(Rational{Int}, "100\\\\10" ) + @test_throws ArgumentError parse(Rational{Int}, "100 \\\\ 10") + @test_throws ArgumentError parse(Rational{Int}, "100/ /10" ) + @test_throws ArgumentError parse(Rational{Int}, "100 / / 10") + @test_throws ArgumentError parse(Rational{Int}, "100// /10" ) + @test_throws ArgumentError parse(Rational{Int}, "100 // / 10") + @test_throws ArgumentError parse(Rational{Int}, "100///10" ) + @test_throws ArgumentError parse(Rational{Int}, "100 /// 10") + @test_throws ArgumentError parse(Rational{Int}, "100÷10" ) + @test_throws ArgumentError parse(Rational{Int}, "100 ÷ 10") + @test_throws ArgumentError parse(Rational{Int}, "100 10" ) + @test_throws ArgumentError parse(Rational{Int}, "100 10") + + # Zero denominator, negative denominator, and double negative + @test_throws ArgumentError parse(Rational{Int}, "0//0") + @test parse(Rational{Int}, "1000//-100") == -10 // 1 + @test parse(Rational{Int}, "-1000//-100") == 10 // 1 + + # Negative Int tests in which parsing is expected to work + @test parse(Rational{Int}, string(-10)) == -10 // 1 + @test parse(Rational{Int}, "-100/10" ) == -10 // 1 + @test parse(Rational{Int}, "-100 / 10") == -10 // 1 + @test parse(Rational{Int}, "-100//10" ) == -10 // 1 + + # Variations of the separator that should throw errors (negative version) + @test_throws ArgumentError parse(Rational{Int}, "-100\\10" ) + @test_throws ArgumentError parse(Rational{Int}, "-100 \\ 10") + @test_throws ArgumentError parse(Rational{Int}, "-100\\\\10" ) + @test_throws ArgumentError parse(Rational{Int}, "-100 \\\\ 10") + @test_throws ArgumentError parse(Rational{Int}, "-100/ /10" ) + @test_throws ArgumentError parse(Rational{Int}, "-100 / / 10") + @test_throws ArgumentError parse(Rational{Int}, "-100// /10" ) + @test_throws ArgumentError parse(Rational{Int}, "-100 // / 10") + @test_throws ArgumentError parse(Rational{Int}, "-100///10" ) + @test_throws ArgumentError parse(Rational{Int}, "-100 /// 10") + @test_throws ArgumentError parse(Rational{Int}, "-100÷10" ) + @test_throws ArgumentError parse(Rational{Int}, "-100 ÷ 10") + @test_throws ArgumentError parse(Rational{Int}, "-100 10" ) + @test_throws ArgumentError parse(Rational{Int}, "-100 10") + @test_throws ArgumentError parse(Rational{Int}, "-100 -10" ) + @test_throws ArgumentError parse(Rational{Int}, "-100 -10") + @test_throws ArgumentError parse(Rational{Int}, "100 -10" ) + @test_throws ArgumentError parse(Rational{Int}, "100 -10") + try # issue 44570 + parse(Rational{BigInt}, "100 10") + @test_broken false + catch + @test_broken true + end + + # A few tests for other Integer types + @test parse(Rational{Bool}, "true") == true // true + @test parse(Rational{UInt8}, "0xff/0xf") == UInt8(17) // UInt8(1) + @test parse(Rational{Int8}, "-0x7e/0xf") == Int8(-126) // Int8(15) + @test parse(Rational{BigInt}, "$(big(typemax(Int))*16)/8") == (big(typemax(Int))*2) // big(1) + # Mixed notations + @test parse(Rational{UInt8}, "0x64//28") == UInt8(25) // UInt8(7) + @test parse(Rational{UInt8}, "100//0x1c") == UInt8(25) // UInt8(7) + + # Out of the bounds tests + # 0x100 is 256, Int test works for both Int32 and Int64 + # The error must be throw even if the canonicalized fraction fits + # (i.e., would be less than typemax after divided by 2 in examples below, + # both over typemax values are even). + @test_throws OverflowError parse(Rational{UInt8}, "0x100/0x1") + @test_throws OverflowError parse(Rational{UInt8}, "0x100/0x2") + @test_throws OverflowError parse(Rational{Int}, "$(big(typemax(Int)) + 1)/1") + @test_throws OverflowError parse(Rational{Int}, "$(big(typemax(Int)) + 1)/2") +end # parse @testset "round" begin @test round(11//2) == round(11//2, RoundNearest) == 6//1 # rounds to closest _even_ integer diff --git a/test/sorting.jl b/test/sorting.jl index 43d7ebbdf67de..4875f10b37f0f 100644 --- a/test/sorting.jl +++ b/test/sorting.jl @@ -513,6 +513,16 @@ end @test issorted(a) end +@testset "sort!(::OffsetVector)" begin + for length in vcat(0:5, [10, 300, 500, 1000]) + for offset in [-100000, -10, -1, 0, 1, 17, 1729] + x = OffsetVector(rand(length), offset) + sort!(x) + @test issorted(x) + end + end +end + @testset "sort!(::OffsetMatrix; dims)" begin x = OffsetMatrix(rand(5,5), 5, -5) sort!(x; dims=1) @@ -654,17 +664,6 @@ end end end -@testset "workspace()" begin - for v in [[1, 2, 3], [0.0]] - for t0 in vcat([nothing], [similar(v,i) for i in 1:5]), len in 0:5 - t = Base.Sort.workspace(v, t0, len) - @test eltype(t) == eltype(v) - @test length(t) >= len - @test firstindex(t) == 1 - end - end -end - @testset "sort(x; workspace=w) " begin for n in [1,10,100,1000] v = rand(n) @@ -681,7 +680,7 @@ end end end - +# This testset is at the end of the file because it is slow. @testset "searchsorted" begin numTypes = [ Int8, Int16, Int32, Int64, Int128, UInt8, UInt16, UInt32, UInt64, UInt128, @@ -842,5 +841,6 @@ end end end end +# The "searchsorted" testset is at the end of the file because it is slow. end