From f3b5e56da1d87555806d4a99326ceca6492f2033 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Mon, 13 Jul 2020 16:39:08 -0400 Subject: [PATCH] squash! remove tuple Type manipulations from convert We use an inference barrier here where we know type-intersection will give an incorrect result to avoid the problem case of #32392. --- base/essentials.jl | 35 ++++++++++++++++++++++++++++++++++- base/reflection.jl | 25 ------------------------- 2 files changed, 34 insertions(+), 26 deletions(-) diff --git a/base/essentials.jl b/base/essentials.jl index b08c7fe17605d..5afce921c3620 100644 --- a/base/essentials.jl +++ b/base/essentials.jl @@ -106,6 +106,31 @@ macro specialize(vars...) return Expr(:meta, :specialize, vars...) end +""" + @isdefined s -> Bool + +Tests whether variable `s` is defined in the current scope. + +See also [`isdefined`](@ref). + +# Examples +```jldoctest +julia> function f() + println(@isdefined x) + x = 3 + println(@isdefined x) + end +f (generic function with 1 method) + +julia> f() +false +true +``` +""" +macro isdefined(s::Symbol) + return Expr(:escape, Expr(:isdefined, s)) +end + macro _pure_meta() return Expr(:meta, :pure) end @@ -280,7 +305,15 @@ _tuple_error(T::Type, x) = (@_noinline_meta; throw(MethodError(convert, (T, x))) convert(::Type{T}, x::T) where {T<:Tuple} = x function convert(::Type{T}, x::NTuple{N,Any}) where {N, T<:Tuple} - NTuple{N,Union{}} <: T || _tuple_error(T, x) + # First see if there could be any conversion of the input type that'd be a subtype of the output. + # If not, we'll throw an explicit MethodError (otherwise, it might throw a typeassert). + S = NTuple{N,Union{}} + # this test is a work-around for #32392: inference doesn't currently + # realize this can't be true, so it successfully prevents it from dropping + # the subtyping test on the next line (assuming it's definitely false) + # whenever `N` wasn't known at compile time + @isdefined(N) || (S = inferencebarrier(:unreachable)) + S <: T || _tuple_error(T, x) cvt1(n) = (@_inline_meta; convert(fieldtype(T, n), getfield(x, n, #=boundscheck=#false))) return ntuple(cvt1, Val(N))::NTuple{N,Any} end diff --git a/base/reflection.jl b/base/reflection.jl index cd548de1d38fd..7b41b8f49d8e8 100644 --- a/base/reflection.jl +++ b/base/reflection.jl @@ -240,31 +240,6 @@ Determine whether a global is declared `const` in a given `Module`. isconst(m::Module, s::Symbol) = ccall(:jl_is_const, Cint, (Any, Any), m, s) != 0 -""" - @isdefined s -> Bool - -Tests whether variable `s` is defined in the current scope. - -See also [`isdefined`](@ref). - -# Examples -```jldoctest -julia> function f() - println(@isdefined x) - x = 3 - println(@isdefined x) - end -f (generic function with 1 method) - -julia> f() -false -true -``` -""" -macro isdefined(s::Symbol) - return Expr(:isdefined, esc(s)) -end - """ @locals()