Skip to content

Commit

Permalink
Merge branch 'master' into ap/which
Browse files Browse the repository at this point in the history
  • Loading branch information
vtjnash authored Feb 1, 2024
2 parents 7fbca2d + 6e7db14 commit 41a4692
Show file tree
Hide file tree
Showing 91 changed files with 1,332 additions and 525 deletions.
21 changes: 16 additions & 5 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,20 @@ New language features
* The new macro `Base.Cartesian.@ncallkw` is analogous to `Base.Cartesian.@ncall`,
but allows to add keyword arguments to the function call ([#51501]).
* Support for Unicode 15.1 ([#51799]).
* A new `AbstractString` type, `AnnotatedString`, is introduced that allows for
regional annotations to be attached to an underlying string. This type is
particularly useful for holding styling information, and is used extensively
in the new `StyledStrings` standard library. There is also a new `AnnotatedChar`
type, that is the equivalent new `AbstractChar` type.
* Three new types around the idea of text with "annotations" (`Pair{Symbol, Any}`
entries, e.g. `:lang => "en"` or `:face => :magenta`). These annotations
are preserved across operations (e.g. string concatenation with `*`) when
possible.
* `AnnotatedString` is a new `AbstractString` type. It wraps an underlying
string and allows for annotations to be attached to regions of the string.
This type is used extensively in the new `StyledStrings` standard library to
hold styling information.
* `AnnotatedChar` is a new `AbstractChar` type. It wraps another char and
holds a list of annotations that apply to it.
* `AnnotatedIOBuffer` is a new `IO` type that mimics an `IOBuffer`, but has
specialised `read`/`write` methods for annotated content. This can be
thought of both as a "string builder" of sorts and also as glue between
annotated and unannotated content.
* `Manifest.toml` files can now be renamed in the format `Manifest-v{major}.{minor}.toml`
to be preferentially picked up by the given julia version. i.e. in the same folder,
a `Manifest-v1.11.toml` would be used by v1.11 and `Manifest.toml` by every other julia
Expand Down Expand Up @@ -165,6 +174,8 @@ Standard library changes
#### Dates
The undocumented function `adjust` is no longer exported but is now documented
#### Statistics
* Statistics is now an upgradeable standard library ([#46501]).
Expand Down
11 changes: 7 additions & 4 deletions base/abstractarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -103,17 +103,20 @@ end
has_offset_axes(A, B, ...)
Return `true` if the indices of `A` start with something other than 1 along any axis.
If multiple arguments are passed, equivalent to `has_offset_axes(A) | has_offset_axes(B) | ...`.
If multiple arguments are passed, equivalent to `has_offset_axes(A) || has_offset_axes(B) || ...`.
See also [`require_one_based_indexing`](@ref).
"""
has_offset_axes() = false
has_offset_axes(A) = _any_tuple(x->Int(first(x))::Int != 1, false, axes(A)...)
has_offset_axes(A::AbstractVector) = Int(firstindex(A))::Int != 1 # improve performance of a common case (ranges)
# Use `_any_tuple` to avoid unneeded invoke.
# note: this could call `any` directly if the compiler can infer it
has_offset_axes(As...) = _any_tuple(has_offset_axes, false, As...)
has_offset_axes(::Colon) = false
has_offset_axes(::Array) = false
# note: this could call `any` directly if the compiler can infer it. We don't use _any_tuple
# here because it stops full elision in some cases (#49332) and we don't need handling of
# `missing` (has_offset_axes(A) always returns a Bool)
has_offset_axes(A, As...) = has_offset_axes(A) || has_offset_axes(As...)


"""
require_one_based_indexing(A::AbstractArray)
Expand Down
2 changes: 1 addition & 1 deletion base/abstractarraymath.jl
Original file line number Diff line number Diff line change
Expand Up @@ -353,7 +353,7 @@ julia> repeat([1, 2, 3], 2, 3)
```
"""
function repeat(A::AbstractArray, counts...)
return _RepeatInnerOuter.repeat(A, outer=counts)
return repeat(A, outer=counts)
end

"""
Expand Down
4 changes: 2 additions & 2 deletions base/abstractdict.jl
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@ julia> keytype(Dict(Int32(1) => "foo"))
Int32
```
"""
keytype(::Type{<:AbstractDict{K,V}}) where {K,V} = K
keytype(::Type{<:AbstractDict{K}}) where {K} = K
keytype(a::AbstractDict) = keytype(typeof(a))

"""
Expand All @@ -315,7 +315,7 @@ julia> valtype(Dict(Int32(1) => "foo"))
String
```
"""
valtype(::Type{<:AbstractDict{K,V}}) where {K,V} = V
valtype(::Type{<:AbstractDict{<:Any,V}}) where {V} = V
valtype(a::AbstractDict) = valtype(typeof(a))

"""
Expand Down
15 changes: 14 additions & 1 deletion base/checked.jl
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ return both the unchecked results and a boolean value denoting the presence of a
module Checked

export checked_neg, checked_abs, checked_add, checked_sub, checked_mul,
checked_div, checked_rem, checked_fld, checked_mod, checked_cld,
checked_div, checked_rem, checked_fld, checked_mod, checked_cld, checked_pow,
checked_length, add_with_overflow, sub_with_overflow, mul_with_overflow

import Core.Intrinsics:
Expand Down Expand Up @@ -358,6 +358,19 @@ The overflow protection may impose a perceptible performance penalty.
"""
checked_cld(x::T, y::T) where {T<:Integer} = cld(x, y) # Base.cld already checks

"""
Base.checked_pow(x, y)
Calculates `^(x,y)`, checking for overflow errors where applicable.
The overflow protection may impose a perceptible performance penalty.
"""
checked_pow(x::Integer, y::Integer) = checked_power_by_squaring(x, y)

checked_power_by_squaring(x_, p::Integer) = Base.power_by_squaring(x_, p; mul = checked_mul)
# For Booleans, the default implementation covers all cases.
checked_power_by_squaring(x::Bool, p::Integer) = Base.power_by_squaring(x, p)

"""
Base.checked_length(r)
Expand Down
19 changes: 10 additions & 9 deletions base/compiler/optimize.jl
Original file line number Diff line number Diff line change
Expand Up @@ -526,8 +526,8 @@ function visit_bb_phis!(callback, ir::IRCode, bb::Int)
end

function any_stmt_may_throw(ir::IRCode, bb::Int)
for stmt in ir.cfg.blocks[bb].stmts
if has_flag(ir[SSAValue(stmt)], IR_FLAG_NOTHROW)
for idx in ir.cfg.blocks[bb].stmts
if !has_flag(ir[SSAValue(idx)], IR_FLAG_NOTHROW)
return true
end
end
Expand Down Expand Up @@ -865,20 +865,22 @@ function ((; sv)::ScanStmt)(inst::Instruction, lstmt::Int, bb::Int)
end

function check_inconsistentcy!(sv::PostOptAnalysisState, scanner::BBScanner)
(; ir, inconsistent, tpdum) = sv

scan!(ScanStmt(sv), scanner, false)
complete!(sv.tpdum); push!(scanner.bb_ip, 1)
populate_def_use_map!(sv.tpdum, scanner)
complete!(tpdum); push!(scanner.bb_ip, 1)
populate_def_use_map!(tpdum, scanner)

(; ir, inconsistent, tpdum) = sv
stmt_ip = BitSetBoundedMinPrioritySet(length(ir.stmts))
for def in sv.inconsistent
for def in inconsistent
for use in tpdum[def]
if !(use in inconsistent)
push!(inconsistent, use)
append!(stmt_ip, tpdum[use])
end
end
end
lazydomtree = LazyDomtree(ir)
while !isempty(stmt_ip)
idx = popfirst!(stmt_ip)
inst = ir[SSAValue(idx)]
Expand All @@ -895,12 +897,11 @@ function check_inconsistentcy!(sv::PostOptAnalysisState, scanner::BBScanner)
any_non_boundscheck_inconsistent || continue
elseif isa(stmt, ReturnNode)
sv.all_retpaths_consistent = false
else isa(stmt, GotoIfNot)
elseif isa(stmt, GotoIfNot)
bb = block_for_inst(ir, idx)
cfg = ir.cfg
blockliveness = BlockLiveness(cfg.blocks[bb].succs, nothing)
domtree = construct_domtree(cfg.blocks)
for succ in iterated_dominance_frontier(cfg, blockliveness, domtree)
for succ in iterated_dominance_frontier(cfg, blockliveness, get!(lazydomtree))
visit_bb_phis!(ir, succ) do phiidx::Int
push!(inconsistent, phiidx)
push!(stmt_ip, phiidx)
Expand Down
4 changes: 3 additions & 1 deletion base/compiler/ssair/inlining.jl
Original file line number Diff line number Diff line change
Expand Up @@ -827,7 +827,7 @@ function compileable_specialization(mi::MethodInstance, effects::Effects,
end
end
add_inlining_backedge!(et, mi) # to the dispatch lookup
push!(et.edges, method.sig, mi_invoke) # add_inlining_backedge to the invoke call
mi_invoke !== mi && push!(et.edges, method.sig, mi_invoke) # add_inlining_backedge to the invoke call, if that is different
return InvokeCase(mi_invoke, effects, info)
end

Expand Down Expand Up @@ -1749,6 +1749,8 @@ function early_inline_special_case(
elseif cond.val === false
return SomeCase(stmt.args[4])
end
elseif (optimizer_lattice(state.interp), cond, Bool) && stmt.args[3] === stmt.args[4]
return SomeCase(stmt.args[3])
end
end
return nothing
Expand Down
7 changes: 5 additions & 2 deletions base/compiler/ssair/passes.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1116,7 +1116,7 @@ function refine_new_effects!(𝕃ₒ::AbstractLattice, compact::IncrementalCompa
return nothing
end

function fold_ifelse!(compact::IncrementalCompact, idx::Int, stmt::Expr)
function fold_ifelse!(compact::IncrementalCompact, idx::Int, stmt::Expr, 𝕃ₒ::AbstractLattice)
length(stmt.args) == 4 || return false
condarg = stmt.args[2]
condtyp = argextype(condarg, compact)
Expand All @@ -1128,6 +1128,9 @@ function fold_ifelse!(compact::IncrementalCompact, idx::Int, stmt::Expr)
compact[idx] = stmt.args[4]
return true
end
elseif (𝕃ₒ, condtyp, Bool) && stmt.args[3] === stmt.args[4]
compact[idx] = stmt.args[3]
return true
end
return false
end
Expand Down Expand Up @@ -1313,7 +1316,7 @@ function sroa_pass!(ir::IRCode, inlining::Union{Nothing,InliningState}=nothing)
elseif is_known_call(stmt, isa, compact)
lift_comparison!(isa, compact, idx, stmt, 𝕃ₒ)
elseif is_known_call(stmt, Core.ifelse, compact)
fold_ifelse!(compact, idx, stmt)
fold_ifelse!(compact, idx, stmt, 𝕃ₒ)
elseif is_known_invoke_or_call(stmt, Core.OptimizedGenerics.KeyValue.get, compact)
2 == (length(stmt.args) - (isexpr(stmt, :invoke) ? 2 : 1)) || continue
lift_keyvalue_get!(compact, idx, stmt, 𝕃ₒ)
Expand Down
3 changes: 2 additions & 1 deletion base/compiler/typelimits.jl
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,7 @@ union_count_abstract(@nospecialize(x)) = !isdispatchelem(x)
function issimpleenoughtype(@nospecialize t)
ut = unwrap_unionall(t)
ut isa DataType && ut.name.wrapper == t && return true
return unionlen(t) + union_count_abstract(t) <= MAX_TYPEUNION_LENGTH &&
return max(unionlen(t), union_count_abstract(t) + 1) <= MAX_TYPEUNION_LENGTH &&
unioncomplexity(t) <= MAX_TYPEUNION_COMPLEXITY
end

Expand Down Expand Up @@ -807,6 +807,7 @@ end
end
if usep
widen = rewrap_unionall(wr{p...}, wr)
widen <: wr || (widen = wr) # sometimes there are cross-constraints on wr that we may lose in this process, but that would cause future calls to this to need to return Any, which is undesirable
end
simplify[j] = !usep
end
Expand Down
27 changes: 18 additions & 9 deletions base/env.jl
Original file line number Diff line number Diff line change
Expand Up @@ -129,25 +129,34 @@ const get_bool_env_falsy = (
"0")

"""
Base.get_bool_env(name::String, default::Bool)::Union{Bool,Nothing}
Base.get_bool_env(name::String, default::Bool; throw=false)::Union{Bool,Nothing}
Base.get_bool_env(f_default::Callable, name::String; throw=false)::Union{Bool,Nothing}
Evaluate whether the value of environnment variable `name` is a truthy or falsy string,
and return `nothing` if it is not recognized as either. If the variable is not set, or is set to "",
return `default`.
and return `nothing` (or throw if `throw=true`) if it is not recognized as either. If
the variable is not set, or is set to "", return `default` or the result of executing `f_default()`.
Recognized values are the following, and their Capitalized and UPPERCASE forms:
truthy: "t", "true", "y", "yes", "1"
falsy: "f", "false", "n", "no", "0"
"""
function get_bool_env(name::String, default::Bool)
haskey(ENV, name) || return default
val = ENV[name]
if isempty(val)
return default
elseif val in get_bool_env_truthy
get_bool_env(name::String, default::Bool; kwargs...) = get_bool_env(Returns(default), name; kwargs...)
function get_bool_env(f_default::Callable, name::String; kwargs...)
if haskey(ENV, name)
val = ENV[name]
if !isempty(val)
return parse_bool_env(name, val; kwargs...)
end
end
return f_default()
end
function parse_bool_env(name::String, val::String = ENV[name]; throw::Bool=false)
if val in get_bool_env_truthy
return true
elseif val in get_bool_env_falsy
return false
elseif throw
Base.throw(ArgumentError("Value for environment variable `$name` could not be parsed as Boolean: $(repr(val))"))
else
return nothing
end
Expand Down
4 changes: 2 additions & 2 deletions base/gmp.jl
Original file line number Diff line number Diff line change
Expand Up @@ -606,8 +606,8 @@ function top_set_bit(x::BigInt)
x.size * sizeof(Limb) << 3 - leading_zeros(GC.@preserve x unsafe_load(x.d, x.size))
end

divrem(x::BigInt, y::BigInt) = MPZ.tdiv_qr(x, y)
divrem(x::BigInt, y::Integer) = MPZ.tdiv_qr(x, big(y))
divrem(x::BigInt, y::BigInt, ::typeof(RoundToZero) = RoundToZero) = MPZ.tdiv_qr(x, y)
divrem(x::BigInt, y::Integer, ::typeof(RoundToZero) = RoundToZero) = MPZ.tdiv_qr(x, BigInt(y))

cmp(x::BigInt, y::BigInt) = sign(MPZ.cmp(x, y))
cmp(x::BigInt, y::ClongMax) = sign(MPZ.cmp_si(x, y))
Expand Down
11 changes: 6 additions & 5 deletions base/intfuncs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -309,14 +309,15 @@ to_power_type(x) = convert(Base._return_type(*, Tuple{typeof(x), typeof(x)}), x)
"\nMake x a float matrix by adding a zero decimal ",
"(e.g., [2.0 1.0;1.0 0.0]^", p, " instead of [2 1;1 0]^", p, ")",
"or write float(x)^", p, " or Rational.(x)^", p, ".")))
@assume_effects :terminates_locally function power_by_squaring(x_, p::Integer)
# The * keyword supports `*=checked_mul` for `checked_pow`
@assume_effects :terminates_locally function power_by_squaring(x_, p::Integer; mul=*)
x = to_power_type(x_)
if p == 1
return copy(x)
elseif p == 0
return one(x)
elseif p == 2
return x*x
return mul(x, x)
elseif p < 0
isone(x) && return copy(x)
isone(-x) && return iseven(p) ? one(x) : copy(x)
Expand All @@ -325,16 +326,16 @@ to_power_type(x) = convert(Base._return_type(*, Tuple{typeof(x), typeof(x)}), x)
t = trailing_zeros(p) + 1
p >>= t
while (t -= 1) > 0
x *= x
x = mul(x, x)
end
y = x
while p > 0
t = trailing_zeros(p) + 1
p >>= t
while (t -= 1) >= 0
x *= x
x = mul(x, x)
end
y *= x
y = mul(y, x)
end
return y
end
Expand Down
3 changes: 3 additions & 0 deletions base/irrationals.jl
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ See also [`AbstractIrrational`](@ref).
"""
struct Irrational{sym} <: AbstractIrrational end

typemin(::Type{T}) where {T<:Irrational} = T()
typemax(::Type{T}) where {T<:Irrational} = T()

show(io::IO, x::Irrational{sym}) where {sym} = print(io, sym)

function show(io::IO, ::MIME"text/plain", x::Irrational{sym}) where {sym}
Expand Down
Loading

0 comments on commit 41a4692

Please sign in to comment.