Skip to content

Commit

Permalink
Enable suppression of warnings from ambiguity & unbound tests (JuliaL…
Browse files Browse the repository at this point in the history
…ang#43817)

* Revert "filesystem & binaryplatforms: remove undefined vars from exports (JuliaLang#43631)"

This reverts commit a3c2798.

* Enable suppression of warnings in ambiguity & undefined tests
  • Loading branch information
timholy authored and LilithHafner committed Feb 22, 2022
1 parent 5e495bb commit 9454725
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 9 deletions.
4 changes: 4 additions & 0 deletions base/filesystem.jl
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ export File,
JL_O_CREAT,
JL_O_EXCL,
JL_O_TRUNC,
JL_O_TEMPORARY,
JL_O_SHORT_LIVED,
JL_O_SEQUENTIAL,
JL_O_RANDOM,
JL_O_NOCTTY,
S_IRUSR, S_IWUSR, S_IXUSR, S_IRWXU,
S_IRGRP, S_IWGRP, S_IXGRP, S_IRWXG,
Expand Down
45 changes: 39 additions & 6 deletions stdlib/Test/src/Test.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1660,7 +1660,9 @@ function is_in_mods(m::Module, recursive::Bool, mods)
end

"""
detect_ambiguities(mod1, mod2...; recursive=false, ambiguous_bottom=false)
detect_ambiguities(mod1, mod2...; recursive=false,
ambiguous_bottom=false,
allowed_undefineds=nothing)
Returns a vector of `(Method,Method)` pairs of ambiguous methods
defined in the specified modules.
Expand All @@ -1669,10 +1671,17 @@ Use `recursive=true` to test in all submodules.
`ambiguous_bottom` controls whether ambiguities triggered only by
`Union{}` type parameters are included; in most cases you probably
want to set this to `false`. See [`Base.isambiguous`](@ref).
See [`Test.detect_unbound_args`](@ref) for an explanation of
`allowed_undefineds`.
!!! compat "Julia 1.8"
`allowed_undefineds` requires at least Julia 1.8.
"""
function detect_ambiguities(mods::Module...;
recursive::Bool = false,
ambiguous_bottom::Bool = false)
ambiguous_bottom::Bool = false,
allowed_undefineds = nothing)
@nospecialize
ambs = Set{Tuple{Method,Method}}()
mods = collect(mods)::Vector{Module}
Expand Down Expand Up @@ -1709,7 +1718,11 @@ function detect_ambiguities(mods::Module...;
for n in names(mod, all = true)
Base.isdeprecated(mod, n) && continue
if !isdefined(mod, n)
is_in_mods(mod, recursive, mods) && println("Skipping ", mod, '.', n) # typically stale exports
if is_in_mods(mod, recursive, mods)
if allowed_undefineds === nothing || GlobalRef(mod, n) allowed_undefineds
println("Skipping ", mod, '.', n) # typically stale exports
end
end
continue
end
f = Base.unwrap_unionall(getfield(mod, n))
Expand All @@ -1726,13 +1739,29 @@ function detect_ambiguities(mods::Module...;
end

"""
detect_unbound_args(mod1, mod2...; recursive=false)
detect_unbound_args(mod1, mod2...; recursive=false, allowed_undefineds=nothing)
Returns a vector of `Method`s which may have unbound type parameters.
Use `recursive=true` to test in all submodules.
By default, any undefined symbols trigger a warning. This warning can
be suppressed by supplying a collection of `GlobalRef`s for which
the warning can be skipped. For example, setting
```
allow_undefineds = Set([GlobalRef(Base, :active_repl),
GlobalRef(Base, :active_repl_backend)])
```
would suppress warnings about `Base.active_repl` and
`Base.active_repl_backend`.
!!! compat "Julia 1.8"
`allowed_undefineds` requires at least Julia 1.8.
"""
function detect_unbound_args(mods...;
recursive::Bool = false)
recursive::Bool = false,
allowed_undefineds=nothing)
@nospecialize mods
ambs = Set{Method}()
mods = collect(mods)::Vector{Module}
Expand Down Expand Up @@ -1760,7 +1789,11 @@ function detect_unbound_args(mods...;
for n in names(mod, all = true)
Base.isdeprecated(mod, n) && continue
if !isdefined(mod, n)
is_in_mods(mod, recursive, mods) && println("Skipping ", mod, '.', n) # typically stale exports
if is_in_mods(mod, recursive, mods)
if allowed_undefineds === nothing || GlobalRef(mod, n) allowed_undefineds
println("Skipping ", mod, '.', n) # typically stale exports
end
end
continue
end
f = Base.unwrap_unionall(getfield(mod, n))
Expand Down
24 changes: 21 additions & 3 deletions test/ambiguous.jl
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,24 @@ ambig(x::Union{Char, Int16}) = 's'
@test ambig(Int16(1)) == 's'

# Automatic detection of ambiguities

const allowed_undefineds = Set([
GlobalRef(Base, :active_repl),
GlobalRef(Base, :active_repl_backend),
GlobalRef(Base.Filesystem, :JL_O_TEMPORARY),
GlobalRef(Base.Filesystem, :JL_O_SHORT_LIVED),
GlobalRef(Base.Filesystem, :JL_O_SEQUENTIAL),
GlobalRef(Base.Filesystem, :JL_O_RANDOM),
])

let Distributed = get(Base.loaded_modules,
Base.PkgId(Base.UUID("8ba89e20-285c-5b6f-9357-94700520ee1b"), "Distributed"),
nothing)
if Distributed !== nothing
push!(allowed_undefineds, GlobalRef(Distributed, :cluster_manager))
end
end

module Ambig1
ambig(x, y) = 1
ambig(x::Integer, y) = 2
Expand Down Expand Up @@ -153,7 +171,7 @@ using LinearAlgebra, SparseArrays, SuiteSparse
# Test that Core and Base are free of ambiguities
# not using isempty so this prints more information when it fails
@testset "detect_ambiguities" begin
let ambig = Set{Any}(((m1.sig, m2.sig) for (m1, m2) in detect_ambiguities(Core, Base; recursive=true, ambiguous_bottom=false)))
let ambig = Set{Any}(((m1.sig, m2.sig) for (m1, m2) in detect_ambiguities(Core, Base; recursive=true, ambiguous_bottom=false, allowed_undefineds)))
@test isempty(ambig)
expect = []
good = true
Expand Down Expand Up @@ -183,7 +201,7 @@ using LinearAlgebra, SparseArrays, SuiteSparse

# List standard libraries. Exclude modules such as Main, Base, and Core.
let modules = [mod for (pkg, mod) in Base.loaded_modules if pkg.uuid !== nothing && String(pkg.name) in STDLIBS]
@test isempty(detect_ambiguities(modules...; recursive=true))
@test isempty(detect_ambiguities(modules...; recursive=true, allowed_undefineds))
end
end

Expand Down Expand Up @@ -313,7 +331,7 @@ end
@test need_to_handle_undef_sparam == Set()
end
let need_to_handle_undef_sparam =
Set{Method}(detect_unbound_args(Base; recursive=true))
Set{Method}(detect_unbound_args(Base; recursive=true, allowed_undefineds))
pop!(need_to_handle_undef_sparam, which(Base._totuple, (Type{Tuple{Vararg{E}}} where E, Any, Any)))
pop!(need_to_handle_undef_sparam, which(Base.eltype, Tuple{Type{Tuple{Any}}}))
pop!(need_to_handle_undef_sparam, first(methods(Base.same_names)))
Expand Down

0 comments on commit 9454725

Please sign in to comment.