Skip to content
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

Type piracy with Base.readuntil #1021

Open
mortenpi opened this issue Mar 14, 2023 · 2 comments
Open

Type piracy with Base.readuntil #1021

mortenpi opened this issue Mar 14, 2023 · 2 comments

Comments

@mortenpi
Copy link
Contributor

HTTP.jl/src/IOExtras.jl

Lines 114 to 124 in a3a5768

function Base.readuntil(buf::IOBuffer,
find_delimiter::F #= Vector{UInt8} -> Int =#
)::ByteView where {F <: Function}
l = find_delimiter(view(buf.data, buf.ptr:buf.size))
if l == 0
return nobytes
end
bytes = view(buf.data, buf.ptr:buf.ptr + l - 1)
buf.ptr += l
return bytes
end

This could be causing some issues for us in our use case, although that needs a bit more investigation. But regardless, it might be a good idea to try to get rid of it, just in case?

@mortenpi
Copy link
Contributor Author

I noticed more type piracy in IOExtras:

HTTP.jl/src/IOExtras.jl

Lines 54 to 84 in a3a5768

if isdefined(Base, :startwrite)
"$_doc"
Base.startwrite(io) = nothing
else
"$_doc"
startwrite(io) = nothing
end
if isdefined(Base, :closewrite)
"$_doc"
Base.closewrite(io) = nothing
else
"$_doc"
closewrite(io) = nothing
end
if isdefined(Base, :startread)
"$_doc"
Base.startread(io) = nothing
else
"$_doc"
startread(io) = nothing
end
if isdefined(Base, :closeread)
"$_doc"
Base.closeread(io) = nothing
else
"$_doc"
closeread(io) = nothing
end

I see it was discussed quite extensively, but never really resolved.

@mortenpi
Copy link
Contributor Author

So #1083 fixed the readuntil case, but the startread / closeread / startwrite / closewrite functions are still there.

HTTP.jl/src/IOExtras.jl

Lines 46 to 84 in bbe1746

_doc = """
startwrite(::IO)
closewrite(::IO)
startread(::IO)
closeread(::IO)
Signal start/end of write or read operations.
"""
@static if isdefined(Base, :startwrite)
"$_doc"
Base.startwrite(io) = nothing
else
"$_doc"
startwrite(io) = nothing
end
@static if isdefined(Base, :closewrite)
"$_doc"
Base.closewrite(io) = nothing
else
"$_doc"
closewrite(io) = nothing
end
@static if isdefined(Base, :startread)
"$_doc"
Base.startread(io) = nothing
else
"$_doc"
startread(io) = nothing
end
@static if isdefined(Base, :closeread)
"$_doc"
Base.closeread(io) = nothing
else
"$_doc"
closeread(io) = nothing
end

Not quite sure how to handle those, since those are exported and/or sometimes extend a Base function.

It seems like IOExtras assumes that they might be defined in Base, although that's only actually true for closewrite. And so HTTP sometimes exports Base.closewrite and sometimes HTTP.IOExtras.closewrite (depending on Julia version). And if it exports Base.closewrite, it does type piracy on it by defining a Base.closewrite(::Any) method. Changing HTTP to always export HTTP.IOExtras.closewrite might be breaking though, since it's also exported from Base.

The other cases are not really a problem though, and we could just remove the isdefined checks. I guess if we really want, we could use a @static if hasmethod() in IOExtras instead, and trust that the trivial fallback methods more or less make sense for other users of the function.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant