From 0f43d993b5d6de5ca7a8783bd36a367cc3aed186 Mon Sep 17 00:00:00 2001 From: Neven Sajko Date: Sun, 2 Mar 2025 14:24:11 +0100 Subject: [PATCH 1/6] strings: type assert `Int` in the generic `nextind`, `prevind` methods The type assertions are valid according to the doc strings of these two functions in the case of `AbstractString`. Should prevent some invalidation of user code. Fixes #57605 --- base/strings/basic.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/base/strings/basic.jl b/base/strings/basic.jl index 6c93ff881e6aa..c67e0f2a66480 100644 --- a/base/strings/basic.jl +++ b/base/strings/basic.jl @@ -514,7 +514,7 @@ function prevind(s::AbstractString, i::Int, n::Int) while n > 0 && 1 < i @inbounds n -= isvalid(s, i -= 1) end - return i - n + return (i - n)::Int end """ @@ -573,7 +573,7 @@ function nextind(s::AbstractString, i::Int, n::Int) while n > 0 && i < z @inbounds n -= isvalid(s, i += 1) end - return i + n + return (i + n)::Int end ## string index iteration type ## From f8c883f6be948d928dc00034517cf8d327099a03 Mon Sep 17 00:00:00 2001 From: Neven Sajko Date: Sun, 2 Mar 2025 14:37:23 +0100 Subject: [PATCH 2/6] add test --- test/strings/basic.jl | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/strings/basic.jl b/test/strings/basic.jl index f90ce8c697ed8..c3e0bcc501070 100644 --- a/test/strings/basic.jl +++ b/test/strings/basic.jl @@ -877,6 +877,11 @@ end end end end + + @testset "return type infers to `Int`" begin + @test Int === Base.infer_return_type(prevind, Tuple{AbstractString, Vararg}) + @test Int === Base.infer_return_type(nextind, Tuple{AbstractString, Vararg}) + end end @testset "first and last" begin From 1c86f6d200ec90ea12f82f231243edc10dddadd4 Mon Sep 17 00:00:00 2001 From: Neven Sajko Date: Sun, 2 Mar 2025 16:57:05 +0100 Subject: [PATCH 3/6] stronger assertions --- base/strings/basic.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/base/strings/basic.jl b/base/strings/basic.jl index c67e0f2a66480..5a01fa770ed98 100644 --- a/base/strings/basic.jl +++ b/base/strings/basic.jl @@ -514,7 +514,7 @@ function prevind(s::AbstractString, i::Int, n::Int) while n > 0 && 1 < i @inbounds n -= isvalid(s, i -= 1) end - return (i - n)::Int + return i::Int - n::Int end """ @@ -573,7 +573,7 @@ function nextind(s::AbstractString, i::Int, n::Int) while n > 0 && i < z @inbounds n -= isvalid(s, i += 1) end - return (i + n)::Int + return i::Int + n::Int end ## string index iteration type ## From 17e384ef20c68d5a448b060dab9b834adfac7311 Mon Sep 17 00:00:00 2001 From: Neven Sajko Date: Sun, 2 Mar 2025 22:03:40 +0100 Subject: [PATCH 4/6] delete unnecessary type asserts on `i` --- base/strings/basic.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/base/strings/basic.jl b/base/strings/basic.jl index 5a01fa770ed98..5b5605dd82822 100644 --- a/base/strings/basic.jl +++ b/base/strings/basic.jl @@ -514,7 +514,7 @@ function prevind(s::AbstractString, i::Int, n::Int) while n > 0 && 1 < i @inbounds n -= isvalid(s, i -= 1) end - return i::Int - n::Int + return i - n::Int end """ @@ -573,7 +573,7 @@ function nextind(s::AbstractString, i::Int, n::Int) while n > 0 && i < z @inbounds n -= isvalid(s, i += 1) end - return i::Int + n::Int + return i + n::Int end ## string index iteration type ## From 400ca90d2b75a6f81cbf023b34ffa7fd8ddd9480 Mon Sep 17 00:00:00 2001 From: Neven Sajko Date: Sun, 2 Mar 2025 22:04:57 +0100 Subject: [PATCH 5/6] instead of doing `n::Int` do `isvalid(...)::Bool` --- base/strings/basic.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/base/strings/basic.jl b/base/strings/basic.jl index 5b5605dd82822..9abdeda537f70 100644 --- a/base/strings/basic.jl +++ b/base/strings/basic.jl @@ -512,9 +512,9 @@ function prevind(s::AbstractString, i::Int, n::Int) @boundscheck 0 < i ≤ z || throw(BoundsError(s, i)) n == 0 && return thisind(s, i) == i ? i : string_index_err(s, i) while n > 0 && 1 < i - @inbounds n -= isvalid(s, i -= 1) + @inbounds n -= isvalid(s, i -= 1)::Bool end - return i - n::Int + return i - n end """ @@ -571,9 +571,9 @@ function nextind(s::AbstractString, i::Int, n::Int) @boundscheck 0 ≤ i ≤ z || throw(BoundsError(s, i)) n == 0 && return thisind(s, i) == i ? i : string_index_err(s, i) while n > 0 && i < z - @inbounds n -= isvalid(s, i += 1) + @inbounds n -= isvalid(s, i += 1)::Bool end - return i + n::Int + return i + n end ## string index iteration type ## From 7b174df7c366002ee66282977697e3f95975f434 Mon Sep 17 00:00:00 2001 From: Neven Sajko Date: Sun, 2 Mar 2025 22:08:13 +0100 Subject: [PATCH 6/6] also type assert `thisind` and `ncodeunits` calls Maybe it prevents more invalidation. --- base/strings/basic.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/base/strings/basic.jl b/base/strings/basic.jl index 9abdeda537f70..3748424a18aa7 100644 --- a/base/strings/basic.jl +++ b/base/strings/basic.jl @@ -508,9 +508,9 @@ prevind(s::AbstractString, i::Int) = prevind(s, i, 1) function prevind(s::AbstractString, i::Int, n::Int) n < 0 && throw(ArgumentError("n cannot be negative: $n")) - z = ncodeunits(s) + 1 + z = ncodeunits(s)::Int + 1 @boundscheck 0 < i ≤ z || throw(BoundsError(s, i)) - n == 0 && return thisind(s, i) == i ? i : string_index_err(s, i) + n == 0 && return thisind(s, i)::Int == i ? i : string_index_err(s, i) while n > 0 && 1 < i @inbounds n -= isvalid(s, i -= 1)::Bool end @@ -567,9 +567,9 @@ nextind(s::AbstractString, i::Int) = nextind(s, i, 1) function nextind(s::AbstractString, i::Int, n::Int) n < 0 && throw(ArgumentError("n cannot be negative: $n")) - z = ncodeunits(s) + z = ncodeunits(s)::Int @boundscheck 0 ≤ i ≤ z || throw(BoundsError(s, i)) - n == 0 && return thisind(s, i) == i ? i : string_index_err(s, i) + n == 0 && return thisind(s, i)::Int == i ? i : string_index_err(s, i) while n > 0 && i < z @inbounds n -= isvalid(s, i += 1)::Bool end