Skip to content
1 change: 1 addition & 0 deletions base/broadcast.jl
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,7 @@ Base.@propagate_inbounds function Base.iterate(bc::Broadcasted, s)
end

Base.IteratorSize(::Type{<:Broadcasted{<:Any,<:NTuple{N,Base.OneTo}}}) where {N} = Base.HasShape{N}()
Base.IteratorSize(::Type{<:Broadcasted{<:AbstractArrayStyle{N}, Nothing}}) where {N} = Base.HasShape{N}()
Base.IteratorEltype(::Type{<:Broadcasted}) = Base.EltypeUnknown()

## Instantiation fills in the "missing" fields in Broadcasted.
Expand Down
6 changes: 4 additions & 2 deletions base/compiler/ssair/show.jl
Original file line number Diff line number Diff line change
Expand Up @@ -629,8 +629,10 @@ function show_ir_stmt(io::IO, code::Union{IRCode, CodeInfo}, idx::Int, line_info

@assert new_node_inst !== UNDEF # we filtered these out earlier
show_type = should_print_ssa_type(new_node_inst)
with_output_color(:green, io) do io′
print_stmt(io′, node_idx, new_node_inst, used, maxlength_idx, false, show_type)
let maxlength_idx=maxlength_idx, show_type=show_type
with_output_color(:green, io) do io′
print_stmt(io′, node_idx, new_node_inst, used, maxlength_idx, false, show_type)
end
end

if new_node_type === UNDEF # try to be robust against errors
Expand Down
16 changes: 9 additions & 7 deletions base/errorshow.jl
Original file line number Diff line number Diff line change
Expand Up @@ -345,13 +345,15 @@ function showerror_ambiguous(io::IO, meth, f, args)
sigfix = typeintersect(m.sig, sigfix)
end
if isa(unwrap_unionall(sigfix), DataType) && sigfix <: Tuple
if all(m->morespecific(sigfix, m.sig), meth)
print(io, "\nPossible fix, define\n ")
Base.show_tuple_as_call(io, :function, sigfix)
else
println(io)
print(io, "To resolve the ambiguity, try making one of the methods more specific, or ")
print(io, "adding a new method more specific than any of the existing applicable methods.")
let sigfix=sigfix
if all(m->morespecific(sigfix, m.sig), meth)
print(io, "\nPossible fix, define\n ")
Base.show_tuple_as_call(io, :function, sigfix)
else
println(io)
print(io, "To resolve the ambiguity, try making one of the methods more specific, or ")
print(io, "adding a new method more specific than any of the existing applicable methods.")
end
end
end
nothing
Expand Down
25 changes: 5 additions & 20 deletions base/loading.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1003,9 +1003,6 @@ end
# require always works in Main scope and loads files from node 1
const toplevel_load = Ref(true)

const full_warning_showed = Ref(false)
const modules_warned_for = Set{PkgId}()

"""
require(into::Module, module::Symbol)

Expand Down Expand Up @@ -1051,26 +1048,14 @@ function require(into::Module, mod::Symbol)
Package $mod not found in current path$hint_message.
- $start_sentence `import Pkg; Pkg.add($(repr(String(mod))))` to install the $mod package."""))
else
s = """
throw(ArgumentError("""
Package $(where.name) does not have $mod in its dependencies:
- If you have $(where.name) checked out for development and have
- You may have a partially installed environment. Try `Pkg.instantiate()`
to ensure all packages in the environment are installed.
- Or, if you have $(where.name) checked out for development and have
added $mod as a dependency but haven't updated your primary
environment's manifest file, try `Pkg.resolve()`.
- Otherwise you may need to report an issue with $(where.name)"""

uuidkey = identify_package(PkgId(string(into)), String(mod))
uuidkey === nothing && throw(ArgumentError(s))

# fall back to toplevel loading with a warning
if !(where in modules_warned_for)
@warn string(
full_warning_showed[] ? "" : s, "\n",
string("Loading $(mod) into $(where.name) from project dependency, ",
"future warnings for $(where.name) are suppressed.")
) _module = nothing _file = nothing _group = nothing
push!(modules_warned_for, where)
end
full_warning_showed[] = true
- Otherwise you may need to report an issue with $(where.name)"""))
end
end
if _track_dependencies[]
Expand Down
82 changes: 44 additions & 38 deletions base/reinterpretarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ struct ReinterpretArray{T,N,S,A<:AbstractArray{S},IsReshaped} <: AbstractArray{T
if N != 0 && sizeof(S) != sizeof(T)
ax1 = axes(a)[1]
dim = length(ax1)
if Base.issingletontype(T)
if issingletontype(T)
dim == 0 || throwsingleton(S, T, "a non-empty")
else
rem(dim*sizeof(S),sizeof(T)) == 0 || thrownonint(S, T, dim)
Expand Down Expand Up @@ -75,15 +75,15 @@ struct ReinterpretArray{T,N,S,A<:AbstractArray{S},IsReshaped} <: AbstractArray{T
if sizeof(S) == sizeof(T)
N = ndims(a)
elseif sizeof(S) > sizeof(T)
Base.issingletontype(T) && throwsingleton(S, T, "with reshape a")
issingletontype(T) && throwsingleton(S, T, "with reshape a")
rem(sizeof(S), sizeof(T)) == 0 || throwintmult(S, T)
N = ndims(a) + 1
else
Base.issingletontype(S) && throwfromsingleton(S, T)
issingletontype(S) && throwfromsingleton(S, T)
rem(sizeof(T), sizeof(S)) == 0 || throwintmult(S, T)
N = ndims(a) - 1
N > -1 || throwsize0(S, T, "larger")
axes(a, 1) == Base.OneTo(sizeof(T) ÷ sizeof(S)) || throwsize1(a, T)
axes(a, 1) == OneTo(sizeof(T) ÷ sizeof(S)) || throwsize1(a, T)
end
readable = array_subpadding(T, S)
writable = array_subpadding(S, T)
Expand Down Expand Up @@ -148,33 +148,39 @@ StridedVector{T} = StridedArray{T,1}
StridedMatrix{T} = StridedArray{T,2}
StridedVecOrMat{T} = Union{StridedVector{T}, StridedMatrix{T}}

# the definition of strides for Array{T,N} is tuple() if N = 0, otherwise it is
# a tuple containing 1 and a cumulative product of the first N-1 sizes
# this definition is also used for StridedReshapedArray and StridedReinterpretedArray
# which have the same memory storage as Array
stride(a::Union{DenseArray,StridedReshapedArray,StridedReinterpretArray}, i::Int) = _stride(a, i)

function stride(a::ReinterpretArray, i::Int)
a.parent isa StridedArray || throw(ArgumentError("Parent must be strided."))
return _stride(a, i)
end
strides(a::Union{DenseArray,StridedReshapedArray,StridedReinterpretArray}) = size_to_strides(1, size(a)...)

function _stride(a, i)
if i > ndims(a)
return length(a)
function strides(a::ReshapedReinterpretArray)
ap = parent(a)
els, elp = elsize(a), elsize(ap)
stp = strides(ap)
els == elp && return stp
els < elp && return (1, _checked_strides(stp, els, elp)...)
stp[1] == 1 || throw(ArgumentError("Parent must be contiguous in the 1st dimension!"))
return _checked_strides(tail(stp), els, elp)
end

function strides(a::NonReshapedReinterpretArray)
ap = parent(a)
els, elp = elsize(a), elsize(ap)
stp = strides(ap)
els == elp && return stp
stp[1] == 1 || throw(ArgumentError("Parent must be contiguous in the 1st dimension!"))
return (1, _checked_strides(tail(stp), els, elp)...)
end

@inline function _checked_strides(stp::Tuple, els::Integer, elp::Integer)
if elp > els && rem(elp, els) == 0
N = div(elp, els)
return map(i -> N * i, stp)
end
s = 1
for n = 1:(i-1)
s *= size(a, n)
end
return s
drs = map(i -> divrem(elp * i, els), stp)
all(i->iszero(i[2]), drs) ||
throw(ArgumentError("Parent's strides could not be exactly divided!"))
map(first, drs)
end

function strides(a::ReinterpretArray)
a.parent isa StridedArray || throw(ArgumentError("Parent must be strided."))
size_to_strides(1, size(a)...)
end
strides(a::Union{DenseArray,StridedReshapedArray,StridedReinterpretArray}) = size_to_strides(1, size(a)...)
_checkcontiguous(::Type{Bool}, A::ReinterpretArray) = _checkcontiguous(Bool, parent(A))

similar(a::ReinterpretArray, T::Type, d::Dims) = similar(a.parent, T, d)

Expand Down Expand Up @@ -227,12 +233,12 @@ SCartesianIndices2{K}(indices2::AbstractUnitRange{Int}) where {K} = (@assert K::
eachindex(::IndexSCartesian2{K}, A::ReshapedReinterpretArray) where {K} = SCartesianIndices2{K}(eachindex(IndexLinear(), parent(A)))
@inline function eachindex(style::IndexSCartesian2{K}, A::AbstractArray, B::AbstractArray...) where {K}
iter = eachindex(style, A)
Base._all_match_first(C->eachindex(style, C), iter, B...) || Base.throw_eachindex_mismatch_indices(IndexSCartesian2{K}(), axes(A), axes.(B)...)
_all_match_first(C->eachindex(style, C), iter, B...) || throw_eachindex_mismatch_indices(IndexSCartesian2{K}(), axes(A), axes.(B)...)
return iter
end

size(iter::SCartesianIndices2{K}) where K = (K, length(iter.indices2))
axes(iter::SCartesianIndices2{K}) where K = (Base.OneTo(K), iter.indices2)
axes(iter::SCartesianIndices2{K}) where K = (OneTo(K), iter.indices2)

first(iter::SCartesianIndices2{K}) where {K} = SCartesianIndex2{K}(1, first(iter.indices2))
last(iter::SCartesianIndices2{K}) where {K} = SCartesianIndex2{K}(K, last(iter.indices2))
Expand Down Expand Up @@ -300,27 +306,27 @@ unaliascopy(a::ReshapedReinterpretArray{T}) where {T} = reinterpret(reshape, T,

function size(a::NonReshapedReinterpretArray{T,N,S} where {N}) where {T,S}
psize = size(a.parent)
size1 = Base.issingletontype(T) ? psize[1] : div(psize[1]*sizeof(S), sizeof(T))
size1 = issingletontype(T) ? psize[1] : div(psize[1]*sizeof(S), sizeof(T))
tuple(size1, tail(psize)...)
end
function size(a::ReshapedReinterpretArray{T,N,S} where {N}) where {T,S}
psize = size(a.parent)
sizeof(S) > sizeof(T) && return (div(sizeof(S), sizeof(T)), psize...)
sizeof(S) < sizeof(T) && return Base.tail(psize)
sizeof(S) < sizeof(T) && return tail(psize)
return psize
end
size(a::NonReshapedReinterpretArray{T,0}) where {T} = ()

function axes(a::NonReshapedReinterpretArray{T,N,S} where {N}) where {T,S}
paxs = axes(a.parent)
f, l = first(paxs[1]), length(paxs[1])
size1 = Base.issingletontype(T) ? l : div(l*sizeof(S), sizeof(T))
size1 = issingletontype(T) ? l : div(l*sizeof(S), sizeof(T))
tuple(oftype(paxs[1], f:f+size1-1), tail(paxs)...)
end
function axes(a::ReshapedReinterpretArray{T,N,S} where {N}) where {T,S}
paxs = axes(a.parent)
sizeof(S) > sizeof(T) && return (Base.OneTo(div(sizeof(S), sizeof(T))), paxs...)
sizeof(S) < sizeof(T) && return Base.tail(paxs)
sizeof(S) > sizeof(T) && return (OneTo(div(sizeof(S), sizeof(T))), paxs...)
sizeof(S) < sizeof(T) && return tail(paxs)
return paxs
end
axes(a::NonReshapedReinterpretArray{T,0}) where {T} = ()
Expand Down Expand Up @@ -372,7 +378,7 @@ end
@inline @propagate_inbounds function _getindex_ra(a::NonReshapedReinterpretArray{T,N,S}, i1::Int, tailinds::TT) where {T,N,S,TT}
# Make sure to match the scalar reinterpret if that is applicable
if sizeof(T) == sizeof(S) && (fieldcount(T) + fieldcount(S)) == 0
if Base.issingletontype(T) # singleton types
if issingletontype(T) # singleton types
@boundscheck checkbounds(a, i1, tailinds...)
return T.instance
end
Expand Down Expand Up @@ -420,7 +426,7 @@ end
@inline @propagate_inbounds function _getindex_ra(a::ReshapedReinterpretArray{T,N,S}, i1::Int, tailinds::TT) where {T,N,S,TT}
# Make sure to match the scalar reinterpret if that is applicable
if sizeof(T) == sizeof(S) && (fieldcount(T) + fieldcount(S)) == 0
if Base.issingletontype(T) # singleton types
if issingletontype(T) # singleton types
@boundscheck checkbounds(a, i1, tailinds...)
return T.instance
end
Expand Down Expand Up @@ -511,7 +517,7 @@ end
v = convert(T, v)::T
# Make sure to match the scalar reinterpret if that is applicable
if sizeof(T) == sizeof(S) && (fieldcount(T) + fieldcount(S)) == 0
if Base.issingletontype(T) # singleton types
if issingletontype(T) # singleton types
@boundscheck checkbounds(a, i1, tailinds...)
# setindex! is a noop except for the index check
else
Expand Down Expand Up @@ -577,7 +583,7 @@ end
v = convert(T, v)::T
# Make sure to match the scalar reinterpret if that is applicable
if sizeof(T) == sizeof(S) && (fieldcount(T) + fieldcount(S)) == 0
if Base.issingletontype(T) # singleton types
if issingletontype(T) # singleton types
@boundscheck checkbounds(a, i1, tailinds...)
# setindex! is a noop except for the index check
else
Expand Down
17 changes: 15 additions & 2 deletions base/reshapedarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ end

@inline function _unsafe_getindex(A::ReshapedArray{T,N}, indices::Vararg{Int,N}) where {T,N}
axp = axes(A.parent)
i = offset_if_vec(Base._sub2ind(size(A), indices...), axp)
i = offset_if_vec(_sub2ind(size(A), indices...), axp)
I = ind2sub_rs(axp, A.mi, i)
_unsafe_getindex_rs(parent(A), I)
end
Expand All @@ -266,7 +266,7 @@ end

@inline function _unsafe_setindex!(A::ReshapedArray{T,N}, val, indices::Vararg{Int,N}) where {T,N}
axp = axes(A.parent)
i = offset_if_vec(Base._sub2ind(size(A), indices...), axp)
i = offset_if_vec(_sub2ind(size(A), indices...), axp)
@inbounds parent(A)[ind2sub_rs(axes(A.parent), A.mi, i)...] = val
val
end
Expand All @@ -292,3 +292,16 @@ substrides(strds::NTuple{N,Int}, I::Tuple{ReshapedUnitRange, Vararg{Any}}) where
(size_to_strides(strds[1], size(I[1])...)..., substrides(tail(strds), tail(I))...)
unsafe_convert(::Type{Ptr{T}}, V::SubArray{T,N,P,<:Tuple{Vararg{Union{RangeIndex,ReshapedUnitRange}}}}) where {T,N,P} =
unsafe_convert(Ptr{T}, V.parent) + (first_index(V)-1)*sizeof(T)


_checkcontiguous(::Type{Bool}, A::AbstractArray) = size_to_strides(1, size(A)...) == strides(A)
_checkcontiguous(::Type{Bool}, A::Array) = true
_checkcontiguous(::Type{Bool}, A::ReshapedArray) = _checkcontiguous(Bool, parent(A))
_checkcontiguous(::Type{Bool}, A::FastContiguousSubArray) = _checkcontiguous(Bool, parent(A))

function strides(a::ReshapedArray)
# We can handle non-contiguous parent if it's a StridedVector
ndims(parent(a)) == 1 && return size_to_strides(only(strides(parent(a))), size(a)...)
_checkcontiguous(Bool, a) || throw(ArgumentError("Parent must be contiguous."))
size_to_strides(1, size(a)...)
end
4 changes: 2 additions & 2 deletions base/shell.jl
Original file line number Diff line number Diff line change
Expand Up @@ -211,8 +211,8 @@ function print_shell_escaped_posixly(io::IO, args::AbstractString...)
first || print(io, ' ')
# avoid printing quotes around simple enough strings
# that any (reasonable) shell will definitely never consider them to be special
have_single = false
have_double = false
have_single::Bool = false
have_double::Bool = false
function isword(c::AbstractChar)
if '0' <= c <= '9' || 'a' <= c <= 'z' || 'A' <= c <= 'Z'
# word characters
Expand Down
2 changes: 1 addition & 1 deletion base/weakkeydict.jl
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ end

function getkey(wkh::WeakKeyDict{K}, kk, default) where K
k = lock(wkh) do
k = getkey(wkh.ht, kk, nothing)
local k = getkey(wkh.ht, kk, nothing)
k === nothing && return nothing
return k.value
end
Expand Down
3 changes: 3 additions & 0 deletions doc/src/manual/functions.md
Original file line number Diff line number Diff line change
Expand Up @@ -993,6 +993,9 @@ julia> f.(A, B)
33.0
```

Keyword arguments are not broadcasted over, but are simply passed through to each call of
the function. For example, `round.(x, digits=3)` is equivalent to `broadcast(x -> round(x, digits=3), x)`.

Moreover, *nested* `f.(args...)` calls are *fused* into a single `broadcast` loop. For example,
`sin.(cos.(X))` is equivalent to `broadcast(x -> sin(cos(x)), X)`, similar to `[sin(cos(x)) for x in X]`:
there is only a single loop over `X`, and a single array is allocated for the result. [In contrast,
Expand Down
8 changes: 5 additions & 3 deletions stdlib/Profile/src/Allocs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,11 @@ const _g_expected_sampled_allocs = Ref{Float64}(0)
function _prof_expr(expr, opts)
quote
$start(; $(esc(opts)))
local res = $(esc(expr))
$stop()
res
try
$(esc(expr))
finally
$stop()
end
end
end

Expand Down
2 changes: 1 addition & 1 deletion stdlib/REPL/src/LineEdit.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1971,7 +1971,7 @@ function enter_prefix_search(s::MIState, p::PrefixHistoryPrompt, backward::Bool)
parent = mode(s)

transition(s, p) do
pss = state(s, p)
local pss = state(s, p)
pss.parent = parent
pss.histprompt.parent_prompt = parent
pss.prefix = String(buf.data[1:position(buf)])
Expand Down
4 changes: 2 additions & 2 deletions stdlib/Test/src/Test.jl
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ struct Pass <: Result
value
source::Union{Nothing,LineNumberNode}
message_only::Bool
function Pass(test_type::Symbol, orig_expr, data, thrown, source=nothing, message_only=false)
function Pass(test_type::Symbol, orig_expr, data, thrown, source::Union{Nothing,LineNumberNode}=nothing, message_only::Bool=false)
return new(test_type, orig_expr, data, thrown, source, message_only)
end
end
Expand Down Expand Up @@ -168,7 +168,7 @@ struct Error <: Result
backtrace::String
source::LineNumberNode

function Error(test_type, orig_expr, value, bt, source)
function Error(test_type::Symbol, orig_expr, value, bt, source::LineNumberNode)
if test_type === :test_error
bt = scrub_exc_stack(bt)
end
Expand Down
18 changes: 18 additions & 0 deletions test/abstractarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1561,3 +1561,21 @@ end
r = Base.IdentityUnitRange(3:4)
@test reshape(r, :) === reshape(r, (:,)) === r
end

@testset "strides for ReshapedArray" begin
# Type-based contiguous check is tested in test/compiler/inline.jl
# General contiguous check
a = view(rand(10,10), 1:10, 1:10)
@test strides(vec(a)) == (1,)
b = view(parent(a), 1:9, 1:10)
@test_throws "Parent must be contiguous." strides(vec(b))
# StridedVector parent
for n in 1:3
a = view(collect(1:60n), 1:n:60n)
@test strides(reshape(a, 3, 4, 5)) == (n, 3n, 12n)
@test strides(reshape(a, 5, 6, 2)) == (n, 5n, 30n)
b = view(parent(a), 60n:-n:1)
@test strides(reshape(b, 3, 4, 5)) == (-n, -3n, -12n)
@test strides(reshape(b, 5, 6, 2)) == (-n, -5n, -30n)
end
end
Loading