Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[pull] master from JuliaLang:master #1803

Merged
merged 4 commits into from
Mar 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion base/compiler/inferencestate.jl
Original file line number Diff line number Diff line change
Expand Up @@ -487,7 +487,17 @@ function sptypes_from_meth_instance(linfo::MethodInstance)
ty = UnionAll(tv, Type{tv})
end
@label ty_computed
undef = !constrains_param(v, linfo.specTypes, #=covariant=#true)
undef = !(let sig=sig
# if the specialized signature `linfo.specTypes` doesn't contain any free
# type variables, we can use it for a more accurate analysis of whether `v`
# is constrained or not, otherwise we should use `def.sig` which always
# doesn't contain any free type variables
if !has_free_typevars(linfo.specTypes)
sig = linfo.specTypes
end
@assert !has_free_typevars(sig)
constrains_param(v, sig, #=covariant=#true)
end)
elseif isvarargtype(v)
ty = Int
undef = false
Expand Down
71 changes: 70 additions & 1 deletion base/errorshow.jl
Original file line number Diff line number Diff line change
Expand Up @@ -823,6 +823,73 @@ function _simplify_include_frames(trace)
return trace[kept_frames]
end

# Collapse frames that have the same location (in some cases)
function _collapse_repeated_frames(trace)
kept_frames = trues(length(trace))
last_frame = nothing
for i in 1:length(trace)
frame::StackFrame, _ = trace[i]
if last_frame !== nothing && frame.file == last_frame.file && frame.line == last_frame.line
#=
Handles this case:

f(g, a; kw...) = error();
@inline f(a; kw...) = f(identity, a; kw...);
f(1)

which otherwise ends up as:

[4] #f#4 <-- useless
@ ./REPL[2]:1 [inlined]
[5] f(a::Int64)
@ Main ./REPL[2]:1
=#
if startswith(sprint(show, last_frame), "#")
kept_frames[i-1] = false
end

#= Handles this case
g(x, y=1, z=2) = error();
g(1)

which otherwise ends up as:

[2] g(x::Int64, y::Int64, z::Int64)
@ Main ./REPL[1]:1
[3] g(x::Int64) <-- useless
@ Main ./REPL[1]:1
=#
if frame.linfo isa MethodInstance && last_frame.linfo isa MethodInstance &&
frame.linfo.def isa Method && last_frame.linfo.def isa Method
m, last_m = frame.linfo.def::Method, last_frame.linfo.def::Method
params, last_params = Base.unwrap_unionall(m.sig).parameters, Base.unwrap_unionall(last_m.sig).parameters

if last_m.nkw != 0
pos_sig_params = Base.rewrap_unionall(Tuple{last_params[(last_m.nkw+2):end]...}, last_m.sig).parameters
issame = true
if pos_sig_params == params
kept_frames[i] = false
end
end
if length(last_params) > length(params)
issame = true
for i = 1:length(params)
issame &= params[i] == last_params[i]
end
if issame
kept_frames[i] = false
end
end
end

# TODO: Detect more cases that can be collapsed
end
last_frame = frame
end
return trace[kept_frames]
end


function process_backtrace(t::Vector, limit::Int=typemax(Int); skipC = true)
n = 0
last_frame = StackTraces.UNKNOWN
Expand Down Expand Up @@ -875,7 +942,9 @@ function process_backtrace(t::Vector, limit::Int=typemax(Int); skipC = true)
if n > 0
push!(ret, (last_frame, n))
end
return _simplify_include_frames(ret)
trace = _simplify_include_frames(ret)
trace = _collapse_repeated_frames(trace)
return trace
end

function show_exception_stack(io::IO, stack)
Expand Down
1 change: 1 addition & 0 deletions base/opaque_closure.jl
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ function Core.OpaqueClosure(ir::IRCode, env...;
if (isva && nargs > length(ir.argtypes)) || (!isva && nargs != length(ir.argtypes)-1)
throw(ArgumentError("invalid argument count"))
end
ir = Core.Compiler.copy(ir)
src = ccall(:jl_new_code_info_uninit, Ref{CodeInfo}, ())
src.slotflags = UInt8[]
src.slotnames = fill(:none, nargs+1)
Expand Down
20 changes: 20 additions & 0 deletions test/compiler/inference.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4684,6 +4684,26 @@ unknown_sparam_nothrow2(x::Ref{Ref{T}}) where T = @isdefined(T) ? T::Type : noth
@test only(Base.return_types(unknown_sparam_nothrow1, (Ref,))) === Type
@test only(Base.return_types(unknown_sparam_nothrow2, (Ref{Ref{T}} where T,))) === Type

struct Issue49027{Ty<:Number}
x::Ty
end
function issue49027(::Type{<:Issue49027{Ty}}) where Ty
if @isdefined Ty # should be false when `Ty` is given as a free type var.
return Ty::DataType
end
return nothing
end
@test only(Base.return_types(issue49027, (Type{Issue49027{TypeVar(:Ty)}},))) >: Nothing
@test isnothing(issue49027(Issue49027{TypeVar(:Ty)}))
function issue49027_integer(::Type{<:Issue49027{Ty}}) where Ty<:Integer
if @isdefined Ty # should be false when `Ty` is given as a free type var.
return Ty::DataType
end
nothing
end
@test only(Base.return_types(issue49027_integer, (Type{Issue49027{TypeVar(:Ty,Int)}},))) >: Nothing
@test isnothing(issue49027_integer(Issue49027{TypeVar(:Ty,Int)}))

function fapplicable end
gapplicable() = Val(applicable(fapplicable))
gapplicable(x) = Val(applicable(fapplicable; x))
Expand Down
40 changes: 40 additions & 0 deletions test/errorshow.jl
Original file line number Diff line number Diff line change
Expand Up @@ -947,3 +947,43 @@ let buf = IOBuffer()
Base.show_method_candidates(buf, Base.MethodError(isa, ()), pairs((a = 5,)))
@test isempty(take!(buf))
end

f_internal_wrap(g, a; kw...) = error();
@inline f_internal_wrap(a; kw...) = f_internal_wrap(identity, a; kw...);
bt = try
f_internal_wrap(1)
catch
catch_backtrace()
end
@test !occursin("#f_internal_wrap#", sprint(Base.show_backtrace, bt))

g_collapse_pos(x, y=1.0, z=2.0) = error()
bt = try
g_collapse_pos(1.0)
catch
catch_backtrace()
end
bt_str = sprint(Base.show_backtrace, bt)
@test occursin("g_collapse_pos(x::Float64, y::Float64, z::Float64)", bt_str)
@test !occursin("g_collapse_pos(x::Float64)", bt_str)

g_collapse_kw(x; y=2.0) = error()
bt = try
g_collapse_kw(1.0)
catch
catch_backtrace()
end
bt_str = sprint(Base.show_backtrace, bt)
@test occursin("g_collapse_kw(x::Float64; y::Float64)", bt_str)
@test !occursin("g_collapse_kw(x::Float64)", bt_str)

g_collapse_pos_kw(x, y=1.0; z=2.0) = error()
bt = try
g_collapse_pos_kw(1.0)
catch
catch_backtrace()
end
bt_str = sprint(Base.show_backtrace, bt)
@test occursin("g_collapse_pos_kw(x::Float64, y::Float64; z::Float64)", bt_str)
@test !occursin("g_collapse_pos_kw(x::Float64, y::Float64)", bt_str)
@test !occursin("g_collapse_pos_kw(x::Float64)", bt_str)
63 changes: 33 additions & 30 deletions test/opaque_closure.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using Test
using InteractiveUtils
using Core: OpaqueClosure
using Base.Experimental: @opaque

const_int() = 1

Expand All @@ -12,7 +13,7 @@ let ci = @code_lowered const_int()
Expr(:opaque_closure_method, nothing, 0, false, lno, ci)))
end
end
@test isa(oc_trivial(), Core.OpaqueClosure{Tuple{}, Any})
@test isa(oc_trivial(), OpaqueClosure{Tuple{}, Any})
@test oc_trivial()() == 1

let ci = @code_lowered const_int()
Expand All @@ -21,7 +22,7 @@ let ci = @code_lowered const_int()
Expr(:opaque_closure_method, nothing, 0, false, lno, ci)))
end
end
@test isa(oc_simple_inf(), Core.OpaqueClosure{Tuple{}, Int})
@test isa(oc_simple_inf(), OpaqueClosure{Tuple{}, Int})
@test oc_simple_inf()() == 1

struct OcClos2Int
Expand Down Expand Up @@ -72,8 +73,8 @@ let ci = @code_lowered OcClos1Any(1)()
:x))
end
end
@test isa(oc_infer_pass_clos(1), Core.OpaqueClosure{Tuple{}, typeof(1)})
@test isa(oc_infer_pass_clos("a"), Core.OpaqueClosure{Tuple{}, typeof("a")})
@test isa(oc_infer_pass_clos(1), OpaqueClosure{Tuple{}, typeof(1)})
@test isa(oc_infer_pass_clos("a"), OpaqueClosure{Tuple{}, typeof("a")})
@test oc_infer_pass_clos(1)() == 1
@test oc_infer_pass_clos("a")() == "a"

Expand Down Expand Up @@ -115,8 +116,6 @@ let A = [1 2]
end
end

using Base.Experimental: @opaque

@test @opaque(x->2x)(8) == 16
let f = @opaque (x::Int, y::Float64)->(2x, 3y)
@test_throws TypeError f(1, 1)
Expand All @@ -128,18 +127,26 @@ end
@test uses_frontend_opaque(10)(8) == 18

# World age mechanism
module test_world_age

using Test
using Core: OpaqueClosure
using Base.Experimental: @opaque

function test_oc_world_age end
mk_oc_world_age() = @opaque ()->test_oc_world_age()
g_world_age = @opaque ()->test_oc_world_age()
h_world_age = mk_oc_world_age()
@test isa(h_world_age, Core.OpaqueClosure{Tuple{}, Union{}})
@test isa(h_world_age, OpaqueClosure{Tuple{}, Union{}})
test_oc_world_age() = 1
@test_throws MethodError g_world_age()
@test_throws MethodError h_world_age()
@test mk_oc_world_age()() == 1
g_world_age = @opaque ()->test_oc_world_age()
@test g_world_age() == 1
@test isa(mk_oc_world_age(), Core.OpaqueClosure{Tuple{}, Int})
@test isa(mk_oc_world_age(), OpaqueClosure{Tuple{}, Int})

end # module test_world_age

function maybe_vararg(isva::Bool)
T = isva ? Vararg{Int} : Int
Expand Down Expand Up @@ -196,7 +203,7 @@ end
QuoteNode(Symbol(@__FILE__)),
true)))
end
@test isa(oc_trivial_generated(), Core.OpaqueClosure{Tuple{}, Any})
@test isa(oc_trivial_generated(), OpaqueClosure{Tuple{}, Any})
@test oc_trivial_generated()() == 1

# Constprop through varargs OpaqueClosure
Expand Down Expand Up @@ -242,31 +249,27 @@ let oc = @opaque a->sin(a)
end

# constructing an opaque closure from IRCode
let ci = code_typed(+, (Int, Int))[1][1]
ir = Core.Compiler.inflate_ir(ci)
@test OpaqueClosure(ir; nargs=2, isva=false)(40, 2) == 42
@test OpaqueClosure(ci)(40, 2) == 42

ir = Core.Compiler.inflate_ir(ci)
@test OpaqueClosure(ir; nargs=2, isva=false)(40, 2) == 42
@test isa(OpaqueClosure(ir; nargs=2, isva=false), Core.OpaqueClosure{Tuple{Int, Int}, Int})
@test_throws TypeError OpaqueClosure(ir; nargs=2, isva=false)(40.0, 2)
let src = first(only(code_typed(+, (Int, Int))))
ir = Core.Compiler.inflate_ir(src)
@test OpaqueClosure(src)(40, 2) == 42
oc = OpaqueClosure(ir)
@test oc(40, 2) == 42
@test isa(oc, OpaqueClosure{Tuple{Int,Int}, Int})
@test_throws TypeError oc("40", 2)
@test OpaqueClosure(ir)(40, 2) == 42 # OpaqueClosure constructor should be non-destructive
end

let ci = code_typed((x, y...)->(x, y), (Int, Int))[1][1]
ir = Core.Compiler.inflate_ir(ci)
let oc = OpaqueClosure(ir; nargs=2, isva=true)
@test oc(40, 2) === (40, (2,))
# variadic arguments
let src = code_typed((Int,Int)) do x, y...
return (x, y)
end |> only |> first
let oc = OpaqueClosure(src)
@test oc(1,2) === (1,(2,))
@test_throws MethodError oc(1,2,3)
end
let oc = OpaqueClosure(ci)
@test oc(40, 2) === (40, (2,))
@test_throws MethodError oc(1,2,3)
end

ir = Core.Compiler.inflate_ir(ci)
let oc = OpaqueClosure(ir; nargs=2, isva=true)
@test oc(40, 2) === (40, (2,))
ir = Core.Compiler.inflate_ir(src)
let oc = OpaqueClosure(ir; isva=true)
@test oc(1,2) === (1,(2,))
@test_throws MethodError oc(1,2,3)
end
end