diff --git a/base/strings/io.jl b/base/strings/io.jl index f9682ffaacf29..97cdedac3db78 100644 --- a/base/strings/io.jl +++ b/base/strings/io.jl @@ -354,7 +354,8 @@ function join(io::IO, iterator, delim="") end function _join_preserve_annotations(iterator, args...) - if isconcretetype(eltype(iterator)) && !_isannotated(eltype(iterator)) && !any(_isannotated, args) + et = @default_eltype(iterator) + if isconcretetype(et) && !_isannotated(et) && !any(_isannotated, args) sprint(join, iterator, args...) else io = AnnotatedIOBuffer() @@ -363,7 +364,7 @@ function _join_preserve_annotations(iterator, args...) # of iterators with a non-concrete eltype), that the result is annotated # in nature, we extract an `AnnotatedString`, otherwise we just extract # a plain `String` from `io`. - if isconcretetype(eltype(iterator)) || !isempty(io.annotations) + if isconcretetype(et) || !isempty(io.annotations) read(seekstart(io), AnnotatedString{String}) else String(take!(io.io)) diff --git a/test/strings/io.jl b/test/strings/io.jl index f1fe0c24e8aea..3387ebc1e6794 100644 --- a/test/strings/io.jl +++ b/test/strings/io.jl @@ -339,3 +339,8 @@ end @testset "`string` return types" begin @test all(T -> T <: AbstractString, Base.return_types(string)) end + +@testset "type stable `join` (#55389)" begin + itr = ("foo" for _ in 1:100) + @test Base.return_types(join, (typeof(itr),))[] == String +end