Why are concatenated String15's promoted to String31?

I found this bug (I guess it is mine) when trying to @reset an element of an SVector{String15} after updating Accessors from 0.1.38 to 0.1.39, but not sure why it used to work.

MWE:

julia> using InlineStrings

julia> x = String15("A")
"A"

julia> y = x*String15("B")
"AB"

julia> typeof(y)
String31

It was fixed by wrapping the result in another String15(), but it seems like the default should be to keep the same type.

The concatenation of two length-15 strings produce a length-30 string, which can’t be represented by a String15. To ensure type-stability, the result of concatenating String15s must not depend on their length.

3 Likes

Using an internal function of InlineStrings addcodeunit a workaround can be managed:

appendstring(x,y) = 
  foldl(codeunits(y); init=(x,false)) do (a,enough),b
      enough ? (a,enough) : InlineStrings.addcodeunit(a,b)
  end |> first

with this function:

julia> x = String15("A");

julia> y = appendstring(x,String15("B"))
"AB"

julia> typeof(y)
String15

WARNING: This uses an internal function which is not a public interface of InlineStrings.

1 Like