-
-
Notifications
You must be signed in to change notification settings - Fork 11
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
Avoid method overwriting in julia1-compat
branch
#57
Comments
Hmmm, that's an interesting suggestion. At a glance, that looks viable, but I don't think we can do something similar with |
I think limited support would be more beneficial (i.e., less troublesome) than method overwriting. |
Maybe, the goal I went into with this though was to make it behave as close to the 1.11 stdlib as possible, and it's extremely close. As far as I'm aware, the problem with method overwriting here is he latency impact, is there anything beyond that? |
Whether or not method overwriting is performed is a greater difference than missing annotations in some cases. |
Right, but what's the negative impact of the method overwriting? AFAIU it's just the latency. |
This is a tautology, but it is a problem because method overwriting is a problem that is worthy of a warning. Older julia in particular are somewhat fragile with precompilation. Also, I think we need to clarify the relationship between this package and Compat.jl. |
In the first place, the any(_isannotated, args) # `any(_isannotated, iterator)` ? julia> join(("a", styled"{bold:b}"), ", ")|>typeof
String
julia> join(["a", styled"{bold:b}"], ", ")|>typeof
Base.AnnotatedString{String}
julia> versioninfo()
Julia Version 1.12.0-DEV.469
Commit 0d1d4ba068 (2024-05-06 21:04 UTC)
Build Info:
Official https://julialang.org/ release
Platform Info:
OS: Windows (x86_64-w64-mingw32)
CPU: 8 × 11th Gen Intel(R) Core(TM) i7-1165G7 @ 2.80GHz
WORD_SIZE: 64
LLVM: libLLVM-17.0.6 (ORCJIT, tigerlake)
Threads: 1 default, 0 interactive, 1 GC (on 8 virtual cores) |
Right, but the overwriting doesn't happen during precompilation. Chatting about method overwriting on Triage with Jeff, he said method overwriting is a fine thing to do.
There is no relation, I can't say I see the need? |
Looks like that's worthy of an issue in JuliaLang/julia, either the |
My point here (not in JuliaLang/julia) is that even with limited support for The following is just a PoC, but it works minimally. join(iterator, delim::Union{AbstractString, AbstractChar}) = _join_preserve_annotations(iterator, delim)
join(iterator, delim::Union{AbstractString, AbstractChar}, last) = _join_preserve_annotations(iterator, delim, last) Edit: join(iterator, delim::Union{AnnotatedChar, AnnotatedString}) = _join_preserve_annotations(iterator, delim)
join(iterator, delim::Union{AnnotatedChar, AnnotatedString}, last) = _join_preserve_annotations(iterator, delim, last) |
The |
Ah, right I follow now. |
Not quite, we do want |
xref: https://discourse.julialang.org/t/method-overwriting-in-styledstrings-jl-v1-0-julia1-compat/113935 |
As raised in <JuliaLang/StyledStrings.jl#57 (comment)>, when the eltype of an iterator is non-concrete, _isannotated can erroneously return false. To properly check such cases, we need to see if any of the elements of the iterator are annotated. This is a bit of an interesting case, since: - Most of the time it shouldn't be hit, we reasonably expect most iterables to infer as producing concrete types - The eltype of the iterator is (generally) known at compile-time, and so in any case other than the ambiguous non-concrete, this check remains able to be done at compile-time. - Should the iterator be stateful and non-concrete, the check can consume some amount of the iterator before join is called. If it weren't for the edge-case of stateful iterators, I'd say this would be a fairly clean/straightforward fix, but since they exist I'm currently tempted to think the best compromise is just to avoid checking any Iterators.Stateful iterators. If somebody can work out a nicer compromise, that would be grand. Reported-by: kimikage <kimikage.ceo@gmail.com>
As raised in <JuliaLang/StyledStrings.jl#57 (comment)>, when the eltype of an iterator is non-concrete, _isannotated can erroneously return false. To properly check such cases, we need to see if any of the elements of the iterator are annotated. This is a bit of an interesting case, since: - Most of the time it shouldn't be hit, we reasonably expect most iterables to infer as producing concrete types - The eltype of the iterator is (generally) known at compile-time, and so in any case other than the ambiguous non-concrete one, this check remains able to be done at compile-time. - Should the iterator be stateful and non-concrete, the check can consume some amount of the iterator before join is called. If it weren't for the edge-case of stateful iterators, I'd say this would be a fairly clean/straightforward fix, but since they exist I'm currently tempted to think the best compromise is just to avoid checking any Iterators.Stateful iterators. If somebody can work out a nicer compromise, that would be grand. Reported-by: kimikage <kimikage.ceo@gmail.com>
As raised in <JuliaLang/StyledStrings.jl#57 (comment)>, when the eltype of an iterator is non-concrete, _isannotated will return false. To properly check such cases, we need to see if any of the elements of the iterator are annotated. This is a bit of an interesting case, since: - Most of the time it shouldn't be hit, we reasonably expect most iterables to infer as producing concrete types - The eltype of the iterator is (generally) known at compile-time, and so in any case other than the ambiguous non-concrete one, this check remains able to be done at compile-time. - Should the iterator be stateful and non-concrete, the check can consume some amount of the iterator before join is called. With this change, join always preserves annotations. The compromise made is that iterators with non-concrete eltypes can result in join inferring a union return type (i.e. type instability with non-concrete iterators), but that doesn't seem too bad to me. Reported-by: kimikage <kimikage.ceo@gmail.com>
As raised in <JuliaLang/StyledStrings.jl#57 (comment)>, when the eltype of an iterator is non-concrete, _isannotated will return false. To properly check such cases, we need to see if any of the elements of the iterator are annotated. This is a bit of an interesting case, since: - Most of the time it shouldn't be hit, we reasonably expect most iterables to infer as producing concrete types - The eltype of the iterator is (generally) known at compile-time, and so in any case other than the ambiguous non-concrete one, this check remains able to be done at compile-time. With this change, join always preserves annotations. The compromise made is that iterators with non-concrete eltypes can result in join inferring a union return type (i.e. type instability with non-concrete iterators), but that doesn't seem too bad to me. Reported-by: kimikage <kimikage.ceo@gmail.com>
As raised in <JuliaLang/StyledStrings.jl#57 (comment)>, when the eltype of an iterator is non-concrete, _isannotated will return false. To properly check such cases, we need to see if any of the elements of the iterator are annotated. This is a bit of an interesting case, since: - Most of the time it shouldn't be hit, we reasonably expect most iterables to infer as producing concrete types - The eltype of the iterator is (generally) known at compile-time, and so in any case other than the ambiguous non-concrete one, this check remains able to be done at compile-time. With this change, join always preserves annotations. The compromise made is that iterators with non-concrete eltypes can result in join inferring a union return type (i.e. type instability with non-concrete iterators), but that doesn't seem too bad to me. Reported-by: kimikage <kimikage.ceo@gmail.com>
As raised in <JuliaLang/StyledStrings.jl#57 (comment)>, when the eltype of an iterator is non-concrete, `_isannotated` will return false. To properly check such cases, we need to see if any of the elements of the iterator are annotated. This is a bit of an interesting case, since: - Most of the time it shouldn't be hit, we can reasonably expect most iterables to infer as producing concrete types - The eltype of the iterator is (generally) known at compile-time, and so in any case other than the ambiguous non-concrete one, this check remains able to be done at compile-time. With this change, join always preserves annotations. The compromise made is that iterators with non-concrete eltypes can result in join inferring a union return type (i.e. type instability with non-concrete iterators), but that doesn't seem too bad to me (I don't see how we could be completely type stable without concrete types here).
As raised in <JuliaLang/StyledStrings.jl#57 (comment)>, when the eltype of an iterator is non-concrete, `_isannotated` will return false. To properly check such cases, we need to see if any of the elements of the iterator are annotated. This is a bit of an interesting case, since: - Most of the time it shouldn't be hit, we can reasonably expect most iterables to infer as producing concrete types - The eltype of the iterator is (generally) known at compile-time, and so in any case other than the ambiguous non-concrete one, this check remains able to be done at compile-time. With this change, join always preserves annotations. The compromise made is that iterators with non-concrete eltypes can result in join inferring a union return type (i.e. type instability with non-concrete iterators), but that doesn't seem too bad to me (I don't see how we could be completely type stable without concrete types here). (cherry picked from commit 462d7f4)
FWIW, here is some snoop compile output: julia> using SnoopCompileCore
julia> invalidations = @snoop_invalidations using StyledStrings
julia> using SnoopCompile
julia> trees = invalidation_trees(invalidations)
...
deleting join(iterator) @ Base strings/io.jl:356 invalidated:
backedges: 1: superseding join(iterator) @ Base strings/io.jl:356 with MethodInstance for join(::Vector{Char}) (1 children)
...
8: superseding join(iterator) @ Base strings/io.jl:356 with MethodInstance for join(::Tuple{String}) (596 children)
mt_disable: MethodInstance for join(::Vector{String})
+5 more
deleting join(iterator, delim) @ Base strings/io.jl:357 invalidated:
backedges: 1: superseding join(iterator, delim) @ Base strings/io.jl:357 with MethodInstance for join(::Vector{Symbol}, ::Char) (1 children)
...
11: superseding join(iterator, delim) @ Base strings/io.jl:357 with MethodInstance for join(::Base.Generator{Base.Iterators.Filter{Base.BinaryPlatforms.var"#14#16", Dict{String, String}}, Base.BinaryPlatforms.var"#13#15"}, ::String) (359 children)
12: superseding join(iterator, delim) @ Base strings/io.jl:357 with MethodInstance for join(::Vector{SubString{String}}, ::String) (620 children)
13: superseding join(iterator, delim) @ Base strings/io.jl:357 with MethodInstance for join(::Vector{Any}, ::String) (4123 children)
mt_disable: MethodInstance for join(::Tuple{Symbol}, ::String)
inserting *(s1::Union{AbstractChar, AbstractString}, s2::Union{AbstractChar, AbstractString}, ss::Union{AbstractChar, AbstractString}...) @ StyledStrings.AnnotatedStrings ~/.julia/packages/StyledStrings/fsZJu/src/strings/basic.jl:21 invalidated:
mt_backedges: 1: signature Tuple{typeof(*), Union{Nothing, String}, String} triggered MethodInstance for Pkg.Operations.var"#download_source#44"(::Bool, ::typeof(Pkg.Operations.download_source), ::Pkg.Types.Context) (0 children)
....
13: superseding *(s1::Union{AbstractChar, AbstractString}, ss::Union{AbstractChar, AbstractString}...) @ Base strings/basic.jl:260 with MethodInstance for *(::String, ::String, ::String) (114 children)
14: superseding *(s1::Union{AbstractChar, AbstractString}, ss::Union{AbstractChar, AbstractString}...) @ Base strings/basic.jl:260 with MethodInstance for *(::String, ::String, ::String, ::String, ::String, ::String, ::String) (1160 children)
15: superseding *(s1::Union{AbstractChar, AbstractString}, ss::Union{AbstractChar, AbstractString}...) @ Base strings/basic.jl:260 with MethodInstance for *(::String, ::String) (6902 children) |
As raised in <JuliaLang/StyledStrings.jl#57 (comment)>, when the eltype of an iterator is non-concrete, `_isannotated` will return false. To properly check such cases, we need to see if any of the elements of the iterator are annotated. This is a bit of an interesting case, since: - Most of the time it shouldn't be hit, we can reasonably expect most iterables to infer as producing concrete types - The eltype of the iterator is (generally) known at compile-time, and so in any case other than the ambiguous non-concrete one, this check remains able to be done at compile-time. With this change, join always preserves annotations. The compromise made is that iterators with non-concrete eltypes can result in join inferring a union return type (i.e. type instability with non-concrete iterators), but that doesn't seem too bad to me (I don't see how we could be completely type stable without concrete types here).
StyledStrings v1.0 currently does method overwriting.
StyledStrings.jl/src/strings/overrides.jl
Lines 1 to 15 in db9f9b5
At least for
*
, we should be able to avoid overwriting by defining the following (or something like):Edit:
An alternative is to require that the first 2 or 3 arguments should contain
Union{AnnotatedChar, AnnotatedString}
.The text was updated successfully, but these errors were encountered: