Skip to content

Commit

Permalink
Merge branch 'master' into cjf/exception-stack
Browse files Browse the repository at this point in the history
  • Loading branch information
vchuravy committed Oct 22, 2018
2 parents 1eaf27a + c162219 commit 3577e33
Show file tree
Hide file tree
Showing 76 changed files with 675 additions and 296 deletions.
20 changes: 16 additions & 4 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,29 @@ Julia v1.1.0 Release Notes
New language features
---------------------

* `CartesianIndices` can now be constructed from two `CartesianIndex`es `I` and `J` with `I:J` ([#29440]).
* An *exception stack* is maintained on each task to make exception handling more robust and enable root cause analysis using `catch_stack` ([#28878]).
* `isnothing(::Any)` function can now be called to check whether something is a `Nothing`, returns a `Bool` ([#29679])


Language changes
----------------

Standard Library Changes
* Parser inputs ending with a comma are now consistently treated as incomplete.
Previously they were sometimes parsed as tuples, depending on whitespace ([#28506]).

New library functions
---------------------

* `splitpath(p::String)` function, which is the opposite of `joinpath(parts...)`: it splits a filepath into its components ([#28156]).
* `isnothing(::Any)` function, to check whether something is a `Nothing`, returns a `Bool` ([#29679]).

Standard library changes
------------------------

* New `splitpath(p::String)` function added, which is the opposite of `joinpath(parts...)`: it splits a filepath into its components ([#28156]).
* `CartesianIndices` can now be constructed from two `CartesianIndex`es `I` and `J` with `I:J` ([#29440]).
* `copy!` support for arrays, dicts, and sets has been moved to Base from the Future package ([#29173]).
* Channels now convert inserted values (like containers) instead of requiring types to match ([#29092]).
* `range` can accept the stop value as a positional argument, e.g. `range(1,10,step=2)` ([#28708]).
* `edit` can now be called on a module to edit the file that defines it ([#29636]).

Compiler/Runtime improvements
-----------------------------
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,8 @@ When building Julia, or its dependencies, libraries installed by third party pac
### FreeBSD

Clang is the default compiler on FreeBSD 11.0-RELEASE and above.
The remaining build tools are available from the Ports Collection, and can be installed using `pkg install git gcc gmake cmake`.
The remaining build tools are available from the Ports Collection, and can be installed using
`pkg install git gcc gmake cmake pkgconf`.
To build Julia, simply run `gmake`.
(Note that `gmake` must be used rather than `make`, since `make` on FreeBSD corresponds to the incompatible BSD Make rather than GNU Make.)

Expand Down
18 changes: 18 additions & 0 deletions base/abstractarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -638,6 +638,24 @@ empty(a::AbstractVector{T}, ::Type{U}=T) where {T,U} = Vector{U}()
emptymutable(a::AbstractVector{T}, ::Type{U}=T) where {T,U} = Vector{U}()
emptymutable(itr, ::Type{U}) where {U} = Vector{U}()

"""
copy!(dst, src) -> dst
In-place [`copy`](@ref) of `src` into `dst`, discarding any pre-existing
elements in `dst`.
If `dst` and `src` are of the same type, `dst == src` should hold after
the call. If `dst` and `src` are multidimensional arrays, they must have
equal [`axes`](@ref).
See also [`copyto!`](@ref).
"""
copy!(dst::AbstractVector, src::AbstractVector) = append!(empty!(dst), src)

function copy!(dst::AbstractArray, src::AbstractArray)
axes(dst) == axes(src) || throw(ArgumentError(
"arrays must have the same axes for copy! (consider using `copyto!`)"))
copyto!(dst, src)
end

## from general iterable to any array

function copyto!(dest::AbstractArray, src)
Expand Down
15 changes: 6 additions & 9 deletions base/abstractdict.jl
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,10 @@ struct ValueIterator{T<:AbstractDict}
dict::T
end

summary(iter::T) where {T<:Union{KeySet,ValueIterator}} =
string(T.name, " for a ", summary(iter.dict))
function summary(io::IO, iter::T) where {T<:Union{KeySet,ValueIterator}}
print(io, T.name, " for a ")
summary(io, iter.dict)
end

show(io::IO, iter::Union{KeySet,ValueIterator}) = show_vector(io, iter)

Expand Down Expand Up @@ -146,13 +148,8 @@ The default is to return an empty `Dict`.
empty(a::AbstractDict) = empty(a, keytype(a), valtype(a))
empty(a::AbstractDict, ::Type{V}) where {V} = empty(a, keytype(a), V) # Note: this is the form which makes sense for `Vector`.

function copy(a::AbstractDict)
b = empty(a)
for (k,v) in a
b[k] = v
end
return b
end
copy(a::AbstractDict) = merge!(empty(a), a)
copy!(dst::AbstractDict, src::AbstractDict) = merge!(empty!(dst), src)

"""
merge!(d::AbstractDict, others::AbstractDict...)
Expand Down
2 changes: 2 additions & 0 deletions base/abstractset.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
eltype(::Type{<:AbstractSet{T}}) where {T} = @isdefined(T) ? T : Any
sizehint!(s::AbstractSet, n) = nothing

copy!(dst::AbstractSet, src::AbstractSet) = union!(empty!(dst), src)

"""
union(s, itrs...)
∪(s, itrs...)
Expand Down
2 changes: 1 addition & 1 deletion base/arrayshow.jl
Original file line number Diff line number Diff line change
Expand Up @@ -410,7 +410,7 @@ _show_nonempty(::IO, ::AbstractVector, ::String) =
_show_nonempty(io::IO, X::AbstractArray{T,0} where T, prefix::String) = print_array(io, X)

# NOTE: it's not clear how this method could use the :typeinfo attribute
_show_empty(io::IO, X::Array{T}) where {T} = print(io, "Array{$T}(", join(size(X),','), ')')
_show_empty(io::IO, X::Array{T}) where {T} = print(io, "Array{", T, "}(", join(size(X),','), ')')
_show_empty(io, X) = nothing # by default, we don't know this constructor

# typeinfo aware (necessarily)
Expand Down
8 changes: 0 additions & 8 deletions base/bitset.jl
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,6 @@ emptymutable(s::BitSet, ::Type{Int}=Int) = BitSet()
copy(s1::BitSet) = copy!(BitSet(), s1)
copymutable(s::BitSet) = copy(s)

"""
copy!(dst, src)
In-place [`copy`](@ref) of `src` into `dst`. After the call to `copy!`,
`dst` must be left equal to `src`, otherwise an error is thrown; this
function appropriately resizes `dst` if necessary.
See also [`copyto!`](@ref).
"""
function copy!(dest::BitSet, src::BitSet)
resize!(dest.bits, length(src.bits))
copyto!(dest.bits, src.bits)
Expand Down
3 changes: 2 additions & 1 deletion base/channels.jl
Original file line number Diff line number Diff line change
Expand Up @@ -246,8 +246,9 @@ Append an item `v` to the channel `c`. Blocks if the channel is full.
For unbuffered channels, blocks until a [`take!`](@ref) is performed by a different
task.
"""
function put!(c::Channel, v)
function put!(c::Channel{T}, v) where T
check_channel_state(c)
v = convert(T, v)
isbuffered(c) ? put_buffered(c,v) : put_unbuffered(c,v)
end

Expand Down
2 changes: 1 addition & 1 deletion base/compiler/compiler.jl
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ include("abstractdict.jl")
include("abstractset.jl")
include("iterators.jl")
using .Iterators: zip, enumerate
using .Iterators: Flatten, product # for generators
using .Iterators: Flatten, Filter, product # for generators
include("namedtuple.jl")

# core docsystem
Expand Down
40 changes: 21 additions & 19 deletions base/errorshow.jl
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ function showerror(io::IO, ex::BoundsError)
if isdefined(ex, :a)
print(io, ": attempt to access ")
if isa(ex.a, AbstractArray)
print(io, summary(ex.a))
summary(io, ex.a)
else
show(io, MIME"text/plain"(), ex.a)
end
Expand All @@ -54,19 +54,19 @@ end
function showerror(io::IO, ex::TypeError)
print(io, "TypeError: ")
if ex.expected === Bool
print(io, "non-boolean ($(typeof(ex.got))) used in boolean context")
print(io, "non-boolean (", typeof(ex.got), ") used in boolean context")
else
if isa(ex.got, Type)
tstr = "Type{$(ex.got)}"
targs = ("Type{", ex.got, "}")
else
tstr = string(typeof(ex.got))
targs = (typeof(ex.got),)
end
if isempty(ex.context)
ctx = "in $(ex.func)"
else
ctx = "in $(ex.func), in $(ex.context)"
end
print(io, ctx, ", expected $(ex.expected), got ", tstr)
print(io, ctx, ", expected ", ex.expected, ", got ", targs...)
end
end

Expand All @@ -90,7 +90,7 @@ showerror(io::IO, ex::LoadError) = showerror(io, ex, [])
function showerror(io::IO, ex::InitError, bt; backtrace=true)
print(io, "InitError: ")
showerror(io, ex.error, bt, backtrace=backtrace)
print(io, "\nduring initialization of module $(ex.mod)")
print(io, "\nduring initialization of module ", ex.mod)
end
showerror(io::IO, ex::InitError) = showerror(io, ex, [])

Expand Down Expand Up @@ -128,7 +128,9 @@ function showerror(io::IO, ex::ErrorException)
print(io, "Use `codeunits(str)` instead.")
end
end
showerror(io::IO, ex::KeyError) = print(io, "KeyError: key $(repr(ex.key)) not found")
showerror(io::IO, ex::KeyError) = (print(io, "KeyError: key ");
show(io, ex.key);
print(io, " not found"))
showerror(io::IO, ex::InterruptException) = print(io, "InterruptException:")
showerror(io::IO, ex::ArgumentError) = print(io, "ArgumentError: $(ex.msg)")
showerror(io::IO, ex::AssertionError) = print(io, "AssertionError: $(ex.msg)")
Expand Down Expand Up @@ -188,9 +190,9 @@ function showerror(io::IO, ex::MethodError)
print(io, "Cannot `convert` an object of type ", arg_types_param[2], " to an object of type ", T)
end
elseif isempty(methods(f)) && isa(f, DataType) && f.abstract
print(io, "no constructors have been defined for $f")
print(io, "no constructors have been defined for ", f)
elseif isempty(methods(f)) && !isa(f, Function) && !isa(f, Type)
print(io, "objects of type $ft are not callable")
print(io, "objects of type ", ft, " are not callable")
else
if ft <: Function && isempty(ft.parameters) &&
isdefined(ft.name.module, name) &&
Expand All @@ -204,7 +206,7 @@ function showerror(io::IO, ex::MethodError)
end
print(io, "(")
for (i, typ) in enumerate(arg_types_param)
print(io, "::$typ")
print(io, "::", typ)
i == length(arg_types_param) || print(io, ", ")
end
if !isempty(kwargs)
Expand Down Expand Up @@ -341,10 +343,10 @@ function show_method_candidates(io::IO, ex::MethodError, @nospecialize kwargs=()
# If isvarargtype then it checks whether the rest of the input arguments matches
# the varargtype
if Base.isvarargtype(sig[i])
sigstr = string(unwrap_unionall(sig[i]).parameters[1], "...")
sigstr = (unwrap_unionall(sig[i]).parameters[1], "...")
j = length(t_i)
else
sigstr = string(sig[i])
sigstr = (sig[i],)
j = i
end
# Checks if the type of arg 1:i of the input intersects with the current method
Expand All @@ -356,18 +358,18 @@ function show_method_candidates(io::IO, ex::MethodError, @nospecialize kwargs=()
if t_in === Union{}
if get(io, :color, false)
Base.with_output_color(Base.error_color(), iob) do iob
print(iob, "::$sigstr")
print(iob, "::", sigstr...)
end
else
print(iob, "!Matched::$sigstr")
print(iob, "!Matched::", sigstr...)
end
# If there is no typeintersect then the type signature from the method is
# inserted in t_i this ensures if the type at the next i matches the type
# signature then there will be a type intersect
t_i[i] = sig[i]
else
right_matches += j==i ? 1 : 0
print(iob, "::$sigstr")
print(iob, "::", sigstr...)
end
end
special && right_matches == 0 && continue
Expand All @@ -389,19 +391,19 @@ function show_method_candidates(io::IO, ex::MethodError, @nospecialize kwargs=()
for (k, sigtype) in enumerate(sig[length(t_i)+1:end])
sigtype = isvarargtype(sigtype) ? unwrap_unionall(sigtype) : sigtype
if Base.isvarargtype(sigtype)
sigstr = string(sigtype.parameters[1], "...")
sigstr = (sigtype.parameters[1], "...")
else
sigstr = string(sigtype)
sigstr = (sigtype,)
end
if !((min(length(t_i), length(sig)) == 0) && k==1)
print(iob, ", ")
end
if get(io, :color, false)
Base.with_output_color(Base.error_color(), iob) do iob
print(iob, "::$sigstr")
print(iob, "::", sigstr...)
end
else
print(iob, "!Matched::$sigstr")
print(iob, "!Matched::", sigstr...)
end
end
end
Expand Down
2 changes: 1 addition & 1 deletion base/iostream.jl
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ function open(fname::AbstractString;
append = append,
)
s = IOStream(string("<file ",fname,">"))
systemerror("opening file $fname",
systemerror("opening file $(repr(fname))",
ccall(:ios_file, Ptr{Cvoid},
(Ptr{UInt8}, Cstring, Cint, Cint, Cint, Cint),
s.ios, fname, flags.read, flags.write, flags.create, flags.truncate) == C_NULL)
Expand Down
2 changes: 1 addition & 1 deletion base/loading.jl
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ string(hash::SHA1) = bytes2hex(hash.bytes)
print(io::IO, hash::SHA1) = bytes2hex(io, hash.bytes)
show(io::IO, hash::SHA1) = print(io, "SHA1(\"", hash, "\")")

isless(a::SHA1, b::SHA1) = lexless(a.bytes, b.bytes)
isless(a::SHA1, b::SHA1) = isless(a.bytes, b.bytes)
hash(a::SHA1, h::UInt) = hash((SHA1, a.bytes), h)
==(a::SHA1, b::SHA1) = a.bytes == b.bytes

Expand Down
58 changes: 56 additions & 2 deletions base/locks.jl
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# This file is a part of Julia. License is MIT: https://julialang.org/license

import .Base: _uv_hook_close, unsafe_convert,
lock, trylock, unlock, islocked
lock, trylock, unlock, islocked, wait, notify

export SpinLock, RecursiveSpinLock, Mutex
export SpinLock, RecursiveSpinLock, Mutex, Event


##########################################
Expand Down Expand Up @@ -238,3 +238,57 @@ end
function islocked(m::Mutex)
return m.ownertid != 0
end

"""
Event()
Create a level-triggered event source. Tasks that call [`wait`](@ref) on an
`Event` are suspended and queued until `notify` is called on the `Event`.
After `notify` is called, the `Event` remains in a signaled state and
tasks will no longer block when waiting for it.
"""
mutable struct Event
lock::Mutex
q::Vector{Task}
set::Bool
# TODO: use a Condition with its paired lock
Event() = new(Mutex(), Task[], false)
end

function wait(e::Event)
e.set && return
lock(e.lock)
while !e.set
ct = current_task()
push!(e.q, ct)
unlock(e.lock)
try
wait()
catch
filter!(x->x!==ct, e.q)
rethrow()
end
lock(e.lock)
end
unlock(e.lock)
return nothing
end

function notify(e::Event)
lock(e.lock)
if !e.set
e.set = true
for t in e.q
schedule(t)
end
empty!(e.q)
end
unlock(e.lock)
return nothing
end

# TODO: decide what to call this
#function clear(e::Event)
# e.set = false
# return nothing
#end
2 changes: 1 addition & 1 deletion base/methodshow.jl
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,7 @@ function show(io::IO, mime::MIME"text/plain", mt::AbstractVector{Method})
end

function show(io::IO, mime::MIME"text/html", mt::AbstractVector{Method})
print(io, summary(mt))
summary(io, mt)
if !isempty(mt)
print(io, ":<ul>")
for d in mt
Expand Down
Loading

0 comments on commit 3577e33

Please sign in to comment.