🐙

[Bug #21450] String#upcase と Symbol#upcase の結果が一致しないケースがあるというバグ報告

に公開

[Bug #21450] Inconsistent upcase between String and Symbol

  • i に対して .upcase(:turkic) を呼び出したときに String#upcaseSymbol#upcase の結果が一致しないというバグ報告
    • :turkic を渡すと チュルク語族 (トルコ語、アゼルバイジャン語など) に適合した完全な Unicode ケースマッピングです。これはたとえば大文字の I は小文字のドットなしの i (ı) にマッピングされることを意味します。
    • see: https://docs.ruby-lang.org/ja/latest/method/String/i/downcase.html
p 'i'.upcase(:turkic)
# =>  "İ" ドットがある
p :i.upcase(:turkic)
# =>  :I ドットがない
  • これは非ASCII文字が含まれている場合は再現しないみたい
p 'iい'.upcase(:turkic)
# =>  "İい"
p :iい.upcase(:turkic)
# =>  :İい
  • これなんですが文字列リテラルの場合は『ソースエンコーディング(デフォルトだと UTF-8)がエンコーディングに設定される』
p "i".encoding # => #<Encoding:UTF-8>
  • 一方でシンボルリテラルの場合は『ASCII 7bit 文字だけの場合は US-ASCII がエンコーディングに設定される』
# ASCII 7bit 文字だけの場合は US-ASCII になる
p :i.encoding # => #<Encoding:US-ASCII>

# 非ASCII 7bit 文字がある場合は UTF-8 になる
p :iい.encoding
  • この違いによって #upcase(:turkic) の結果も違ってくるみたいですね
  • 次のようにエンコーディングを US-ASCII にするとシンボルと同じ結果になる
p "i".encode("US-ASCII").upcase(:turkic) #=> "I"
GitHubで編集を提案

Discussion