From d2399e6349a87f387d7193a205d89fbf1edf25ee Mon Sep 17 00:00:00 2001 From: Jishnu Bhattacharya Date: Tue, 7 May 2024 14:38:25 +0530 Subject: [PATCH] Assume `:foldable` in `isuppercase`/`islowercase` for `Char` (#54346) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With this, `isuppercase`/`islowercase` are evaluated at compile-time for `Char` arguments: ```julia julia> @code_typed (() -> isuppercase('A'))() CodeInfo( 1 ─ return true ) => Bool julia> @code_typed (() -> islowercase('A'))() CodeInfo( 1 ─ return false ) => Bool ``` This would be useful in https://github.com/JuliaLang/julia/pull/54303, where the case of the character indicates which triangular half of a matrix is filled, and may be constant-propagated downstream. --------- Co-authored-by: Shuhei Kadowaki <40514306+aviatesk@users.noreply.github.com> --- base/strings/unicode.jl | 9 ++++++--- test/char.jl | 18 ++++++++++++++++++ 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/base/strings/unicode.jl b/base/strings/unicode.jl index a3b06063b98ac..cc02412925d14 100644 --- a/base/strings/unicode.jl +++ b/base/strings/unicode.jl @@ -5,7 +5,8 @@ module Unicode import Base: show, ==, hash, string, Symbol, isless, length, eltype, convert, isvalid, ismalformed, isoverlong, iterate, - AnnotatedString, AnnotatedChar, annotated_chartransform + AnnotatedString, AnnotatedChar, annotated_chartransform, + @assume_effects # whether codepoints are valid Unicode scalar values, i.e. 0-0xd7ff, 0xe000-0x10ffff @@ -385,7 +386,8 @@ julia> islowercase('❤') false ``` """ -islowercase(c::AbstractChar) = ismalformed(c) ? false : Bool(ccall(:utf8proc_islower, Cint, (UInt32,), UInt32(c))) +islowercase(c::AbstractChar) = ismalformed(c) ? false : + Bool(@assume_effects :foldable @ccall utf8proc_islower(UInt32(c)::UInt32)::Cint) # true for Unicode upper and mixed case @@ -409,7 +411,8 @@ julia> isuppercase('❤') false ``` """ -isuppercase(c::AbstractChar) = ismalformed(c) ? false : Bool(ccall(:utf8proc_isupper, Cint, (UInt32,), UInt32(c))) +isuppercase(c::AbstractChar) = ismalformed(c) ? false : + Bool(@assume_effects :foldable @ccall utf8proc_isupper(UInt32(c)::UInt32)::Cint) """ iscased(c::AbstractChar) -> Bool diff --git a/test/char.jl b/test/char.jl index 1d3579013ad18..5a522dfd1c743 100644 --- a/test/char.jl +++ b/test/char.jl @@ -360,3 +360,21 @@ end @test Base.IteratorSize(Char) == Base.HasShape{0}() @test convert(ASCIIChar, 1) == Char(1) end + +@testset "foldable isuppercase/islowercase" begin + v = @inferred (() -> Val(isuppercase('C')))() + @test v isa Val{true} + v = @inferred (() -> Val(islowercase('C')))() + @test v isa Val{false} + + struct MyChar <: AbstractChar + x :: Char + end + Base.codepoint(m::MyChar) = codepoint(m.x) + MyChar(x::UInt32) = MyChar(Char(x)) + + v = @inferred (() -> Val(isuppercase(MyChar('C'))))() + @test v isa Val{true} + v = @inferred (() -> Val(islowercase(MyChar('C'))))() + @test v isa Val{false} +end