Skip to content

Commit

Permalink
Merge branch 'master' into ms/last_incremental_sweep
Browse files Browse the repository at this point in the history
  • Loading branch information
li1 committed Jun 20, 2023
2 parents 831ac70 + 0da46e2 commit bbf89d9
Show file tree
Hide file tree
Showing 57 changed files with 1,354 additions and 456 deletions.
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,10 @@ endif
# Remove various files which should not be installed
-rm -f $(DESTDIR)$(datarootdir)/julia/base/version_git.sh
-rm -f $(DESTDIR)$(datarootdir)/julia/test/Makefile
-rm -f $(DESTDIR)$(datarootdir)/julia/base/*/source-extracted
-rm -f $(DESTDIR)$(datarootdir)/julia/base/*/build-configured
-rm -f $(DESTDIR)$(datarootdir)/julia/base/*/build-compiled
-rm -f $(DESTDIR)$(datarootdir)/julia/base/*/build-checked
-rm -f $(DESTDIR)$(datarootdir)/julia/stdlib/$(VERSDIR)/*/source-extracted
-rm -f $(DESTDIR)$(datarootdir)/julia/stdlib/$(VERSDIR)/*/build-configured
-rm -f $(DESTDIR)$(datarootdir)/julia/stdlib/$(VERSDIR)/*/build-compiled
Expand Down
3 changes: 3 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ Julia v1.10 Release Notes
New language features
---------------------

* JuliaSyntax.jl is now used as the default parser, providing better diagnostics and faster
parsing. Set environment variable `JULIA_USE_NEW_PARSER` to `0` to switch back to the old
parser if necessary (and if you find this necessary, please file an issue) ([#46372]).
* `` (U+297A, `\leftarrowsubset`) and `` (U+2977, `\leftarrowless`)
may now be used as binary operators with arrow precedence. ([#45962])

Expand Down
1 change: 1 addition & 0 deletions base/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@
/version_git.jl
/version_git.jl.phony
/userimg.jl
/JuliaSyntax
7 changes: 7 additions & 0 deletions base/Base.jl
Original file line number Diff line number Diff line change
Expand Up @@ -489,6 +489,10 @@ a_method_to_overwrite_in_test() = inferencebarrier(1)
include(mod::Module, _path::AbstractString) = _include(identity, mod, _path)
include(mapexpr::Function, mod::Module, _path::AbstractString) = _include(mapexpr, mod, _path)

# External libraries vendored into Base
Core.println("JuliaSyntax/src/JuliaSyntax.jl")
include(@__MODULE__, "JuliaSyntax/src/JuliaSyntax.jl")

end_base_include = time_ns()

const _sysimage_modules = PkgId[]
Expand Down Expand Up @@ -600,6 +604,9 @@ function __init__()
_require_world_age[] = get_world_counter()
# Prevent spawned Julia process from getting stuck waiting on Tracy to connect.
delete!(ENV, "JULIA_WAIT_FOR_TRACY")
if get_bool_env("JULIA_USE_NEW_PARSER", true) === true
JuliaSyntax.enable_in_core!()
end
nothing
end

Expand Down
4 changes: 3 additions & 1 deletion base/boot.jl
Original file line number Diff line number Diff line change
Expand Up @@ -825,9 +825,11 @@ Integer(x::Union{Float16, Float32, Float64}) = Int(x)
# `_parse` must return an `svec` containing an `Expr` and the new offset as an
# `Int`.
#
# The internal jl_parse which will call into Core._parse if not `nothing`.
# The internal jl_parse will call into Core._parse if not `nothing`.
_parse = nothing

_setparser!(parser) = setglobal!(Core, :_parse, parser)

# support for deprecated uses of internal _apply function
_apply(x...) = Core._apply_iterate(Main.Base.iterate, x...)

Expand Down
19 changes: 15 additions & 4 deletions base/client.jl
Original file line number Diff line number Diff line change
Expand Up @@ -202,10 +202,7 @@ parse_input_line(s::AbstractString) = parse_input_line(String(s))
# detect the reason which caused an :incomplete expression
# from the error message
# NOTE: the error messages are defined in src/julia-parser.scm
incomplete_tag(ex) = :none
function incomplete_tag(ex::Expr)
Meta.isexpr(ex, :incomplete) || return :none
msg = ex.args[1]
function fl_incomplete_tag(msg::AbstractString)
occursin("string", msg) && return :string
occursin("comment", msg) && return :comment
occursin("requires end", msg) && return :block
Expand All @@ -214,6 +211,20 @@ function incomplete_tag(ex::Expr)
return :other
end

incomplete_tag(ex) = :none
function incomplete_tag(ex::Expr)
if ex.head !== :incomplete
return :none
elseif isempty(ex.args)
return :other
elseif ex.args[1] isa String
return fl_incomplete_tag(ex.args[1])
else
return incomplete_tag(ex.args[1])
end
end
incomplete_tag(exc::Meta.ParseError) = incomplete_tag(exc.detail)

function exec_options(opts)
quiet = (opts.quiet != 0)
startup = (opts.startupfile != 2)
Expand Down
2 changes: 1 addition & 1 deletion base/compiler/abstractinterpretation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1588,7 +1588,7 @@ function abstract_apply(interp::AbstractInterpreter, argtypes::Vector{Any}, si::
call = abstract_call(interp, ArgInfo(nothing, ct), si, sv, max_methods)
seen += 1
push!(retinfos, ApplyCallInfo(call.info, arginfo))
res = tmerge(res, call.rt)
res = tmerge(typeinf_lattice(interp), res, call.rt)
effects = merge_effects(effects, call.effects)
if bail_out_apply(interp, InferenceLoopState(ct, res, effects), sv)
add_remark!(interp, sv, "_apply_iterate inference reached maximally imprecise information. Bailing on.")
Expand Down
2 changes: 1 addition & 1 deletion base/compiler/compiler.jl
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ include("compiler/bootstrap.jl")
ccall(:jl_set_typeinf_func, Cvoid, (Any,), typeinf_ext_toplevel)

include("compiler/parsing.jl")
Core.eval(Core, :(_parse = Compiler.fl_parse))
Core._setparser!(fl_parse)

end # baremodule Compiler
))
2 changes: 1 addition & 1 deletion base/compiler/typelimits.jl
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,7 @@ function tmerge(lattice::OptimizerLattice, @nospecialize(typea), @nospecialize(t

# type-lattice for MaybeUndef wrapper
if isa(typea, MaybeUndef) || isa(typeb, MaybeUndef)
return MaybeUndef(tmerge(
return MaybeUndef(tmerge(widenlattice(lattice),
isa(typea, MaybeUndef) ? typea.typ : typea,
isa(typeb, MaybeUndef) ? typeb.typ : typeb))
end
Expand Down
15 changes: 13 additions & 2 deletions base/errorshow.jl
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,13 @@ show_index(io::IO, x::LogicalIndex) = summary(io, x.mask)
show_index(io::IO, x::OneTo) = print(io, "1:", x.stop)
show_index(io::IO, x::Colon) = print(io, ':')

function showerror(io::IO, ex::Meta.ParseError)
if isnothing(ex.detail)
print(io, "ParseError(", repr(ex.msg), ")")
else
showerror(io, ex.detail)
end
end

function showerror(io::IO, ex::BoundsError)
print(io, "BoundsError")
Expand Down Expand Up @@ -243,7 +250,7 @@ function showerror(io::IO, ex::MethodError)
ft = typeof(f)
arg_types_param = arg_types_param[3:end]
kwargs = pairs(ex.args[1])
ex = MethodError(f, ex.args[3:end::Int])
ex = MethodError(f, ex.args[3:end::Int], ex.world)
end
name = ft.name.mt.name
if f === Base.convert && length(arg_types_param) == 2 && !is_arg_types
Expand Down Expand Up @@ -490,7 +497,11 @@ function show_method_candidates(io::IO, ex::MethodError, @nospecialize kwargs=()
if !((min(length(t_i), length(sig)) == 0) && k==1)
print(iob, ", ")
end
if get(io, :color, false)::Bool
if k == 1 && Base.isvarargtype(sigtype)
# There wasn't actually a mismatch - the method match failed for
# some other reason, e.g. world age. Just print the sigstr.
print(iob, sigstr...)
elseif get(io, :color, false)::Bool
let sigstr=sigstr
Base.with_output_color(Base.error_color(), iob) do iob
print(iob, "::", sigstr...)
Expand Down
51 changes: 49 additions & 2 deletions base/loading.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1902,8 +1902,17 @@ function _require(pkg::PkgId, env=nothing)
@goto load_from_cache
end
# spawn off a new incremental pre-compile task for recursive `require` calls
cachefile = compilecache(pkg, path)
if isa(cachefile, Exception)
cachefile_or_module = maybe_cachefile_lock(pkg, path) do
# double-check now that we have lock
m = _require_search_from_serialized(pkg, path, UInt128(0))
m isa Module && return m
compilecache(pkg, path)
end
cachefile_or_module isa Module && return cachefile_or_module::Module
cachefile = cachefile_or_module
if isnothing(cachefile) # maybe_cachefile_lock returns nothing if it had to wait for another process
@goto load_from_cache # the new cachefile will have the newest mtime so will come first in the search
elseif isa(cachefile, Exception)
if precompilableerror(cachefile)
verbosity = isinteractive() ? CoreLogging.Info : CoreLogging.Debug
@logmsg verbosity "Skipping precompilation since __precompile__(false). Importing $pkg."
Expand Down Expand Up @@ -2805,6 +2814,44 @@ function show(io::IO, cf::CacheFlags)
print(io, ", opt_level = ", cf.opt_level)
end

# Set by FileWatching.__init__()
global mkpidlock_hook
global trymkpidlock_hook
global parse_pidfile_hook

# The preferences hash is only known after precompilation so just assume no preferences
# meaning that if all other conditions are equal, the same package cannot be precompiled
# with different preferences at the same time.
compilecache_pidfile_path(pkg::PkgId) = compilecache_path(pkg, UInt64(0)) * ".pidfile"

# Allows processes to wait if another process is precompiling a given source already.
# The lock file is deleted and precompilation will proceed after `stale_age` seconds if
# - the locking process no longer exists
# - the lock is held by another host, since processes cannot be checked remotely
# or after `stale_age * 25` seconds if it does still exist.
function maybe_cachefile_lock(f, pkg::PkgId, srcpath::String; stale_age=60)
if @isdefined(mkpidlock_hook) && @isdefined(trymkpidlock_hook) && @isdefined(parse_pidfile_hook)
pidfile = compilecache_pidfile_path(pkg)
cachefile = invokelatest(trymkpidlock_hook, f, pidfile; stale_age)
if cachefile === false
pid, hostname, age = invokelatest(parse_pidfile_hook, pidfile)
verbosity = isinteractive() ? CoreLogging.Info : CoreLogging.Debug
if isempty(hostname) || hostname == gethostname()
@logmsg verbosity "Waiting for another process (pid: $pid) to finish precompiling $pkg"
else
@logmsg verbosity "Waiting for another machine (hostname: $hostname, pid: $pid) to finish precompiling $pkg"
end
# wait until the lock is available, but don't actually acquire it
# returning nothing indicates a process waited for another
return invokelatest(mkpidlock_hook, Returns(nothing), pidfile; stale_age)
end
return cachefile
else
# for packages loaded before FileWatching.__init__()
f()
end
end

# returns true if it "cachefile.ji" is stale relative to "modpath.jl" and build_id for modkey
# otherwise returns the list of dependencies to also check
@constprop :none function stale_cachefile(modpath::String, cachefile::String; ignore_loaded::Bool = false)
Expand Down
25 changes: 17 additions & 8 deletions base/meta.jl
Original file line number Diff line number Diff line change
Expand Up @@ -187,8 +187,11 @@ expression.
"""
struct ParseError <: Exception
msg::String
detail::Any
end

ParseError(msg::AbstractString) = ParseError(msg, nothing)

function _parse_string(text::AbstractString, filename::AbstractString,
lineno::Integer, index::Integer, options)
if index < 1 || index > ncodeunits(text) + 1
Expand Down Expand Up @@ -233,7 +236,11 @@ function parse(str::AbstractString, pos::Integer; greedy::Bool=true, raise::Bool
depwarn::Bool=true)
ex, pos = _parse_string(str, "none", 1, pos, greedy ? :statement : :atom)
if raise && isa(ex,Expr) && ex.head === :error
throw(ParseError(ex.args[1]))
err = ex.args[1]
if err isa String
err = ParseError(err) # For flisp parser
end
throw(err)
end
return ex, pos
end
Expand All @@ -247,20 +254,22 @@ syntax errors will raise an error; otherwise, `parse` will return an expression
raise an error upon evaluation. If `depwarn` is `false`, deprecation warnings will be
suppressed.
```jldoctest
```jldoctest; filter=r"(?<=Expr\\(:error).*|(?<=Expr\\(:incomplete).*"
julia> Meta.parse("x = 3")
:(x = 3)
julia> Meta.parse("x = ")
:($(Expr(:incomplete, "incomplete: premature end of input")))
julia> Meta.parse("1.0.2")
ERROR: Base.Meta.ParseError("invalid numeric constant \\\"1.0.\\\"")
Stacktrace:
ERROR: ParseError:
# Error @ none:1:1
1.0.2
└──┘ ── invalid numeric constant
[...]
julia> Meta.parse("1.0.2"; raise = false)
:($(Expr(:error, "invalid numeric constant \"1.0.\"")))
:(\$(Expr(:error, "invalid numeric constant \"1.0.\"")))
julia> Meta.parse("x = ")
:(\$(Expr(:incomplete, "incomplete: premature end of input")))
```
"""
function parse(str::AbstractString; raise::Bool=true, depwarn::Bool=true)
Expand Down
15 changes: 14 additions & 1 deletion base/reflection.jl
Original file line number Diff line number Diff line change
Expand Up @@ -820,9 +820,19 @@ julia> Base.fieldindex(Foo, :z, false)
```
"""
function fieldindex(T::DataType, name::Symbol, err::Bool=true)
return err ? _fieldindex_maythrow(T, name) : _fieldindex_nothrow(T, name)
end

function _fieldindex_maythrow(T::DataType, name::Symbol)
@_foldable_meta
@noinline
return Int(ccall(:jl_field_index, Cint, (Any, Any, Cint), T, name, err)+1)
return Int(ccall(:jl_field_index, Cint, (Any, Any, Cint), T, name, true)+1)
end

function _fieldindex_nothrow(T::DataType, name::Symbol)
@_total_meta
@noinline
return Int(ccall(:jl_field_index, Cint, (Any, Any, Cint), T, name, false)+1)
end

function fieldindex(t::UnionAll, name::Symbol, err::Bool=true)
Expand Down Expand Up @@ -1194,6 +1204,7 @@ struct CodegenParams
gnu_pubnames::Cint
debug_info_kind::Cint
safepoint_on_entry::Cint
gcstack_arg::Cint

lookup::Ptr{Cvoid}

Expand All @@ -1203,13 +1214,15 @@ struct CodegenParams
prefer_specsig::Bool=false,
gnu_pubnames=true, debug_info_kind::Cint = default_debug_info_kind(),
safepoint_on_entry::Bool=true,
gcstack_arg::Bool=true,
lookup::Ptr{Cvoid}=unsafe_load(cglobal(:jl_rettype_inferred_addr, Ptr{Cvoid})),
generic_context = nothing)
return new(
Cint(track_allocations), Cint(code_coverage),
Cint(prefer_specsig),
Cint(gnu_pubnames), debug_info_kind,
Cint(safepoint_on_entry),
Cint(gcstack_arg),
lookup, generic_context)
end
end
Expand Down
Loading

0 comments on commit bbf89d9

Please sign in to comment.