Skip to content

Commit 32a6f54

Browse files
authored
Merge branch 'master' into sort-dispatch
2 parents c633419 + 7116a8b commit 32a6f54

File tree

21 files changed

+416
-231
lines changed

21 files changed

+416
-231
lines changed

CONTRIBUTING.md

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,9 @@ A useful bug report filed as a GitHub issue provides information about how to re
5858

5959
### Writing tests
6060

61-
There are never enough tests. Track [code coverage at Coveralls](https://coveralls.io/r/JuliaLang/julia), and help improve it.
61+
There are never enough tests. Track [code coverage at Codecov](https://codecov.io/github/JuliaLang/julia), and help improve it.
6262

63-
1. Go visit https://coveralls.io/r/JuliaLang/julia.
63+
1. Go visit https://codecov.io/github/JuliaLang/julia.
6464

6565
2. Browse through the source files and find some untested functionality (highlighted in red) that you think you might be able to write a test for.
6666

@@ -74,7 +74,7 @@ There are never enough tests. Track [code coverage at Coveralls](https://coveral
7474
* You can see the current buildbot setup at: https://build.julialang.org/builders
7575
* [Issue 9493](https://github.com/JuliaLang/julia/issues/9493) and [issue 11885](https://github.com/JuliaLang/julia/issues/11885) have more detailed discussion on code coverage.
7676

77-
Coveralls shows functionality that still needs "proof of concept" tests. These are important, as are tests for tricky edge cases, such as converting between integer types when the number to convert is near the maximum of the range of one of the integer types. Even if a function already has some coverage on Coveralls, it may still benefit from tests for edge cases.
77+
Code coverage shows functionality that still needs "proof of concept" tests. These are important, as are tests for tricky edge cases, such as converting between integer types when the number to convert is near the maximum of the range of one of the integer types. Even if a function already has some coverage on Codecov, it may still benefit from tests for edge cases.
7878

7979
### Improving documentation
8080

@@ -340,9 +340,8 @@ please remove the `backport-X.Y` tag from the originating pull request for the c
340340
### Git Recommendations For Pull Requests
341341

342342
- Avoid working from the `master` branch of your fork, creating a new branch will make it easier if Julia's `master` changes and you need to update your pull request.
343-
- Try to [squash](http://gitready.com/advanced/2009/02/10/squashing-commits-with-rebase.html) together small commits that make repeated changes to the same section of code so your pull request is easier to review, and Julia's history won't have any broken intermediate commits. A reasonable number of separate well-factored commits is fine, especially for larger changes.
343+
- Try to [squash](http://gitready.com/advanced/2009/02/10/squashing-commits-with-rebase.html) together small commits that make repeated changes to the same section of code so your pull request is easier to review. A reasonable number of separate well-factored commits is fine, especially for larger changes.
344344
- If any conflicts arise due to changes in Julia's `master`, prefer updating your pull request branch with `git rebase` versus `git merge` or `git pull`, since the latter will introduce merge commits that clutter the git history with noise that makes your changes more difficult to review.
345-
- If you see any unrelated changes to submodules like `deps/libuv`, `deps/openlibm`, etc., try running `git submodule update` first.
346345
- Descriptive commit messages are good.
347346
- Using `git add -p` or `git add -i` can be useful to avoid accidentally committing unrelated changes.
348347
- When linking to specific lines of code in discussion of an issue or pull request, hit the `y` key while viewing code on GitHub to reload the page with a URL that includes the specific version that you're viewing. That way any lines of code that you refer to will still make sense in the future, even if the content of the file changes.
@@ -364,7 +363,7 @@ please remove the `backport-X.Y` tag from the originating pull request for the c
364363
- **Community:** <https://julialang.org/community/>
365364
- **Source code:** <https://github.com/JuliaLang/julia>
366365
- **Documentation:** <https://docs.julialang.org>
367-
- **Code coverage:** <https://coveralls.io/r/JuliaLang/julia>
366+
- **Code coverage:** <https://codecov.io/github/JuliaLang/julia>
368367

369368
* Design of Julia
370369
- [Julia: A Fresh Approach to Numerical Computing](https://julialang.org/assets/research/julia-fresh-approach-BEKS.pdf)

NEWS.md

Lines changed: 136 additions & 90 deletions
Large diffs are not rendered by default.

base/compiler/abstractinterpretation.jl

Lines changed: 70 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,7 @@ struct UnionSplitMethodMatches
272272
fullmatches::Vector{Bool}
273273
nonoverlayed::Bool
274274
end
275-
any_ambig(m::UnionSplitMethodMatches) = _any(any_ambig, m.info.matches)
275+
any_ambig(m::UnionSplitMethodMatches) = any(any_ambig, m.info.matches)
276276

277277
function find_matching_methods(argtypes::Vector{Any}, @nospecialize(atype), method_table::MethodTableView,
278278
union_split::Int, max_methods::Int)
@@ -304,7 +304,7 @@ function find_matching_methods(argtypes::Vector{Any}, @nospecialize(atype), meth
304304
push!(applicable_argtypes, arg_n)
305305
end
306306
valid_worlds = intersect(valid_worlds, matches.valid_worlds)
307-
thisfullmatch = _any(match->(match::MethodMatch).fully_covers, matches)
307+
thisfullmatch = any(match::MethodMatch->match.fully_covers, matches)
308308
found = false
309309
for (i, mt′) in enumerate(mts)
310310
if mt′ === mt
@@ -338,7 +338,7 @@ function find_matching_methods(argtypes::Vector{Any}, @nospecialize(atype), meth
338338
return FailedMethodMatch("Too many methods matched")
339339
end
340340
(; matches, overlayed) = result
341-
fullmatch = _any(match->(match::MethodMatch).fully_covers, matches)
341+
fullmatch = any(match::MethodMatch->match.fully_covers, matches)
342342
return MethodMatches(matches.matches,
343343
MethodMatchInfo(matches),
344344
matches.valid_worlds,
@@ -654,7 +654,7 @@ function edge_matches_sv(frame::InferenceState, method::Method, @nospecialize(si
654654

655655
# check in the cycle list first
656656
# all items in here are mutual parents of all others
657-
if !_any(p::InferenceState->matches_sv(p, sv), frame.callers_in_cycle)
657+
if !any(p::InferenceState->matches_sv(p, sv), frame.callers_in_cycle)
658658
let parent = frame.parent
659659
parent !== nothing || return false
660660
parent = parent::InferenceState
@@ -847,7 +847,7 @@ function concrete_eval_call(interp::AbstractInterpreter,
847847
end
848848
end
849849

850-
has_conditional(argtypes::Vector{Any}) = _any(@nospecialize(x)->isa(x, Conditional), argtypes)
850+
has_conditional(argtypes::Vector{Any}) = any(@nospecialize(x)->isa(x, Conditional), argtypes)
851851
has_conditional((; argtypes)::ArgInfo) = has_conditional(argtypes)
852852

853853
function const_prop_enabled(interp::AbstractInterpreter, sv::InferenceState, match::MethodMatch)
@@ -874,6 +874,69 @@ struct ConstCallResults
874874
new(rt, const_result, effects, edge)
875875
end
876876

877+
struct ConditionalArgtypes <: ForwardableArgtypes
878+
arginfo::ArgInfo
879+
sv::InferenceState
880+
end
881+
882+
"""
883+
matching_cache_argtypes(linfo::MethodInstance, argtypes::ConditionalArgtypes)
884+
885+
The implementation is able to forward `Conditional` of `argtypes`,
886+
as well as the other general extended lattice inforamtion.
887+
"""
888+
function matching_cache_argtypes(linfo::MethodInstance, argtypes::ConditionalArgtypes)
889+
(; arginfo, sv) = argtypes
890+
(; fargs, argtypes) = arginfo
891+
given_argtypes = Vector{Any}(undef, length(argtypes))
892+
def = linfo.def::Method
893+
nargs = Int(def.nargs)
894+
cache_argtypes, overridden_by_const = matching_cache_argtypes(linfo)
895+
local condargs = nothing
896+
for i in 1:length(argtypes)
897+
argtype = argtypes[i]
898+
# forward `Conditional` if it conveys a constraint on any other argument
899+
if isa(argtype, Conditional) && fargs !== nothing
900+
cnd = argtype
901+
slotid = find_constrained_arg(cnd, fargs, sv)
902+
if slotid !== nothing
903+
# using union-split signature, we may be able to narrow down `Conditional`
904+
sigt = widenconst(slotid > nargs ? argtypes[slotid] : cache_argtypes[slotid])
905+
thentype = tmeet(cnd.thentype, sigt)
906+
elsetype = tmeet(cnd.elsetype, sigt)
907+
if thentype === Bottom && elsetype === Bottom
908+
# we accidentally proved this method match is impossible
909+
# TODO bail out here immediately rather than just propagating Bottom ?
910+
given_argtypes[i] = Bottom
911+
else
912+
if condargs === nothing
913+
condargs = Tuple{Int,Int}[]
914+
end
915+
push!(condargs, (slotid, i))
916+
given_argtypes[i] = Conditional(slotid, thentype, elsetype)
917+
end
918+
continue
919+
end
920+
end
921+
given_argtypes[i] = widenconditional(argtype)
922+
end
923+
if condargs !== nothing
924+
given_argtypes = let condargs=condargs
925+
va_process_argtypes(given_argtypes, linfo) do isva_given_argtypes::Vector{Any}, last::Int
926+
# invalidate `Conditional` imposed on varargs
927+
for (slotid, i) in condargs
928+
if slotid last && (1 i length(isva_given_argtypes)) # `Conditional` is already widened to vararg-tuple otherwise
929+
isva_given_argtypes[i] = widenconditional(isva_given_argtypes[i])
930+
end
931+
end
932+
end
933+
end
934+
else
935+
given_argtypes = va_process_argtypes(given_argtypes, linfo)
936+
end
937+
return pick_const_args!(cache_argtypes, overridden_by_const, given_argtypes)
938+
end
939+
877940
function abstract_call_method_with_const_args(interp::AbstractInterpreter,
878941
result::MethodCallResult, @nospecialize(f), arginfo::ArgInfo, si::StmtInfo, match::MethodMatch,
879942
sv::InferenceState, invokecall::Union{Nothing,InvokeCall}=nothing)
@@ -920,7 +983,7 @@ function abstract_call_method_with_const_args(interp::AbstractInterpreter,
920983
add_remark!(interp, sv, "[constprop] Edge cycle encountered")
921984
return nothing
922985
end
923-
inf_result = InferenceResult(mi, (arginfo, sv))
986+
inf_result = InferenceResult(mi, ConditionalArgtypes(arginfo, sv))
924987
if !any(inf_result.overridden_by_const)
925988
add_remark!(interp, sv, "[constprop] Could not handle constant info in matching_cache_argtypes")
926989
return nothing
@@ -1260,7 +1323,7 @@ function precise_container_type(interp::AbstractInterpreter, @nospecialize(itft)
12601323
end
12611324
if isa(tti, Union)
12621325
utis = uniontypes(tti)
1263-
if _any(@nospecialize(t) -> !isa(t, DataType) || !(t <: Tuple) || !isknownlength(t), utis)
1326+
if any(@nospecialize(t) -> !isa(t, DataType) || !(t <: Tuple) || !isknownlength(t), utis)
12641327
return Any[Vararg{Any}], nothing
12651328
end
12661329
ltp = length((utis[1]::DataType).parameters)

base/compiler/inferenceresult.jl

Lines changed: 76 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,73 @@
11
# This file is a part of Julia. License is MIT: https://julialang.org/license
22

3+
"""
4+
matching_cache_argtypes(linfo::MethodInstance) ->
5+
(cache_argtypes::Vector{Any}, overridden_by_const::BitVector)
6+
7+
Returns argument types `cache_argtypes::Vector{Any}` for `linfo` that are in the native
8+
Julia type domain. `overridden_by_const::BitVector` is all `false` meaning that
9+
there is no additional extended lattice information there.
10+
11+
matching_cache_argtypes(linfo::MethodInstance, argtypes::ForwardableArgtypes) ->
12+
(cache_argtypes::Vector{Any}, overridden_by_const::BitVector)
13+
14+
Returns cache-correct extended lattice argument types `cache_argtypes::Vector{Any}`
15+
for `linfo` given some `argtypes` accompanied by `overridden_by_const::BitVector`
16+
that marks which argument contains additional extended lattice information.
17+
18+
In theory, there could be a `cache` containing a matching `InferenceResult`
19+
for the provided `linfo` and `given_argtypes`. The purpose of this function is
20+
to return a valid value for `cache_lookup(𝕃, linfo, argtypes, cache).argtypes`,
21+
so that we can construct cache-correct `InferenceResult`s in the first place.
22+
"""
23+
function matching_cache_argtypes end
24+
25+
function matching_cache_argtypes(linfo::MethodInstance)
26+
mthd = isa(linfo.def, Method) ? linfo.def::Method : nothing
27+
cache_argtypes = most_general_argtypes(mthd, linfo.specTypes)
28+
return cache_argtypes, falses(length(cache_argtypes))
29+
end
30+
31+
struct SimpleArgtypes
32+
argtypes::Vector{Any}
33+
end
34+
35+
"""
36+
matching_cache_argtypes(linfo::MethodInstance, argtypes::SimpleArgtypes)
37+
38+
The implementation for `argtypes` with general extended lattice information.
39+
This is supposed to be used for debugging and testing or external `AbstractInterpreter`
40+
usages and in general `matching_cache_argtypes(::MethodInstance, ::ConditionalArgtypes)`
41+
is more preferred it can forward `Conditional` information.
42+
"""
43+
function matching_cache_argtypes(linfo::MethodInstance, simple_argtypes::SimpleArgtypes)
44+
(; argtypes) = simple_argtypes
45+
given_argtypes = Vector{Any}(undef, length(argtypes))
46+
for i = 1:length(argtypes)
47+
given_argtypes[i] = widenconditional(argtypes[i])
48+
end
49+
given_argtypes = va_process_argtypes(given_argtypes, linfo)
50+
return pick_const_args(linfo, given_argtypes)
51+
end
52+
53+
function pick_const_args(linfo::MethodInstance, given_argtypes::Vector{Any})
54+
cache_argtypes, overridden_by_const = matching_cache_argtypes(linfo)
55+
return pick_const_args!(cache_argtypes, overridden_by_const, given_argtypes)
56+
end
57+
58+
function pick_const_args!(cache_argtypes::Vector{Any}, overridden_by_const::BitVector, given_argtypes::Vector{Any})
59+
for i = 1:length(given_argtypes)
60+
given_argtype = given_argtypes[i]
61+
cache_argtype = cache_argtypes[i]
62+
if !is_argtype_match(fallback_lattice, given_argtype, cache_argtype, false)
63+
# prefer the argtype we were given over the one computed from `linfo`
64+
cache_argtypes[i] = given_argtype
65+
overridden_by_const[i] = true
66+
end
67+
end
68+
return cache_argtypes, overridden_by_const
69+
end
70+
371
function is_argtype_match(lattice::AbstractLattice,
472
@nospecialize(given_argtype),
573
@nospecialize(cache_argtype),
@@ -17,10 +85,12 @@ function is_forwardable_argtype(@nospecialize x)
1785
isa(x, PartialOpaque)
1886
end
1987

20-
function va_process_argtypes(given_argtypes::Vector{Any}, mi::MethodInstance,
21-
condargs::Union{Vector{Tuple{Int,Int}}, Nothing}=nothing)
22-
isva = mi.def.isva
23-
nargs = Int(mi.def.nargs)
88+
va_process_argtypes(given_argtypes::Vector{Any}, linfo::MethodInstance) =
89+
va_process_argtypes(Returns(nothing), given_argtypes, linfo)
90+
function va_process_argtypes(@nospecialize(va_handler!), given_argtypes::Vector{Any}, linfo::MethodInstance)
91+
def = linfo.def::Method
92+
isva = def.isva
93+
nargs = Int(def.nargs)
2494
if isva || isvarargtype(given_argtypes[end])
2595
isva_given_argtypes = Vector{Any}(undef, nargs)
2696
for i = 1:(nargs - isva)
@@ -33,74 +103,14 @@ function va_process_argtypes(given_argtypes::Vector{Any}, mi::MethodInstance,
33103
last = nargs
34104
end
35105
isva_given_argtypes[nargs] = tuple_tfunc(given_argtypes[last:end])
36-
# invalidate `Conditional` imposed on varargs
37-
if condargs !== nothing
38-
for (slotid, i) in condargs
39-
if slotid last && (1 i length(isva_given_argtypes)) # `Conditional` is already widened to vararg-tuple otherwise
40-
isva_given_argtypes[i] = widenconditional(isva_given_argtypes[i])
41-
end
42-
end
43-
end
106+
va_handler!(isva_given_argtypes, last)
44107
end
45108
return isva_given_argtypes
46109
end
110+
@assert length(given_argtypes) == nargs "invalid `given_argtypes` for `linfo`"
47111
return given_argtypes
48112
end
49113

50-
# In theory, there could be a `cache` containing a matching `InferenceResult`
51-
# for the provided `linfo` and `given_argtypes`. The purpose of this function is
52-
# to return a valid value for `cache_lookup(linfo, argtypes, cache).argtypes`,
53-
# so that we can construct cache-correct `InferenceResult`s in the first place.
54-
function matching_cache_argtypes(
55-
linfo::MethodInstance, (arginfo, sv)#=::Tuple{ArgInfo,InferenceState}=#)
56-
(; fargs, argtypes) = arginfo
57-
def = linfo.def
58-
@assert isa(def, Method) # ensure the next line works
59-
nargs::Int = def.nargs
60-
cache_argtypes, overridden_by_const = matching_cache_argtypes(linfo, nothing)
61-
given_argtypes = Vector{Any}(undef, length(argtypes))
62-
local condargs = nothing
63-
for i in 1:length(argtypes)
64-
argtype = argtypes[i]
65-
# forward `Conditional` if it conveys a constraint on any other argument
66-
if isa(argtype, Conditional) && fargs !== nothing
67-
cnd = argtype
68-
slotid = find_constrained_arg(cnd, fargs, sv)
69-
if slotid !== nothing
70-
# using union-split signature, we may be able to narrow down `Conditional`
71-
sigt = widenconst(slotid > nargs ? argtypes[slotid] : cache_argtypes[slotid])
72-
thentype = tmeet(cnd.thentype, sigt)
73-
elsetype = tmeet(cnd.elsetype, sigt)
74-
if thentype === Bottom && elsetype === Bottom
75-
# we accidentally proved this method match is impossible
76-
# TODO bail out here immediately rather than just propagating Bottom ?
77-
given_argtypes[i] = Bottom
78-
else
79-
if condargs === nothing
80-
condargs = Tuple{Int,Int}[]
81-
end
82-
push!(condargs, (slotid, i))
83-
given_argtypes[i] = Conditional(slotid, thentype, elsetype)
84-
end
85-
continue
86-
end
87-
end
88-
given_argtypes[i] = widenconditional(argtype)
89-
end
90-
given_argtypes = va_process_argtypes(given_argtypes, linfo, condargs)
91-
@assert length(given_argtypes) == nargs
92-
for i in 1:nargs
93-
given_argtype = given_argtypes[i]
94-
cache_argtype = cache_argtypes[i]
95-
if !is_argtype_match(fallback_lattice, given_argtype, cache_argtype, false)
96-
# prefer the argtype we were given over the one computed from `linfo`
97-
cache_argtypes[i] = given_argtype
98-
overridden_by_const[i] = true
99-
end
100-
end
101-
return cache_argtypes, overridden_by_const
102-
end
103-
104114
function most_general_argtypes(method::Union{Method, Nothing}, @nospecialize(specTypes),
105115
withfirst::Bool = true)
106116
toplevel = method === nothing
@@ -202,12 +212,6 @@ function elim_free_typevars(@nospecialize t)
202212
end
203213
end
204214

205-
function matching_cache_argtypes(linfo::MethodInstance, ::Nothing)
206-
mthd = isa(linfo.def, Method) ? linfo.def::Method : nothing
207-
cache_argtypes = most_general_argtypes(mthd, linfo.specTypes)
208-
return cache_argtypes, falses(length(cache_argtypes))
209-
end
210-
211215
function cache_lookup(lattice::AbstractLattice, linfo::MethodInstance, given_argtypes::Vector{Any}, cache::Vector{InferenceResult})
212216
method = linfo.def::Method
213217
nargs::Int = method.nargs

base/compiler/inferencestate.jl

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -228,12 +228,6 @@ end
228228
is_effect_overridden(method::Method, effect::Symbol) = is_effect_overridden(decode_effects_override(method.purity), effect)
229229
is_effect_overridden(override::EffectsOverride, effect::Symbol) = getfield(override, effect)
230230

231-
function InferenceResult(
232-
linfo::MethodInstance,
233-
arginfo::Union{Nothing,Tuple{ArgInfo,InferenceState}} = nothing)
234-
return _InferenceResult(linfo, arginfo)
235-
end
236-
237231
add_remark!(::AbstractInterpreter, sv::Union{InferenceState, IRCode}, remark) = return
238232

239233
function bail_out_toplevel_call(::AbstractInterpreter, @nospecialize(callsig), sv::Union{InferenceState, IRCode})

base/compiler/ssair/legacy.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ the original `ci::CodeInfo` are modified.
1111
function inflate_ir!(ci::CodeInfo, linfo::MethodInstance)
1212
sptypes = sptypes_from_meth_instance(linfo)
1313
if ci.inferred
14-
argtypes, _ = matching_cache_argtypes(linfo, nothing)
14+
argtypes, _ = matching_cache_argtypes(linfo)
1515
else
1616
argtypes = Any[ Any for i = 1:length(ci.slotflags) ]
1717
end

0 commit comments

Comments
 (0)