-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve inference broadly throughout REPL #37081
Conversation
OK, this grew into a much bigger deal. This should fix inference throughout essentially all of REPL. |
@@ -358,7 +358,7 @@ function pipe_reader end | |||
function pipe_writer end | |||
|
|||
write(io::AbstractPipe, byte::UInt8) = write(pipe_writer(io)::IO, byte) | |||
unsafe_write(io::AbstractPipe, p::Ptr{UInt8}, nb::UInt) = unsafe_write(pipe_writer(io)::IO, p, nb) | |||
unsafe_write(io::AbstractPipe, p::Ptr{UInt8}, nb::UInt) = unsafe_write(pipe_writer(io)::IO, p, nb)::Union{Int,UInt} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Methods for Union{Core.CoreSTDERR,Core.CoreSTDOUT}
and Base.FileSystem.File
return UInt
, the rest (I think) return Int
. Should we make them all one or the other?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not to derail the main point too much, but for overall context:
julia> for (m, rt) in zip(methods(write, (IO, Any)), Base.return_types(write, (IO, Any)))
println(m => rt)
end
write(io::Union{Core.CoreSTDERR, Core.CoreSTDOUT}, x::UInt8) in Base at coreio.jl:26 => Int64
write(s::IO, x::Union{Float16, Float32, Float64, Int128, Int16, Int32, Int64, UInt128, UInt16, UInt32, UInt64}) in Base at io.jl:649 => Any
write(io::IO, s::Union{SubString{String}, String}) in Base at strings/io.jl:185 => Int64
write(io::IO, s::Base.CodeUnits) in Base at strings/basic.jl:744 => Int64
write(to::IO, p::Ptr) in Base at io.jl:654 => Any
write(io::IO, x::Enum{T}) where T<:Integer in Base.Enums at Enums.jl:21 => Any
write(s::IO, a::SubArray{T,N,var"#s68",I,L} where L where I where var"#s68"<:Array) where {T, N} in Base at io.jl:675 => Any
write(s::IO, z::Rational) in Base at rational.jl:94 => Int64
write(io::IO, s::AbstractString) in Base at strings/io.jl:181 => Int64
write(s::IO, a::Array) in Base at io.jl:667 => Any
write(s::IO, x::Ref{T}) where T in Base at io.jl:647 => Any
write(s::IO, z::Complex) in Base at complex.jl:220 => Int64
write(s::IO, B::BitArray) in Base at bitarray.jl:1823 => Any
write(s::IO, A::AbstractArray) in Base at io.jl:656 => Any
write(s::IO, x::Bool) in Base at io.jl:653 => Any
write(io::IO, s::Symbol) in Base at io.jl:708 => Any
write(io::IO, c::Char) in Base at io.jl:696 => Int64
write(io::IO, cred::LibGit2.GitCredential) in LibGit2 at /home/tim/src/julia-master/usr/share/julia/stdlib/v1.6/LibGit2/src/gitcredential.jl:94 => Nothing
write(io::IO, s::Base.SecretBuffer) in Base at secretbuffer.jl:126 => Any
write(s::IO, x::Int8) in Base at io.jl:648 => Any
write(io::Base.AbstractPipe, byte::UInt8) in Base at io.jl:360 => Any
write(to::Base.GenericIOBuffer, from::Base.GenericIOBuffer) in Base at iobuffer.jl:408 => Int64
write(to::IO, from::IO) in Base at io.jl:713 => Any
write(to::Base.GenericIOBuffer, a::UInt8) in Base at iobuffer.jl:445 => Int64
write(pipe::Base64.Base64EncodePipe, x::UInt8) in Base64 at /home/tim/src/julia-master/usr/share/julia/stdlib/v1.6/Base64/src/encode.jl:98 => Int64
write(io::Base.SecretBuffer, b::UInt8) in Base at secretbuffer.jl:112 => Int64
write(s::Base.BufferStream, b::UInt8) in Base at stream.jl:1351 => Int64
write(s::Base.LibuvStream, b::UInt8) in Base at stream.jl:1091 => Int64
write(f::Base.Filesystem.File, c::UInt8) in Base.Filesystem at filesystem.jl:136 => UInt64
write(::Base.DevNull, ::UInt8) in Base at coreio.jl:16 => Int64
write(s::IOStream, b::UInt8) in Base at iostream.jl:366 => Int64
write(s::IO, x::UInt8) in Base at io.jl:224 => Union{}
write(io::IO, x) in Base at io.jl:635 => Union{}
52ecf01
to
f46a78a
Compare
I expect this version should finally pass tests, as on the previous run only 32-bit was failing. Here, for completion methods I've changed |
Moving this earlier in the load sequence allows one to annotate the return type of some methods.
…rt of #37081) Since MIState and others have containers with abstract typing, these interfaces fix inference problems broadly.
Since entire modules are marked `@nospecialize`, we need to declare argument types anywhere we want good inference. This also improves numerous implementations to ensure inferrability. For the completion methods, notice this changes typeof(ret[2]) from UnitRange{Int64} to UnitRange{Int}. Internally, the methods are using Int rather than Int64, so consistently supporting Int64 would require more extensive changes.
Moving this earlier in the load sequence allows one to annotate the return type of some methods.
…rt of #37081) Since MIState and others have containers with abstract typing, these interfaces fix inference problems broadly.
Since entire modules are marked `@nospecialize`, we need to declare argument types anywhere we want good inference. This also improves numerous implementations to ensure inferrability. For the completion methods, notice this changes typeof(ret[2]) from UnitRange{Int64} to UnitRange{Int}. Internally, the methods are using Int rather than Int64, so consistently supporting Int64 would require more extensive changes.
I'm aware that this is a monster to review and that there aren't that many people who work on the REPL, so if necessary I'm happy to take responsibility for problems this causes. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not super familiar with the REPL code but looks good to me from what I can see.
Moving this earlier in the load sequence allows one to annotate the return type of some methods.
…rt of #37081) Since MIState and others have containers with abstract typing, these interfaces fix inference problems broadly.
Since entire modules are marked `@nospecialize`, we need to declare argument types anywhere we want good inference. This also improves numerous implementations to ensure inferrability. For the completion methods, notice this changes typeof(ret[2]) from UnitRange{Int64} to UnitRange{Int}. Internally, the methods are using Int rather than Int64, so consistently supporting Int64 would require more extensive changes.
As for completions part: the changes looks good (I gave it a quick try and even made equivalent changes for FuzzyCompletions.jl, and it seems to work great) |
@ChrisRackauckas it's really fun to be able to load DifferentialEquations and have your next tab-complete not have a 0.25s latency. |
you're the hero we needed. |
Also fun: Julia 1.5: julia> @time using DifferentialEquations
22.845265 seconds (61.37 M allocations: 3.389 GiB, 4.10% gc time) Today's master branch: julia> @time using DifferentialEquations
6.944444 seconds (21.22 M allocations: 1.442 GiB, 5.81% gc time) |
* REPL: move Options to improve inference Moving this earlier in the load sequence allows one to annotate the return type of some methods. * REPL: add interfaces for abstract types and change one field type Since MIState and others have containers with abstract typing, these interfaces fix inference problems broadly. * IO: improve inferrability of write and unsafe_write * REPL: add argument typing and improve implementations Since entire modules are marked `@nospecialize`, we need to declare argument types anywhere we want good inference. This also improves numerous implementations to ensure inferrability. For the completion methods, notice this changes typeof(ret[2]) from UnitRange{Int64} to UnitRange{Int}. Internally, the methods are using Int rather than Int64, so consistently supporting Int64 would require more extensive changes. * REPL: add argtypes to keymap functions * REPL: test inference in LineEdit
This attempts to improve inference in REPL. There are several pieces:
REPLCompletions.Completion
andTerminalMenus.AbstractMenu
Options
struct prior to creating theLineEdit
module, we gain the ability to improve many inference resultsThis does a lot to make REPL more inferrable and less vulnerable to invalidation, but if you check out the precompile statements that get issued during bootstrap, REPL is still the standout "bad actor" with regards to non-inferrable code. (Especially after some of my other PRs from today.)