Skip to content

Commit 185f058

Browse files
authored
Specialised substring equality for annotated strs (#54302)
The least-bad idea I've had so far for fixing #53042. I figure this fixes the bug raised there, and we can always switch to a clearly-better solution if one appears. The fact that only a string without annotations is equal to a non-annotated string (in order to preserve the transitivity of equality), makes the generic fallback methods for string comparison insufficient. As such, ==(::AnnoatedString, ::AbstractString) is implemented in annotated.jl, but this issue re-appears when dealing with substrings. The obvious solution is to just implement a specialised method for substrings. This does seem potentially a bit whack-a-mole, but I'm worried that cleverer solutions might come with subtle issues of their own. For now, let's try the simple and obvious solution, and improve it later if we can work out a nicer way of handling this issue in general.
1 parent c0ce76c commit 185f058

File tree

2 files changed

+22
-0
lines changed

2 files changed

+22
-0
lines changed

base/strings/annotated.jl

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,24 @@ cmp(a::AnnotatedString, b::AnnotatedString) = cmp(a.string, b.string)
203203
==(a::AnnotatedString, b::AbstractString) = isempty(a.annotations) && a.string == b
204204
==(a::AbstractString, b::AnnotatedString) = isempty(b.annotations) && a == b.string
205205

206+
# To prevent substring equality from hitting the generic fallback
207+
208+
function ==(a::SubString{<:AnnotatedString}, b::SubString{<:AnnotatedString})
209+
SubString(a.string.string, a.offset, a.ncodeunits, Val(:noshift)) ==
210+
SubString(b.string.string, b.offset, b.ncodeunits, Val(:noshift)) &&
211+
annotations(a) == annotations(b)
212+
end
213+
214+
==(a::SubString{<:AnnotatedString}, b::AnnotatedString) =
215+
annotations(a) == annotations(b) && SubString(a.string.string, a.offset, a.ncodeunits, Val(:noshift)) == b.string
216+
217+
==(a::SubString{<:AnnotatedString}, b::AbstractString) =
218+
isempty(annotations(a)) && SubString(a.string.string, a.offset, a.ncodeunits, Val(:noshift)) == b
219+
220+
==(a::AbstractString, b::SubString{<:AnnotatedString}) = b == a
221+
222+
==(a::AnnotatedString, b::SubString{<:AnnotatedString}) = b == a
223+
206224
"""
207225
annotatedstring(values...)
208226

test/strings/annotated.jl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
@test "a" * str == Base.AnnotatedString("asome string")
1313
@test str * "a" == Base.AnnotatedString("some stringa")
1414
@test str * str == Base.AnnotatedString("some stringsome string")
15+
@test str[3:4] == SubString("me")
16+
@test SubString("me") == str[3:4]
1517
Base.annotate!(str, 1:4, :thing => 0x01)
1618
Base.annotate!(str, 6:11, :other => 0x02)
1719
Base.annotate!(str, 1:11, :all => 0x03)
@@ -21,6 +23,8 @@
2123
# └───┰─────┘
2224
# :all
2325
@test str[3:4] == SubString(str, 3, 4)
26+
@test str[3:4] != SubString("me")
27+
@test SubString("me") != str[3:4]
2428
@test Base.AnnotatedString(str[3:4]) ==
2529
Base.AnnotatedString("me", [(1:2, :thing => 0x01), (1:2, :all => 0x03)])
2630
@test Base.AnnotatedString(str[3:6]) ==

0 commit comments

Comments
 (0)