Skip to content

Commit 5306e2d

Browse files
authored
Merge branch 'JuliaLang:master' into master
2 parents fd6d832 + 60be409 commit 5306e2d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

78 files changed

+2410
-1078
lines changed

base/compiler/abstractinterpretation.jl

+36-32
Original file line numberDiff line numberDiff line change
@@ -280,17 +280,41 @@ any_ambig(info::MethodMatchInfo) = any_ambig(info.results)
280280
any_ambig(m::MethodMatches) = any_ambig(m.info)
281281
fully_covering(info::MethodMatchInfo) = info.fullmatch
282282
fully_covering(m::MethodMatches) = fully_covering(m.info)
283+
function add_uncovered_edges!(sv::AbsIntState, info::MethodMatchInfo, @nospecialize(atype))
284+
fully_covering(info) || add_mt_backedge!(sv, info.mt, atype)
285+
nothing
286+
end
287+
add_uncovered_edges!(sv::AbsIntState, matches::MethodMatches, @nospecialize(atype)) =
288+
add_uncovered_edges!(sv, matches.info, atype)
283289

284290
struct UnionSplitMethodMatches
285291
applicable::Vector{Any}
286292
applicable_argtypes::Vector{Vector{Any}}
287293
info::UnionSplitInfo
288294
valid_worlds::WorldRange
289295
end
290-
any_ambig(info::UnionSplitInfo) = any(any_ambig, info.matches)
296+
any_ambig(info::UnionSplitInfo) = any(any_ambig, info.split)
291297
any_ambig(m::UnionSplitMethodMatches) = any_ambig(m.info)
292-
fully_covering(info::UnionSplitInfo) = all(info.fullmatches)
298+
fully_covering(info::UnionSplitInfo) = all(fully_covering, info.split)
293299
fully_covering(m::UnionSplitMethodMatches) = fully_covering(m.info)
300+
function add_uncovered_edges!(sv::AbsIntState, info::UnionSplitInfo, @nospecialize(atype))
301+
all(fully_covering, info.split) && return nothing
302+
# add mt backedges with removing duplications
303+
for mt in uncovered_method_tables(info)
304+
add_mt_backedge!(sv, mt, atype)
305+
end
306+
end
307+
add_uncovered_edges!(sv::AbsIntState, matches::UnionSplitMethodMatches, @nospecialize(atype)) =
308+
add_uncovered_edges!(sv, matches.info, atype)
309+
function uncovered_method_tables(info::UnionSplitInfo)
310+
mts = MethodTable[]
311+
for mminfo in info.split
312+
fully_covering(mminfo) && continue
313+
any(mt′::MethodTable->mt′===mminfo.mt, mts) && continue
314+
push!(mts, mminfo.mt)
315+
end
316+
return mts
317+
end
294318

295319
function find_method_matches(interp::AbstractInterpreter, argtypes::Vector{Any}, @nospecialize(atype);
296320
max_union_splitting::Int = InferenceParams(interp).max_union_splitting,
@@ -308,43 +332,30 @@ is_union_split_eligible(𝕃::AbstractLattice, argtypes::Vector{Any}, max_union_
308332
function find_union_split_method_matches(interp::AbstractInterpreter, argtypes::Vector{Any},
309333
@nospecialize(atype), max_methods::Int)
310334
split_argtypes = switchtupleunion(typeinf_lattice(interp), argtypes)
311-
infos = MethodLookupResult[]
335+
infos = MethodMatchInfo[]
312336
applicable = Any[]
313337
applicable_argtypes = Vector{Any}[] # arrays like `argtypes`, including constants, for each match
314338
valid_worlds = WorldRange()
315-
mts = MethodTable[]
316-
fullmatches = Bool[]
317339
for i in 1:length(split_argtypes)
318340
arg_n = split_argtypes[i]::Vector{Any}
319341
sig_n = argtypes_to_type(arg_n)
320342
mt = ccall(:jl_method_table_for, Any, (Any,), sig_n)
321343
mt === nothing && return FailedMethodMatch("Could not identify method table for call")
322344
mt = mt::MethodTable
323-
matches = findall(sig_n, method_table(interp); limit = max_methods)
324-
if matches === nothing
345+
thismatches = findall(sig_n, method_table(interp); limit = max_methods)
346+
if thismatches === nothing
325347
return FailedMethodMatch("For one of the union split cases, too many methods matched")
326348
end
327-
push!(infos, matches)
328-
for m in matches
349+
for m in thismatches
329350
push!(applicable, m)
330351
push!(applicable_argtypes, arg_n)
331352
end
332-
valid_worlds = intersect(valid_worlds, matches.valid_worlds)
333-
thisfullmatch = any(match::MethodMatch->match.fully_covers, matches)
334-
mt_found = false
335-
for (i, mt′) in enumerate(mts)
336-
if mt′ === mt
337-
fullmatches[i] &= thisfullmatch
338-
mt_found = true
339-
break
340-
end
341-
end
342-
if !mt_found
343-
push!(mts, mt)
344-
push!(fullmatches, thisfullmatch)
345-
end
353+
valid_worlds = intersect(valid_worlds, thismatches.valid_worlds)
354+
thisfullmatch = any(match::MethodMatch->match.fully_covers, thismatches)
355+
thisinfo = MethodMatchInfo(thismatches, mt, thisfullmatch)
356+
push!(infos, thisinfo)
346357
end
347-
info = UnionSplitInfo(infos, mts, fullmatches)
358+
info = UnionSplitInfo(infos)
348359
return UnionSplitMethodMatches(
349360
applicable, applicable_argtypes, info, valid_worlds)
350361
end
@@ -583,14 +594,7 @@ function add_call_backedges!(interp::AbstractInterpreter, @nospecialize(rettype)
583594
end
584595
# also need an edge to the method table in case something gets
585596
# added that did not intersect with any existing method
586-
if isa(matches, MethodMatches)
587-
fully_covering(matches) || add_mt_backedge!(sv, matches.info.mt, atype)
588-
else
589-
matches::UnionSplitMethodMatches
590-
for (thisfullmatch, mt) in zip(matches.info.fullmatches, matches.info.mts)
591-
thisfullmatch || add_mt_backedge!(sv, mt, atype)
592-
end
593-
end
597+
add_uncovered_edges!(sv, matches, atype)
594598
return nothing
595599
end
596600

base/compiler/optimize.jl

+4-2
Original file line numberDiff line numberDiff line change
@@ -702,6 +702,8 @@ function check_all_args_noescape!(sv::PostOptAnalysisState, ir::IRCode, @nospeci
702702
else
703703
return false
704704
end
705+
has_no_escape(x::EscapeAnalysis.EscapeInfo) =
706+
EscapeAnalysis.has_no_escape(EscapeAnalysis.ignore_argescape(x))
705707
for i = startidx:length(stmt.args)
706708
arg = stmt.args[i]
707709
argt = argextype(arg, ir)
@@ -710,7 +712,7 @@ function check_all_args_noescape!(sv::PostOptAnalysisState, ir::IRCode, @nospeci
710712
end
711713
# See if we can find the allocation
712714
if isa(arg, Argument)
713-
if EscapeAnalysis.has_no_escape(EscapeAnalysis.ignore_argescape(estate[arg]))
715+
if has_no_escape(estate[arg])
714716
# Even if we prove everything else effect_free, the best we can
715717
# say is :effect_free_if_argmem_only
716718
if sv.effect_free_if_argmem_only === nothing
@@ -721,7 +723,7 @@ function check_all_args_noescape!(sv::PostOptAnalysisState, ir::IRCode, @nospeci
721723
end
722724
return false
723725
elseif isa(arg, SSAValue)
724-
EscapeAnalysis.has_no_escape(estate[arg]) || return false
726+
has_no_escape(estate[arg]) || return false
725727
check_all_args_noescape!(sv, ir, ir[arg][:stmt], estate) || return false
726728
else
727729
return false

base/compiler/stmtinfo.jl

+13-10
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,10 @@ end
3939
nsplit_impl(info::MethodMatchInfo) = 1
4040
getsplit_impl(info::MethodMatchInfo, idx::Int) = (@assert idx == 1; info.results)
4141
getresult_impl(::MethodMatchInfo, ::Int) = nothing
42-
add_uncovered_edges_impl(edges::Vector{Any}, info::MethodMatchInfo, @nospecialize(atype)) = (!info.fullmatch && push!(edges, info.mt, atype); )
42+
function add_uncovered_edges_impl(edges::Vector{Any}, info::MethodMatchInfo, @nospecialize(atype))
43+
fully_covering(info) || push!(edges, info.mt, atype)
44+
nothing
45+
end
4346

4447
"""
4548
info::UnionSplitInfo <: CallInfo
@@ -51,25 +54,25 @@ each partition (`info.matches::Vector{MethodMatchInfo}`).
5154
This info is illegal on any statement that is not a call to a generic function.
5255
"""
5356
struct UnionSplitInfo <: CallInfo
54-
matches::Vector{MethodLookupResult}
55-
mts::Vector{MethodTable}
56-
fullmatches::Vector{Bool}
57+
split::Vector{MethodMatchInfo}
5758
end
5859

5960
nmatches(info::MethodMatchInfo) = length(info.results)
6061
function nmatches(info::UnionSplitInfo)
6162
n = 0
62-
for mminfo in info.matches
63-
n += length(mminfo)
63+
for mminfo in info.split
64+
n += nmatches(mminfo)
6465
end
6566
return n
6667
end
67-
nsplit_impl(info::UnionSplitInfo) = length(info.matches)
68-
getsplit_impl(info::UnionSplitInfo, idx::Int) = info.matches[idx]
68+
nsplit_impl(info::UnionSplitInfo) = length(info.split)
69+
getsplit_impl(info::UnionSplitInfo, idx::Int) = getsplit(info.split[idx], 1)
6970
getresult_impl(::UnionSplitInfo, ::Int) = nothing
7071
function add_uncovered_edges_impl(edges::Vector{Any}, info::UnionSplitInfo, @nospecialize(atype))
71-
for (mt, fullmatch) in zip(info.mts, info.fullmatches)
72-
!fullmatch && push!(edges, mt, atype)
72+
all(fully_covering, info.split) && return nothing
73+
# add mt backedges with removing duplications
74+
for mt in uncovered_method_tables(info)
75+
push!(edges, mt, atype)
7376
end
7477
end
7578

base/compiler/tfuncs.jl

+11-21
Original file line numberDiff line numberDiff line change
@@ -2979,33 +2979,23 @@ function abstract_applicable(interp::AbstractInterpreter, argtypes::Vector{Any},
29792979
else
29802980
(; valid_worlds, applicable) = matches
29812981
update_valid_age!(sv, valid_worlds)
2982-
2983-
# also need an edge to the method table in case something gets
2984-
# added that did not intersect with any existing method
2985-
if isa(matches, MethodMatches)
2986-
fully_covering(matches) || add_mt_backedge!(sv, matches.info.mt, atype)
2987-
else
2988-
for (thisfullmatch, mt) in zip(matches.info.fullmatches, matches.info.mts)
2989-
thisfullmatch || add_mt_backedge!(sv, mt, atype)
2990-
end
2991-
end
2992-
29932982
napplicable = length(applicable)
29942983
if napplicable == 0
29952984
rt = Const(false) # never any matches
2985+
elseif !fully_covering(matches) || any_ambig(matches)
2986+
# Account for the fact that we may encounter a MethodError with a non-covered or ambiguous signature.
2987+
rt = Bool
29962988
else
29972989
rt = Const(true) # has applicable matches
2998-
for i in 1:napplicable
2999-
match = applicable[i]::MethodMatch
3000-
edge = specialize_method(match)::MethodInstance
3001-
add_backedge!(sv, edge)
3002-
end
3003-
3004-
if !fully_covering(matches) || any_ambig(matches)
3005-
# Account for the fact that we may encounter a MethodError with a non-covered or ambiguous signature.
3006-
rt = Bool
3007-
end
30082990
end
2991+
for i in 1:napplicable
2992+
match = applicable[i]::MethodMatch
2993+
edge = specialize_method(match)::MethodInstance
2994+
add_backedge!(sv, edge)
2995+
end
2996+
# also need an edge to the method table in case something gets
2997+
# added that did not intersect with any existing method
2998+
add_uncovered_edges!(sv, matches, atype)
30092999
end
30103000
return CallMeta(rt, Union{}, EFFECTS_TOTAL, NoCallInfo())
30113001
end

base/compiler/types.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -457,7 +457,7 @@ getresult(info::CallInfo, idx::Int) = getresult_impl(info, idx)
457457
# must implement `nsplit`, `getsplit`, and `add_uncovered_edges!` to opt in to inlining
458458
nsplit_impl(::CallInfo) = nothing
459459
getsplit_impl(::CallInfo, ::Int) = error("unexpected call into `getsplit`")
460-
add_uncovered_edges_impl(edges::Vector{Any}, info::CallInfo, @nospecialize(atype)) = error("unexpected call into `add_uncovered_edges!`")
460+
add_uncovered_edges_impl(::Vector{Any}, ::CallInfo, _) = error("unexpected call into `add_uncovered_edges!`")
461461

462462
# must implement `getresult` to opt in to extended lattice return information
463463
getresult_impl(::CallInfo, ::Int) = nothing

base/docs/Docs.jl

+4
Original file line numberDiff line numberDiff line change
@@ -577,6 +577,10 @@ function _doc(binding::Binding, sig::Type = Union{})
577577
for msig in multidoc.order
578578
sig <: msig && return multidoc.docs[msig]
579579
end
580+
# if no matching signatures, return first
581+
if !isempty(multidoc.docs)
582+
return first(values(multidoc.docs))
583+
end
580584
end
581585
end
582586
return nothing

base/docs/basedocs.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -1694,7 +1694,7 @@ julia> ab = AB(1, 3)
16941694
AB(1.0f0, 3.0)
16951695
16961696
julia> ab.c # field `c` doesn't exist
1697-
ERROR: FieldError: type AB has no field c
1697+
ERROR: FieldError: type AB has no field `c`, available fields: `a`, `b`
16981698
Stacktrace:
16991699
[...]
17001700
```

base/errorshow.jl

+28-3
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,7 @@ end
378378

379379
function showerror(io::IO, exc::FieldError)
380380
@nospecialize
381-
print(io, "FieldError: type $(exc.type |> nameof) has no field $(exc.field)")
381+
print(io, "FieldError: type $(exc.type |> nameof) has no field `$(exc.field)`")
382382
Base.Experimental.show_error_hints(io, exc)
383383
end
384384

@@ -1102,7 +1102,7 @@ end
11021102
Experimental.register_error_hint(methods_on_iterable, MethodError)
11031103

11041104
# Display a hint in case the user tries to access non-member fields of container type datastructures
1105-
function fielderror_hint_handler(io, exc)
1105+
function fielderror_dict_hint_handler(io, exc)
11061106
@nospecialize
11071107
field = exc.field
11081108
type = exc.type
@@ -1113,7 +1113,32 @@ function fielderror_hint_handler(io, exc)
11131113
end
11141114
end
11151115

1116-
Experimental.register_error_hint(fielderror_hint_handler, FieldError)
1116+
Experimental.register_error_hint(fielderror_dict_hint_handler, FieldError)
1117+
1118+
function fielderror_listfields_hint_handler(io, exc)
1119+
fields = fieldnames(exc.type)
1120+
if isempty(fields)
1121+
print(io, "; $(nameof(exc.type)) has no fields at all.")
1122+
else
1123+
print(io, ", available fields: $(join(map(k -> "`$k`", fields), ", "))")
1124+
end
1125+
props = _propertynames_bytype(exc.type)
1126+
isnothing(props) && return
1127+
props = setdiff(props, fields)
1128+
isempty(props) && return
1129+
print(io, "\nAvailable properties: $(join(map(k -> "`$k`", props), ", "))")
1130+
end
1131+
1132+
function _propertynames_bytype(T::Type)
1133+
which(propertynames, (T,)) === which(propertynames, (Any,)) && return nothing
1134+
inferred_names = promote_op(Valpropertynames, T)
1135+
inferred_names isa DataType && inferred_names <: Val || return nothing
1136+
inferred_names = inferred_names.parameters[1]
1137+
inferred_names isa NTuple{<:Any, Symbol} || return nothing
1138+
return Symbol[inferred_names[i] for i in 1:length(inferred_names)]
1139+
end
1140+
1141+
Experimental.register_error_hint(fielderror_listfields_hint_handler, FieldError)
11171142

11181143
# ExceptionStack implementation
11191144
size(s::ExceptionStack) = size(s.stack)

base/floatfuncs.jl

+3-1
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,9 @@ function isapprox(x::Integer, y::Integer;
232232
if norm === abs && atol < 1 && rtol == 0
233233
return x == y
234234
else
235-
return norm(x - y) <= max(atol, rtol*max(norm(x), norm(y)))
235+
# We need to take the difference `max` - `min` when comparing unsigned integers.
236+
_x, _y = x < y ? (x, y) : (y, x)
237+
return norm(_y - _x) <= max(atol, rtol*max(norm(_x), norm(_y)))
236238
end
237239
end
238240

base/iostream.jl

+2-2
Original file line numberDiff line numberDiff line change
@@ -230,8 +230,8 @@ end
230230
function filesize(s::IOStream)
231231
sz = @_lock_ios s ccall(:ios_filesize, Int64, (Ptr{Cvoid},), s.ios)
232232
if sz == -1
233-
err = Libc.errno()
234-
throw(IOError(string("filesize: ", Libc.strerror(err), " for ", s.name), err))
233+
# if `s` is not seekable `ios_filesize` can fail, so fall back to slower stat method
234+
sz = filesize(stat(s))
235235
end
236236
return sz
237237
end

0 commit comments

Comments
 (0)