Skip to content

Commit

Permalink
Fix annotated join with non-concrete eltype iters
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
tecosaur committed Jun 24, 2024
1 parent 36a0da0 commit 29d7b74
Showing 1 changed file with 2 additions and 1 deletion.
3 changes: 2 additions & 1 deletion base/strings/io.jl
Original file line number Diff line number Diff line change
Expand Up @@ -354,7 +354,8 @@ function join(io::IO, iterator, delim="")
end

function _join_preserve_annotations(iterator, args...)
if _isannotated(eltype(iterator)) || any(_isannotated, args)
if _isannotated(eltype(iterator)) || any(_isannotated, args) ||
(!isconcretetype(eltype(iterator)) && !isa(iterator, Iterators.Stateful) && any(_isannotated, iterator))
io = AnnotatedIOBuffer()
join(io, iterator, args...)
read(seekstart(io), AnnotatedString{String})
Expand Down

0 comments on commit 29d7b74

Please sign in to comment.