# <!-- rdoc-file=string.rb -->
# A `String` object has an arbitrary sequence of bytes, typically representing
# text or binary data. A `String` object may be created using String::new or as
# literals.
#
# String objects differ from Symbol objects in that Symbol objects are designed
# to be used as identifiers, instead of text or data.
#
# You can create a `String` object explicitly with:
#
# *   A [string literal](rdoc-ref:syntax/literals.rdoc@String+Literals).
# *   A [heredoc literal](rdoc-ref:syntax/literals.rdoc@Here+Document+Literals).
#
# You can convert certain objects to Strings with:
#
# *   Method #String.
#
# Some `String` methods modify `self`. Typically, a method whose name ends with
# `!` modifies `self` and returns `self`; often, a similarly named method
# (without the `!`) returns a new string.
#
# In general, if both bang and non-bang versions of a method exist, the bang
# method mutates and the non-bang method does not. However, a method without a
# bang can also mutate, such as String#replace.
#
# ## Substitution Methods
#
# These methods perform substitutions:
#
# *   String#sub: One substitution (or none); returns a new string.
# *   String#sub!: One substitution (or none); returns `self` if any changes,
#     `nil` otherwise.
# *   String#gsub: Zero or more substitutions; returns a new string.
# *   String#gsub!: Zero or more substitutions; returns `self` if any changes,
#     `nil` otherwise.
#
# Each of these methods takes:
#
# *   A first argument, `pattern` (String or Regexp), that specifies the
#     substring(s) to be replaced.
#
# *   Either of the following:
#
#     *   A second argument, `replacement` (String or Hash), that determines the
#         replacing string.
#     *   A block that will determine the replacing string.
#
# The examples in this section mostly use the String#sub and String#gsub
# methods; the principles illustrated apply to all four substitution methods.
#
# **Argument `pattern`**
#
# Argument `pattern` is commonly a regular expression:
#
#     s = 'hello'
#     s.sub(/[aeiou]/, '*') # => "h*llo"
#     s.gsub(/[aeiou]/, '*') # => "h*ll*"
#     s.gsub(/[aeiou]/, '')  # => "hll"
#     s.sub(/ell/, 'al')     # => "halo"
#     s.gsub(/xyzzy/, '*')   # => "hello"
#     'THX1138'.gsub(/\d+/, '00') # => "THX00"
#
# When `pattern` is a string, all its characters are treated as ordinary
# characters (not as Regexp special characters):
#
#     'THX1138'.gsub('\d+', '00') # => "THX1138"
#
# **`String` `replacement`**
#
# If `replacement` is a string, that string determines the replacing string that
# is substituted for the matched text.
#
# Each of the examples above uses a simple string as the replacing string.
#
# `String` `replacement` may contain back-references to the pattern's captures:
#
# *   `\n` (*n* is a non-negative integer) refers to `$n`.
# *   `\k<name>` refers to the named capture `name`.
#
# See Regexp for details.
#
# Note that within the string `replacement`, a character combination such as
# `$&` is treated as ordinary text, not as a special match variable. However,
# you may refer to some special match variables using these combinations:
#
# *   `\&` and `\0` correspond to `$&`, which contains the complete matched
#     text.
# *   `\'` corresponds to `$'`, which contains the string after the match.
# *   `\`` corresponds to `$``, which contains the string before the match.
# *   `\+` corresponds to `$+`, which contains the last capture group.
#
# See Regexp for details.
#
# Note that `\\\` is interpreted as an escape, i.e., a single backslash.
#
# Note also that a string literal consumes backslashes. See [String
# Literals](rdoc-ref:syntax/literals.rdoc@String+Literals) for details about
# string literals.
#
# A back-reference is typically preceded by an additional backslash. For
# example, if you want to write a back-reference `\&` in `replacement` with a
# double-quoted string literal, you need to write `"..\\\\&.."`.
#
# If you want to write a non-back-reference string `\&` in `replacement`, you
# need to first escape the backslash to prevent this method from interpreting it
# as a back-reference, and then you need to escape the backslashes again to
# prevent a string literal from consuming them: `"..\\\\\\\\&.."`.
#
# You may want to use the block form to avoid excessive backslashes.
#
# **\Hash `replacement`**
#
# If the argument `replacement` is a hash, and `pattern` matches one of its
# keys, the replacing string is the value for that key:
#
#     h = {'foo' => 'bar', 'baz' => 'bat'}
#     'food'.sub('foo', h) # => "bard"
#
# Note that a symbol key does not match:
#
#     h = {foo: 'bar', baz: 'bat'}
#     'food'.sub('foo', h) # => "d"
#
# **Block**
#
# In the block form, the current match string is passed to the block; the
# block's return value becomes the replacing string:
#
#     s = '@'
#     '1234'.gsub(/\d/) { |match| s.succ! } # => "ABCD"
#
# Special match variables such as `$1`, `$2`, `$``, `$&`, and `$'` are set
# appropriately.
#
# ## Whitespace in Strings
#
# In the class `String`, *whitespace* is defined as a contiguous sequence of
# characters consisting of any mixture of the following:
#
# *   NL (null): `"\x00"`, `"\u0000"`.
# *   HT (horizontal tab): `"\x09"`, `"\t"`.
# *   LF (line feed): `"\x0a"`, `"\n"`.
# *   VT (vertical tab): `"\x0b"`, `"\v"`.
# *   FF (form feed): `"\x0c"`, `"\f"`.
# *   CR (carriage return): `"\x0d"`, `"\r"`.
# *   SP (space): `"\x20"`, `" "`.
#
# Whitespace is relevant for the following methods:
#
# *   #lstrip, #lstrip!: Strip leading whitespace.
# *   #rstrip, #rstrip!: Strip trailing whitespace.
# *   #strip, #strip!: Strip leading and trailing whitespace.
#
# ## What's Here
#
# First, what's elsewhere. Class `String`:
#
# *   Inherits from the [Object class](rdoc-ref:Object@What-27s+Here).
# *   Includes the [Comparable module](rdoc-ref:Comparable@What-27s+Here).
#
# Here, class `String` provides methods that are useful for:
#
# *   [Creating a \String](rdoc-ref:String@Creating+a+String).
# *   [Freezing/Unfreezing a \String](rdoc-ref:String@Freezing-2FUnfreezing).
# *   [Querying a \String](rdoc-ref:String@Querying).
# *   [Comparing Strings](rdoc-ref:String@Comparing).
# *   [Modifying a \String](rdoc-ref:String@Modifying).
# *   [Converting to a new \String](rdoc-ref:String@Converting+to+New+String).
# *   [Converting to a
#     non-\String](rdoc-ref:String@Converting+to+Non--5CString).
# *   [Iterating over a \String](rdoc-ref:String@Iterating).
#
# ### Creating a String
#
# *   ::new: Returns a new string.
# *   ::try_convert: Returns a new string created from a given object.
#
# ### Freezing/Unfreezing
#
# *   #+@: Returns a string that is not frozen: `self` if not frozen; `self.dup`
#     otherwise.
# *   #-@ (aliased as #dedup): Returns a string that is frozen: `self` if
#     already frozen; `self.freeze` otherwise.
# *   #freeze: Freezes `self` if not already frozen; returns `self`.
#
# ### Querying
#
# *Counts*
#
# *   #bytesize: Returns the count of bytes.
# *   #count: Returns the count of substrings matching given strings.
# *   #empty?: Returns whether the length of `self` is zero.
# *   #length (aliased as #size): Returns the count of characters (not bytes).
#
# *Substrings*
#
# *   #=~: Returns the index of the first substring that matches a given Regexp
#     or other object; returns `nil` if no match is found.
# *   #byteindex: Returns the byte index of the first occurrence of a given
#     substring.
# *   #byterindex: Returns the byte index of the last occurrence of a given
#     substring.
# *   #index: Returns the index of the *first* occurrence of a given substring;
#     returns `nil` if none found.
# *   #rindex: Returns the index of the *last* occurrence of a given substring;
#     returns `nil` if none found.
# *   #include?: Returns `true` if the string contains a given substring;
#     `false` otherwise.
# *   #match: Returns a MatchData object if the string matches a given Regexp;
#     `nil` otherwise.
# *   #match?: Returns `true` if the string matches a given Regexp; `false`
#     otherwise.
# *   #start_with?: Returns `true` if the string begins with any of the given
#     substrings.
# *   #end_with?: Returns `true` if the string ends with any of the given
#     substrings.
#
# *Encodings*
#
# *   #encoding: Returns the Encoding object that represents the encoding of the
#     string.
# *   #unicode_normalized?: Returns `true` if the string is in Unicode
#     normalized form; `false` otherwise.
# *   #valid_encoding?: Returns `true` if the string contains only characters
#     that are valid for its encoding.
# *   #ascii_only?: Returns `true` if the string has only ASCII characters;
#     `false` otherwise.
#
# *Other*
#
# *   #sum: Returns a basic checksum for the string: the sum of each byte.
# *   #hash: Returns the integer hash code.
#
# ### Comparing
#
# *   #== (aliased as #===): Returns `true` if a given other string has the same
#     content as `self`.
# *   #eql?: Returns `true` if the content is the same as the given other
#     string.
# *   #<=>: Returns -1, 0, or 1 as a given other string is smaller than, equal
#     to, or larger than `self`.
# *   #casecmp: Ignoring case, returns -1, 0, or 1 as `self` is smaller than,
#     equal to, or larger than a given other string.
# *   #casecmp?: Ignoring case, returns whether a given other string is equal to
#     `self`.
#
# ### Modifying
#
# Each of these methods modifies `self`.
#
# *Insertion*
#
# *   #insert: Returns `self` with a given string inserted at a specified
#     offset.
# *   #<<: Returns `self` concatenated with a given string or integer.
# *   #append_as_bytes: Returns `self` concatenated with strings without
#     performing any encoding validation or conversion.
# *   #prepend: Prefixes to `self` the concatenation of given other strings.
#
# *Substitution*
#
# *   #bytesplice: Replaces bytes of `self` with bytes from a given string;
#     returns `self`.
# *   #sub!: Replaces the first substring that matches a given pattern with a
#     given replacement string; returns `self` if any changes, `nil` otherwise.
# *   #gsub!: Replaces each substring that matches a given pattern with a given
#     replacement string; returns `self` if any changes, `nil` otherwise.
# *   #succ! (aliased as #next!): Returns `self` modified to become its own
#     successor.
# *   #replace: Returns `self` with its entire content replaced by a given
#     string.
# *   #reverse!: Returns `self` with its characters in reverse order.
# *   #setbyte: Sets the byte at a given integer offset to a given value;
#     returns the argument.
# *   #tr!: Replaces specified characters in `self` with specified replacement
#     characters; returns `self` if any changes, `nil` otherwise.
# *   #tr_s!: Replaces specified characters in `self` with specified replacement
#     characters, removing duplicates from the substrings that were modified;
#     returns `self` if any changes, `nil` otherwise.
#
# *Casing*
#
# *   #capitalize!: Upcases the initial character and downcases all others;
#     returns `self` if any changes, `nil` otherwise.
# *   #downcase!: Downcases all characters; returns `self` if any changes, `nil`
#     otherwise.
# *   #upcase!: Upcases all characters; returns `self` if any changes, `nil`
#     otherwise.
# *   #swapcase!: Upcases each downcase character and downcases each upcase
#     character; returns `self` if any changes, `nil` otherwise.
#
# *Encoding*
#
# *   #encode!: Returns `self` with all characters transcoded from one encoding
#     to another.
# *   #unicode_normalize!: Unicode-normalizes `self`; returns `self`.
# *   #scrub!: Replaces each invalid byte with a given character; returns
#     `self`.
# *   #force_encoding: Changes the encoding to a given encoding; returns `self`.
#
# *Deletion*
#
# *   #clear: Removes all content, so that `self` is empty; returns `self`.
# *   #slice!, #[]=: Removes a substring determined by a given index,
#     start/length, range, regexp, or substring.
# *   #squeeze!: Removes contiguous duplicate characters; returns `self`.
# *   #delete!: Removes characters as determined by the intersection of
#     substring arguments.
# *   #delete_prefix!: Removes leading prefix; returns `self` if any changes,
#     `nil` otherwise.
# *   #delete_suffix!: Removes trailing suffix; returns `self` if any changes,
#     `nil` otherwise.
# *   #lstrip!: Removes leading whitespace; returns `self` if any changes, `nil`
#     otherwise.
# *   #rstrip!: Removes trailing whitespace; returns `self` if any changes,
#     `nil` otherwise.
# *   #strip!: Removes leading and trailing whitespace; returns `self` if any
#     changes, `nil` otherwise.
# *   #chomp!: Removes the trailing record separator, if found; returns `self`
#     if any changes, `nil` otherwise.
# *   #chop!: Removes trailing newline characters if found; otherwise removes
#     the last character; returns `self` if any changes, `nil` otherwise.
#
# ### Converting to New String
#
# Each of these methods returns a new `String` based on `self`, often just a
# modified copy of `self`.
#
# *Extension*
#
# *   #*: Returns the concatenation of multiple copies of `self`.
# *   #+: Returns the concatenation of `self` and a given other string.
# *   #center: Returns a copy of `self`, centered by specified padding.
# *   #concat: Returns the concatenation of `self` with given other strings.
# *   #ljust: Returns a copy of `self` of a given length, right-padded with a
#     given other string.
# *   #rjust: Returns a copy of `self` of a given length, left-padded with a
#     given other string.
#
# *Encoding*
#
# *   #b: Returns a copy of `self` with ASCII-8BIT encoding.
# *   #scrub: Returns a copy of `self` with each invalid byte replaced with a
#     given character.
# *   #unicode_normalize: Returns a copy of `self` with each character
#     Unicode-normalized.
# *   #encode: Returns a copy of `self` with all characters transcoded from one
#     encoding to another.
#
# *Substitution*
#
# *   #dump: Returns a printable version of `self`, enclosed in double-quotes.
# *   #undump: Inverse of #dump; returns a copy of `self` with changes of the
#     kinds made by #dump "undone."
# *   #sub: Returns a copy of `self` with the first substring matching a given
#     pattern replaced with a given replacement string.
# *   #gsub: Returns a copy of `self` with each substring that matches a given
#     pattern replaced with a given replacement string.
# *   #succ (aliased as #next): Returns the string that is the successor to
#     `self`.
# *   #reverse: Returns a copy of `self` with its characters in reverse order.
# *   #tr: Returns a copy of `self` with specified characters replaced with
#     specified replacement characters.
# *   #tr_s: Returns a copy of `self` with specified characters replaced with
#     specified replacement characters, removing duplicates from the substrings
#     that were modified.
# *   #%: Returns the string resulting from formatting a given object into
#     `self`.
#
# *Casing*
#
# *   #capitalize: Returns a copy of `self` with the first character upcased and
#     all other characters downcased.
# *   #downcase: Returns a copy of `self` with all characters downcased.
# *   #upcase: Returns a copy of `self` with all characters upcased.
# *   #swapcase: Returns a copy of `self` with all upcase characters downcased
#     and all downcase characters upcased.
#
# *Deletion*
#
# *   #delete: Returns a copy of `self` with characters removed.
# *   #delete_prefix: Returns a copy of `self` with a given prefix removed.
# *   #delete_suffix: Returns a copy of `self` with a given suffix removed.
# *   #lstrip: Returns a copy of `self` with leading whitespace removed.
# *   #rstrip: Returns a copy of `self` with trailing whitespace removed.
# *   #strip: Returns a copy of `self` with leading and trailing whitespace
#     removed.
# *   #chomp: Returns a copy of `self` with a trailing record separator removed,
#     if found.
# *   #chop: Returns a copy of `self` with trailing newline characters or the
#     last character removed.
# *   #squeeze: Returns a copy of `self` with contiguous duplicate characters
#     removed.
# *   #[] (aliased as #slice): Returns a substring determined by a given index,
#     start/length, range, regexp, or string.
# *   #byteslice: Returns a substring determined by a given index, start/length,
#     or range.
# *   #chr: Returns the first character.
#
# *Duplication*
#
# *   #to_s (aliased as #to_str): If `self` is a subclass of `String`, returns
#     `self` copied into a `String`; otherwise, returns `self`.
#
# ### Converting to Non-String
#
# Each of these methods converts the contents of `self` to a non-`String`.
#
# *Characters, Bytes, and Clusters*
#
# *   #bytes: Returns an array of the bytes in `self`.
# *   #chars: Returns an array of the characters in `self`.
# *   #codepoints: Returns an array of the integer ordinals in `self`.
# *   #getbyte: Returns the integer byte at the given index in `self`.
# *   #grapheme_clusters: Returns an array of the grapheme clusters in `self`.
#
# *Splitting*
#
# *   #lines: Returns an array of the lines in `self`, as determined by a given
#     record separator.
# *   #partition: Returns a 3-element array determined by the first substring
#     that matches a given substring or regexp.
# *   #rpartition: Returns a 3-element array determined by the last substring
#     that matches a given substring or regexp.
# *   #split: Returns an array of substrings determined by a given delimiter --
#     regexp or string -- or, if a block is given, passes those substrings to
#     the block.
#
# *Matching*
#
# *   #scan: Returns an array of substrings matching a given regexp or string,
#     or, if a block is given, passes each matching substring to the block.
# *   #unpack: Returns an array of substrings extracted from `self` according to
#     a given format.
# *   #unpack1: Returns the first substring extracted from `self` according to a
#     given format.
#
# *Numerics*
#
# *   #hex: Returns the integer value of the leading characters, interpreted as
#     hexadecimal digits.
# *   #oct: Returns the integer value of the leading characters, interpreted as
#     octal digits.
# *   #ord: Returns the integer ordinal of the first character in `self`.
# *   #to_c: Returns the complex value of leading characters, interpreted as a
#     complex number.
# *   #to_i: Returns the integer value of leading characters, interpreted as an
#     integer.
# *   #to_f: Returns the floating-point value of leading characters, interpreted
#     as a floating-point number.
# *   #to_r: Returns the rational value of leading characters, interpreted as a
#     rational.
#
# *Strings and Symbols*
#
# *   #inspect: Returns a copy of `self`, enclosed in double quotes, with
#     special characters escaped.
# *   #intern (aliased as #to_sym): Returns the symbol corresponding to `self`.
#
# ### Iterating
#
# *   #each_byte: Calls the given block with each successive byte in `self`.
# *   #each_char: Calls the given block with each successive character in
#     `self`.
# *   #each_codepoint: Calls the given block with each successive integer
#     codepoint in `self`.
# *   #each_grapheme_cluster: Calls the given block with each successive
#     grapheme cluster in `self`.
# *   #each_line: Calls the given block with each successive line in `self`, as
#     determined by a given record separator.
# *   #upto: Calls the given block with each string value returned by successive
#     calls to #succ.
#
# <!-- rdoc-file=string.rb -->
# A `String` object has an arbitrary sequence of bytes, typically representing
# text or binary data. A `String` object may be created using String::new or as
# literals.
#
# String objects differ from Symbol objects in that Symbol objects are designed
# to be used as identifiers, instead of text or data.
#
# You can create a `String` object explicitly with:
#
# *   A [string literal](rdoc-ref:syntax/literals.rdoc@String+Literals).
# *   A [heredoc literal](rdoc-ref:syntax/literals.rdoc@Here+Document+Literals).
#
# You can convert certain objects to Strings with:
#
# *   Method #String.
#
# Some `String` methods modify `self`. Typically, a method whose name ends with
# `!` modifies `self` and returns `self`; often, a similarly named method
# (without the `!`) returns a new string.
#
# In general, if both bang and non-bang versions of a method exist, the bang
# method mutates and the non-bang method does not. However, a method without a
# bang can also mutate, such as String#replace.
#
# ## Substitution Methods
#
# These methods perform substitutions:
#
# *   String#sub: One substitution (or none); returns a new string.
# *   String#sub!: One substitution (or none); returns `self` if any changes,
#     `nil` otherwise.
# *   String#gsub: Zero or more substitutions; returns a new string.
# *   String#gsub!: Zero or more substitutions; returns `self` if any changes,
#     `nil` otherwise.
#
# Each of these methods takes:
#
# *   A first argument, `pattern` (String or Regexp), that specifies the
#     substring(s) to be replaced.
#
# *   Either of the following:
#
#     *   A second argument, `replacement` (String or Hash), that determines the
#         replacing string.
#     *   A block that will determine the replacing string.
#
# The examples in this section mostly use the String#sub and String#gsub
# methods; the principles illustrated apply to all four substitution methods.
#
# **Argument `pattern`**
#
# Argument `pattern` is commonly a regular expression:
#
#     s = 'hello'
#     s.sub(/[aeiou]/, '*') # => "h*llo"
#     s.gsub(/[aeiou]/, '*') # => "h*ll*"
#     s.gsub(/[aeiou]/, '')  # => "hll"
#     s.sub(/ell/, 'al')     # => "halo"
#     s.gsub(/xyzzy/, '*')   # => "hello"
#     'THX1138'.gsub(/\d+/, '00') # => "THX00"
#
# When `pattern` is a string, all its characters are treated as ordinary
# characters (not as Regexp special characters):
#
#     'THX1138'.gsub('\d+', '00') # => "THX1138"
#
# **`String` `replacement`**
#
# If `replacement` is a string, that string determines the replacing string that
# is substituted for the matched text.
#
# Each of the examples above uses a simple string as the replacing string.
#
# `String` `replacement` may contain back-references to the pattern's captures:
#
# *   `\n` (*n* is a non-negative integer) refers to `$n`.
# *   `\k<name>` refers to the named capture `name`.
#
# See Regexp for details.
#
# Note that within the string `replacement`, a character combination such as
# `$&` is treated as ordinary text, not as a special match variable. However,
# you may refer to some special match variables using these combinations:
#
# *   `\&` and `\0` correspond to `$&`, which contains the complete matched
#     text.
# *   `\'` corresponds to `$'`, which contains the string after the match.
# *   `\`` corresponds to `$``, which contains the string before the match.
# *   `\+` corresponds to `$+`, which contains the last capture group.
#
# See Regexp for details.
#
# Note that `\\\` is interpreted as an escape, i.e., a single backslash.
#
# Note also that a string literal consumes backslashes. See [String
# Literals](rdoc-ref:syntax/literals.rdoc@String+Literals) for details about
# string literals.
#
# A back-reference is typically preceded by an additional backslash. For
# example, if you want to write a back-reference `\&` in `replacement` with a
# double-quoted string literal, you need to write `"..\\\\&.."`.
#
# If you want to write a non-back-reference string `\&` in `replacement`, you
# need to first escape the backslash to prevent this method from interpreting it
# as a back-reference, and then you need to escape the backslashes again to
# prevent a string literal from consuming them: `"..\\\\\\\\&.."`.
#
# You may want to use the block form to avoid excessive backslashes.
#
# **\Hash `replacement`**
#
# If the argument `replacement` is a hash, and `pattern` matches one of its
# keys, the replacing string is the value for that key:
#
#     h = {'foo' => 'bar', 'baz' => 'bat'}
#     'food'.sub('foo', h) # => "bard"
#
# Note that a symbol key does not match:
#
#     h = {foo: 'bar', baz: 'bat'}
#     'food'.sub('foo', h) # => "d"
#
# **Block**
#
# In the block form, the current match string is passed to the block; the
# block's return value becomes the replacing string:
#
#     s = '@'
#     '1234'.gsub(/\d/) { |match| s.succ! } # => "ABCD"
#
# Special match variables such as `$1`, `$2`, `$``, `$&`, and `$'` are set
# appropriately.
#
# ## Whitespace in Strings
#
# In the class `String`, *whitespace* is defined as a contiguous sequence of
# characters consisting of any mixture of the following:
#
# *   NL (null): `"\x00"`, `"\u0000"`.
# *   HT (horizontal tab): `"\x09"`, `"\t"`.
# *   LF (line feed): `"\x0a"`, `"\n"`.
# *   VT (vertical tab): `"\x0b"`, `"\v"`.
# *   FF (form feed): `"\x0c"`, `"\f"`.
# *   CR (carriage return): `"\x0d"`, `"\r"`.
# *   SP (space): `"\x20"`, `" "`.
#
# Whitespace is relevant for the following methods:
#
# *   #lstrip, #lstrip!: Strip leading whitespace.
# *   #rstrip, #rstrip!: Strip trailing whitespace.
# *   #strip, #strip!: Strip leading and trailing whitespace.
#
# ## What's Here
#
# First, what's elsewhere. Class `String`:
#
# *   Inherits from the [Object class](rdoc-ref:Object@What-27s+Here).
# *   Includes the [Comparable module](rdoc-ref:Comparable@What-27s+Here).
#
# Here, class `String` provides methods that are useful for:
#
# *   [Creating a \String](rdoc-ref:String@Creating+a+String).
# *   [Freezing/Unfreezing a \String](rdoc-ref:String@Freezing-2FUnfreezing).
# *   [Querying a \String](rdoc-ref:String@Querying).
# *   [Comparing Strings](rdoc-ref:String@Comparing).
# *   [Modifying a \String](rdoc-ref:String@Modifying).
# *   [Converting to a new \String](rdoc-ref:String@Converting+to+New+String).
# *   [Converting to a
#     non-\String](rdoc-ref:String@Converting+to+Non--5CString).
# *   [Iterating over a \String](rdoc-ref:String@Iterating).
#
# ### Creating a String
#
# *   ::new: Returns a new string.
# *   ::try_convert: Returns a new string created from a given object.
#
# ### Freezing/Unfreezing
#
# *   #+@: Returns a string that is not frozen: `self` if not frozen; `self.dup`
#     otherwise.
# *   #-@ (aliased as #dedup): Returns a string that is frozen: `self` if
#     already frozen; `self.freeze` otherwise.
# *   #freeze: Freezes `self` if not already frozen; returns `self`.
#
# ### Querying
#
# *Counts*
#
# *   #bytesize: Returns the count of bytes.
# *   #count: Returns the count of substrings matching given strings.
# *   #empty?: Returns whether the length of `self` is zero.
# *   #length (aliased as #size): Returns the count of characters (not bytes).
#
# *Substrings*
#
# *   #=~: Returns the index of the first substring that matches a given Regexp
#     or other object; returns `nil` if no match is found.
# *   #byteindex: Returns the byte index of the first occurrence of a given
#     substring.
# *   #byterindex: Returns the byte index of the last occurrence of a given
#     substring.
# *   #index: Returns the index of the *first* occurrence of a given substring;
#     returns `nil` if none found.
# *   #rindex: Returns the index of the *last* occurrence of a given substring;
#     returns `nil` if none found.
# *   #include?: Returns `true` if the string contains a given substring;
#     `false` otherwise.
# *   #match: Returns a MatchData object if the string matches a given Regexp;
#     `nil` otherwise.
# *   #match?: Returns `true` if the string matches a given Regexp; `false`
#     otherwise.
# *   #start_with?: Returns `true` if the string begins with any of the given
#     substrings.
# *   #end_with?: Returns `true` if the string ends with any of the given
#     substrings.
#
# *Encodings*
#
# *   #encoding: Returns the Encoding object that represents the encoding of the
#     string.
# *   #unicode_normalized?: Returns `true` if the string is in Unicode
#     normalized form; `false` otherwise.
# *   #valid_encoding?: Returns `true` if the string contains only characters
#     that are valid for its encoding.
# *   #ascii_only?: Returns `true` if the string has only ASCII characters;
#     `false` otherwise.
#
# *Other*
#
# *   #sum: Returns a basic checksum for the string: the sum of each byte.
# *   #hash: Returns the integer hash code.
#
# ### Comparing
#
# *   #== (aliased as #===): Returns `true` if a given other string has the same
#     content as `self`.
# *   #eql?: Returns `true` if the content is the same as the given other
#     string.
# *   #<=>: Returns -1, 0, or 1 as a given other string is smaller than, equal
#     to, or larger than `self`.
# *   #casecmp: Ignoring case, returns -1, 0, or 1 as `self` is smaller than,
#     equal to, or larger than a given other string.
# *   #casecmp?: Ignoring case, returns whether a given other string is equal to
#     `self`.
#
# ### Modifying
#
# Each of these methods modifies `self`.
#
# *Insertion*
#
# *   #insert: Returns `self` with a given string inserted at a specified
#     offset.
# *   #<<: Returns `self` concatenated with a given string or integer.
# *   #append_as_bytes: Returns `self` concatenated with strings without
#     performing any encoding validation or conversion.
# *   #prepend: Prefixes to `self` the concatenation of given other strings.
#
# *Substitution*
#
# *   #bytesplice: Replaces bytes of `self` with bytes from a given string;
#     returns `self`.
# *   #sub!: Replaces the first substring that matches a given pattern with a
#     given replacement string; returns `self` if any changes, `nil` otherwise.
# *   #gsub!: Replaces each substring that matches a given pattern with a given
#     replacement string; returns `self` if any changes, `nil` otherwise.
# *   #succ! (aliased as #next!): Returns `self` modified to become its own
#     successor.
# *   #replace: Returns `self` with its entire content replaced by a given
#     string.
# *   #reverse!: Returns `self` with its characters in reverse order.
# *   #setbyte: Sets the byte at a given integer offset to a given value;
#     returns the argument.
# *   #tr!: Replaces specified characters in `self` with specified replacement
#     characters; returns `self` if any changes, `nil` otherwise.
# *   #tr_s!: Replaces specified characters in `self` with specified replacement
#     characters, removing duplicates from the substrings that were modified;
#     returns `self` if any changes, `nil` otherwise.
#
# *Casing*
#
# *   #capitalize!: Upcases the initial character and downcases all others;
#     returns `self` if any changes, `nil` otherwise.
# *   #downcase!: Downcases all characters; returns `self` if any changes, `nil`
#     otherwise.
# *   #upcase!: Upcases all characters; returns `self` if any changes, `nil`
#     otherwise.
# *   #swapcase!: Upcases each downcase character and downcases each upcase
#     character; returns `self` if any changes, `nil` otherwise.
#
# *Encoding*
#
# *   #encode!: Returns `self` with all characters transcoded from one encoding
#     to another.
# *   #unicode_normalize!: Unicode-normalizes `self`; returns `self`.
# *   #scrub!: Replaces each invalid byte with a given character; returns
#     `self`.
# *   #force_encoding: Changes the encoding to a given encoding; returns `self`.
#
# *Deletion*
#
# *   #clear: Removes all content, so that `self` is empty; returns `self`.
# *   #slice!, #[]=: Removes a substring determined by a given index,
#     start/length, range, regexp, or substring.
# *   #squeeze!: Removes contiguous duplicate characters; returns `self`.
# *   #delete!: Removes characters as determined by the intersection of
#     substring arguments.
# *   #delete_prefix!: Removes leading prefix; returns `self` if any changes,
#     `nil` otherwise.
# *   #delete_suffix!: Removes trailing suffix; returns `self` if any changes,
#     `nil` otherwise.
# *   #lstrip!: Removes leading whitespace; returns `self` if any changes, `nil`
#     otherwise.
# *   #rstrip!: Removes trailing whitespace; returns `self` if any changes,
#     `nil` otherwise.
# *   #strip!: Removes leading and trailing whitespace; returns `self` if any
#     changes, `nil` otherwise.
# *   #chomp!: Removes the trailing record separator, if found; returns `self`
#     if any changes, `nil` otherwise.
# *   #chop!: Removes trailing newline characters if found; otherwise removes
#     the last character; returns `self` if any changes, `nil` otherwise.
#
# ### Converting to New String
#
# Each of these methods returns a new `String` based on `self`, often just a
# modified copy of `self`.
#
# *Extension*
#
# *   #*: Returns the concatenation of multiple copies of `self`.
# *   #+: Returns the concatenation of `self` and a given other string.
# *   #center: Returns a copy of `self`, centered by specified padding.
# *   #concat: Returns the concatenation of `self` with given other strings.
# *   #ljust: Returns a copy of `self` of a given length, right-padded with a
#     given other string.
# *   #rjust: Returns a copy of `self` of a given length, left-padded with a
#     given other string.
#
# *Encoding*
#
# *   #b: Returns a copy of `self` with ASCII-8BIT encoding.
# *   #scrub: Returns a copy of `self` with each invalid byte replaced with a
#     given character.
# *   #unicode_normalize: Returns a copy of `self` with each character
#     Unicode-normalized.
# *   #encode: Returns a copy of `self` with all characters transcoded from one
#     encoding to another.
#
# *Substitution*
#
# *   #dump: Returns a printable version of `self`, enclosed in double-quotes.
# *   #undump: Inverse of #dump; returns a copy of `self` with changes of the
#     kinds made by #dump "undone."
# *   #sub: Returns a copy of `self` with the first substring matching a given
#     pattern replaced with a given replacement string.
# *   #gsub: Returns a copy of `self` with each substring that matches a given
#     pattern replaced with a given replacement string.
# *   #succ (aliased as #next): Returns the string that is the successor to
#     `self`.
# *   #reverse: Returns a copy of `self` with its characters in reverse order.
# *   #tr: Returns a copy of `self` with specified characters replaced with
#     specified replacement characters.
# *   #tr_s: Returns a copy of `self` with specified characters replaced with
#     specified replacement characters, removing duplicates from the substrings
#     that were modified.
# *   #%: Returns the string resulting from formatting a given object into
#     `self`.
#
# *Casing*
#
# *   #capitalize: Returns a copy of `self` with the first character upcased and
#     all other characters downcased.
# *   #downcase: Returns a copy of `self` with all characters downcased.
# *   #upcase: Returns a copy of `self` with all characters upcased.
# *   #swapcase: Returns a copy of `self` with all upcase characters downcased
#     and all downcase characters upcased.
#
# *Deletion*
#
# *   #delete: Returns a copy of `self` with characters removed.
# *   #delete_prefix: Returns a copy of `self` with a given prefix removed.
# *   #delete_suffix: Returns a copy of `self` with a given suffix removed.
# *   #lstrip: Returns a copy of `self` with leading whitespace removed.
# *   #rstrip: Returns a copy of `self` with trailing whitespace removed.
# *   #strip: Returns a copy of `self` with leading and trailing whitespace
#     removed.
# *   #chomp: Returns a copy of `self` with a trailing record separator removed,
#     if found.
# *   #chop: Returns a copy of `self` with trailing newline characters or the
#     last character removed.
# *   #squeeze: Returns a copy of `self` with contiguous duplicate characters
#     removed.
# *   #[] (aliased as #slice): Returns a substring determined by a given index,
#     start/length, range, regexp, or string.
# *   #byteslice: Returns a substring determined by a given index, start/length,
#     or range.
# *   #chr: Returns the first character.
#
# *Duplication*
#
# *   #to_s (aliased as #to_str): If `self` is a subclass of `String`, returns
#     `self` copied into a `String`; otherwise, returns `self`.
#
# ### Converting to Non-String
#
# Each of these methods converts the contents of `self` to a non-`String`.
#
# *Characters, Bytes, and Clusters*
#
# *   #bytes: Returns an array of the bytes in `self`.
# *   #chars: Returns an array of the characters in `self`.
# *   #codepoints: Returns an array of the integer ordinals in `self`.
# *   #getbyte: Returns the integer byte at the given index in `self`.
# *   #grapheme_clusters: Returns an array of the grapheme clusters in `self`.
#
# *Splitting*
#
# *   #lines: Returns an array of the lines in `self`, as determined by a given
#     record separator.
# *   #partition: Returns a 3-element array determined by the first substring
#     that matches a given substring or regexp.
# *   #rpartition: Returns a 3-element array determined by the last substring
#     that matches a given substring or regexp.
# *   #split: Returns an array of substrings determined by a given delimiter --
#     regexp or string -- or, if a block is given, passes those substrings to
#     the block.
#
# *Matching*
#
# *   #scan: Returns an array of substrings matching a given regexp or string,
#     or, if a block is given, passes each matching substring to the block.
# *   #unpack: Returns an array of substrings extracted from `self` according to
#     a given format.
# *   #unpack1: Returns the first substring extracted from `self` according to a
#     given format.
#
# *Numerics*
#
# *   #hex: Returns the integer value of the leading characters, interpreted as
#     hexadecimal digits.
# *   #oct: Returns the integer value of the leading characters, interpreted as
#     octal digits.
# *   #ord: Returns the integer ordinal of the first character in `self`.
# *   #to_c: Returns the complex value of leading characters, interpreted as a
#     complex number.
# *   #to_i: Returns the integer value of leading characters, interpreted as an
#     integer.
# *   #to_f: Returns the floating-point value of leading characters, interpreted
#     as a floating-point number.
# *   #to_r: Returns the rational value of leading characters, interpreted as a
#     rational.
#
# *Strings and Symbols*
#
# *   #inspect: Returns a copy of `self`, enclosed in double quotes, with
#     special characters escaped.
# *   #intern (aliased as #to_sym): Returns the symbol corresponding to `self`.
#
# ### Iterating
#
# *   #each_byte: Calls the given block with each successive byte in `self`.
# *   #each_char: Calls the given block with each successive character in
#     `self`.
# *   #each_codepoint: Calls the given block with each successive integer
#     codepoint in `self`.
# *   #each_grapheme_cluster: Calls the given block with each successive
#     grapheme cluster in `self`.
# *   #each_line: Calls the given block with each successive line in `self`, as
#     determined by a given record separator.
# *   #upto: Calls the given block with each string value returned by successive
#     calls to #succ.
#
class String
  include Comparable

  # A `selector` is a special type of string, used within methods like `String#tr`.
  type selector = string

  # <!--
  #   rdoc-file=string.c
  #   - String.try_convert(object) -> object, new_string, or nil
  # -->
  # Attempts to convert the given `object` to a string.
  #
  # If `object` is already a string, returns `object`, unmodified.
  #
  # Otherwise if `object` responds to `:to_str`, calls `object.to_str` and returns
  # the result.
  #
  # Returns `nil` if `object` does not respond to `:to_str`.
  #
  # Raises an exception unless `object.to_str` returns a string.
  #
  def self.try_convert: (String object) -> String # technically will return `object` unchanged.
                      | (_ToStr object) -> String
                      | (untyped object) -> String?

  # <!--
  #   rdoc-file=string.c
  #   - String.new(string = ''.encode(Encoding::ASCII_8BIT) , **options) -> new_string
  # -->
  # Returns a new String object containing the given `string`.
  #
  # The `options` are optional keyword options (see below).
  #
  # With no argument given and keyword `encoding` also not given, returns an empty
  # string with the Encoding `ASCII-8BIT`:
  #
  #     s = String.new # => ""
  #     s.encoding     # => #<Encoding:ASCII-8BIT>
  #
  # With argument `string` given and keyword option `encoding` not given, returns
  # a new string with the same encoding as `string`:
  #
  #     s0 = 'foo'.encode(Encoding::UTF_16)
  #     s1 = String.new(s0)
  #     s1.encoding # => #<Encoding:UTF-16 (dummy)>
  #
  # (Unlike String.new, a [string
  # literal](rdoc-ref:syntax/literals.rdoc@String+Literals) like `''` or a [here
  # document literal](rdoc-ref:syntax/literals.rdoc@Here+Document+Literals) always
  # has [script encoding](rdoc-ref:encodings.rdoc@Script+Encoding).)
  #
  # With keyword option `encoding` given, returns a string with the specified
  # encoding; the `encoding` may be an Encoding object, an encoding name, or an
  # encoding name alias:
  #
  #     String.new(encoding: Encoding::US_ASCII).encoding        # => #<Encoding:US-ASCII>
  #     String.new('', encoding: Encoding::US_ASCII).encoding    # => #<Encoding:US-ASCII>
  #     String.new('foo', encoding: Encoding::US_ASCII).encoding # => #<Encoding:US-ASCII>
  #     String.new('foo', encoding: 'US-ASCII').encoding         # => #<Encoding:US-ASCII>
  #     String.new('foo', encoding: 'ASCII').encoding            # => #<Encoding:US-ASCII>
  #
  # The given encoding need not be valid for the string's content, and its
  # validity is not checked:
  #
  #     s = String.new('こんにちは', encoding: 'ascii')
  #     s.valid_encoding? # => false
  #
  # But the given `encoding` itself is checked:
  #
  #     String.new('foo', encoding: 'bar') # Raises ArgumentError.
  #
  # With keyword option `capacity` given, the given value is advisory only, and
  # may or may not set the size of the internal buffer, which may in turn affect
  # performance:
  #
  #     String.new('foo', capacity: 1)    # Buffer size is at least 4 (includes terminal null byte).
  #     String.new('foo', capacity: 4096) # Buffer size is at least 4;
  #                                       # may be equal to, greater than, or less than 4096.
  #
  def initialize: (?string source, ?encoding: encoding, ?capacity: int) -> void

  # <!-- rdoc-file=string.c -->
  # Replaces the contents of `self` with the contents of `other_string`; returns
  # `self`:
  #
  #     s = 'foo'        # => "foo"
  #     s.replace('bar') # => "bar"
  #
  # Related: see [Modifying](rdoc-ref:String@Modifying).
  #
  alias initialize_copy replace

  # <!--
  #   rdoc-file=string.c
  #   - self % object -> new_string
  # -->
  # Returns the result of formatting `object` into the format specifications
  # contained in `self` (see [Format
  # Specifications](rdoc-ref:language/format_specifications.rdoc)):
  #
  #     '%05d' % 123 # => "00123"
  #
  # If `self` contains multiple format specifications, `object` must be an array
  # or hash containing the objects to be formatted:
  #
  #     '%-5s: %016x' % [ 'ID', self.object_id ]                # => "ID   : 00002b054ec93168"
  #     'foo = %{foo}' % {foo: 'bar'}                           # => "foo = bar"
  #     'foo = %{foo}, baz = %{baz}' % {foo: 'bar', baz: 'bat'} # => "foo = bar, baz = bat"
  #
  # Related: see [Converting to New
  # String](rdoc-ref:String@Converting+to+New+String).
  #
  def %: (array[untyped] positional_args) -> String
       | (hash[Symbol, untyped] named_args) -> String
       | (untyped arg) -> String

  # <!--
  #   rdoc-file=string.c
  #   - self * n -> new_string
  # -->
  # Returns a new string containing `n` copies of `self`:
  #
  #     'Ho!' * 3 # => "Ho!Ho!Ho!"
  #     'No!' * 0 # => ""
  #
  # Related: see [Converting to New
  # String](rdoc-ref:String@Converting+to+New+String).
  #
  def *: (int amount) -> String

  # <!--
  #   rdoc-file=string.c
  #   - self + other_string -> new_string
  # -->
  # Returns a new string containing `other_string` concatenated to `self`:
  #
  #     'Hello from ' + self.to_s # => "Hello from main"
  #
  # Related: see [Converting to New
  # String](rdoc-ref:String@Converting+to+New+String).
  #
  def +: (string other_string) -> String

  # <!--
  #   rdoc-file=string.c
  #   - +string -> new_string or self
  # -->
  # Returns `self` if `self` is not frozen and can be mutated without warning
  # issuance.
  #
  # Otherwise returns `self.dup`, which is not frozen.
  #
  # Related: see [Freezing/Unfreezing](rdoc-ref:String@Freezing-2FUnfreezing).
  #
  def +@: () -> self

  # <!--
  #   rdoc-file=string.c
  #   - -self -> frozen_string
  # -->
  # Returns a frozen string equal to `self`.
  #
  # The returned string is `self` if and only if all of the following are true:
  #
  # *   `self` is already frozen.
  # *   `self` is an instance of String (rather than of a subclass of String)
  # *   `self` has no instance variables set on it.
  #
  # Otherwise, the returned string is a frozen copy of `self`.
  #
  # Returning `self`, when possible, saves duplicating `self`; see [Data
  # deduplication](https://en.wikipedia.org/wiki/Data_deduplication).
  #
  # It may also save duplicating other, already-existing, strings:
  #
  #     s0 = 'foo'
  #     s1 = 'foo'
  #     s0.object_id == s1.object_id       # => false
  #     (-s0).object_id == (-s1).object_id # => true
  #
  # Note that method #-@ is convenient for defining a constant:
  #
  #     FileName = -'config/database.yml'
  #
  # While its alias #dedup is better suited for chaining:
  #
  #     'foo'.dedup.gsub!('o')
  #
  # Related: see [Freezing/Unfreezing](rdoc-ref:String@Freezing-2FUnfreezing).
  #
  def -@: () -> self

  # <!--
  #   rdoc-file=string.c
  #   - self << object -> self
  # -->
  # Appends a string representation of `object` to `self`; returns `self`.
  #
  # If `object` is a string, appends it to `self`:
  #
  #     s = 'foo'
  #     s << 'bar' # => "foobar"
  #     s          # => "foobar"
  #
  # If `object` is an integer, its value is considered a codepoint; converts the
  # value to a character before concatenating:
  #
  #     s = 'foo'
  #     s << 33 # => "foo!"
  #
  # Additionally, if the codepoint is in range `0..0xff` and the encoding of
  # `self` is Encoding::US_ASCII, changes the encoding to Encoding::ASCII_8BIT:
  #
  #     s = 'foo'.encode(Encoding::US_ASCII)
  #     s.encoding # => #<Encoding:US-ASCII>
  #     s << 0xff  # => "foo\xFF"
  #     s.encoding # => #<Encoding:BINARY (ASCII-8BIT)>
  #
  # Raises RangeError if that codepoint is not representable in the encoding of
  # `self`:
  #
  #     s = 'foo'
  #     s.encoding              # => <Encoding:UTF-8>
  #     s << 0x00110000         # 1114112 out of char range (RangeError)
  #     s = 'foo'.encode(Encoding::EUC_JP)
  #     s << 0x00800080         # invalid codepoint 0x800080 in EUC-JP (RangeError)
  #
  # Related: see [Modifying](rdoc-ref:String@Modifying).
  #
  def <<: (string | Integer str_or_codepoint) -> self

  # <!--
  #   rdoc-file=string.c
  #   - self <=> other_string -> -1, 0, 1, or nil
  # -->
  # Compares `self` and `other_string`, returning:
  #
  # *   -1 if `other_string` is larger.
  # *   0 if the two are equal.
  # *   1 if `other_string` is smaller.
  # *   `nil` if the two are incomparable.
  #
  # Examples:
  #
  #     'foo' <=> 'foo'  # => 0
  #     'foo' <=> 'food' # => -1
  #     'food' <=> 'foo' # => 1
  #     'FOO' <=> 'foo'  # => -1
  #     'foo' <=> 'FOO'  # => 1
  #     'foo' <=> 1      # => nil
  #
  # Related: see [Comparing](rdoc-ref:String@Comparing).
  #
  def <=>: (string) -> (-1 | 0 | 1)
         | (untyped) -> (-1 | 0 | 1)?

  # <!--
  #   rdoc-file=string.c
  #   - self == object -> true or false
  # -->
  # Returns whether `object` is equal to `self`.
  #
  # When `object` is a string, returns whether `object` has the same length and
  # content as `self`:
  #
  #     s = 'foo'
  #     s == 'foo'  # => true
  #     s == 'food' # => false
  #     s == 'FOO'  # => false
  #
  # Returns `false` if the two strings' encodings are not compatible:
  #
  #     "\u{e4 f6 fc}".encode(Encoding::ISO_8859_1) == ("\u{c4 d6 dc}") # => false
  #
  # When `object` is not a string:
  #
  # *   If `object` responds to method `to_str`, `object == self` is called and
  #     its return value is returned.
  # *   If `object` does not respond to `to_str`, `false` is returned.
  #
  # Related: [Comparing](rdoc-ref:String@Comparing).
  #
  def ==: (untyped other) -> bool

  # <!-- rdoc-file=string.c -->
  # Returns whether `object` is equal to `self`.
  #
  # When `object` is a string, returns whether `object` has the same length and
  # content as `self`:
  #
  #     s = 'foo'
  #     s == 'foo'  # => true
  #     s == 'food' # => false
  #     s == 'FOO'  # => false
  #
  # Returns `false` if the two strings' encodings are not compatible:
  #
  #     "\u{e4 f6 fc}".encode(Encoding::ISO_8859_1) == ("\u{c4 d6 dc}") # => false
  #
  # When `object` is not a string:
  #
  # *   If `object` responds to method `to_str`, `object == self` is called and
  #     its return value is returned.
  # *   If `object` does not respond to `to_str`, `false` is returned.
  #
  # Related: [Comparing](rdoc-ref:String@Comparing).
  #
  alias === ==

  # <!--
  #   rdoc-file=string.c
  #   - self =~ object -> integer or nil
  # -->
  # When `object` is a Regexp, returns the index of the first substring in `self`
  # matched by `object`, or `nil` if no match is found; updates [Regexp-related
  # global variables](rdoc-ref:Regexp@Global+Variables):
  #
  #     'foo' =~ /f/ # => 0
  #     $~           # => #<MatchData "f">
  #     'foo' =~ /o/ # => 1
  #     $~           # => #<MatchData "o">
  #     'foo' =~ /x/ # => nil
  #     $~           # => nil
  #
  # Note that `string =~ regexp` is different from `regexp =~ string` (see
  # Regexp#=~):
  #
  #     number = nil
  #     'no. 9' =~ /(?<number>\d+)/ # => 4
  #     number                      # => nil # Not assigned.
  #     /(?<number>\d+)/ =~ 'no. 9' # => 4
  #     number                      # => "9" # Assigned.
  #
  # If `object` is not a Regexp, returns the value returned by `object =~ self`.
  #
  # Related: see [Querying](rdoc-ref:String@Querying).
  #
  def =~: (Regexp regex) -> Integer?
        | [T] (_MatchAgainst[self, T] object) -> T

  interface _MatchAgainst[O, T]
    def =~: (O string) -> T
  end

  # <!--
  #   rdoc-file=string.c
  #   - self[index] -> new_string or nil
  #   - self[start, length] -> new_string or nil
  #   - self[range] -> new_string or nil
  #   - self[regexp, capture = 0] -> new_string or nil
  #   - self[substring] -> new_string or nil
  # -->
  # Returns the substring of `self` specified by the arguments.
  #
  # **Form `self[index]`**
  #
  # With non-negative integer argument `index` given, returns the 1-character
  # substring found in self at character offset index:
  #
  #     'hello'[0]    # => "h"
  #     'hello'[4]    # => "o"
  #     'hello'[5]    # => nil
  #     'Привет'[2]   # => "и"
  #     'こんにちは'[4] # => "は"
  #
  # With negative integer argument `index` given, counts backward from the end of
  # `self`:
  #
  #     'hello'[-1] # => "o"
  #     'hello'[-5] # => "h"
  #     'hello'[-6] # => nil
  #
  # **Form `self[start, length]`**
  #
  # With integer arguments `start` and `length` given, returns a substring of size
  # `length` characters (as available) beginning at character offset specified by
  # `start`.
  #
  # If argument `start` is non-negative, the offset is `start`:
  #
  #     'hello'[0, 1]  # => "h"
  #     'hello'[0, 5]  # => "hello"
  #     'hello'[0, 6]  # => "hello"
  #     'hello'[2, 3]  # => "llo"
  #     'hello'[2, 0]  # => ""
  #     'hello'[2, -1] # => nil
  #
  # If argument `start` is negative, counts backward from the end of `self`:
  #
  #     'hello'[-1, 1] # => "o"
  #     'hello'[-5, 5] # => "hello"
  #     'hello'[-1, 0] # => ""
  #     'hello'[-6, 5] # => nil
  #
  # Special case: if `start` equals the length of `self`, returns a new empty
  # string:
  #
  #     'hello'[5, 3]  # => ""
  #
  # **Form `self[range]`**
  #
  # With Range argument `range` given, forms substring `self[range.start,
  # range.size]`:
  #
  #     'hello'[0..2]  # => "hel"
  #     'hello'[0, 3]  # => "hel"
  #
  #     'hello'[0...2] # => "he"
  #     'hello'[0, 2]  # => "he"
  #
  #     'hello'[0, 0]  # => ""
  #     'hello'[0...0] # => ""
  #
  # **Form `self[regexp, capture = 0]`**
  #
  # With Regexp argument `regexp` given and `capture` as zero, searches for a
  # matching substring in `self`; updates [Regexp-related global
  # variables](rdoc-ref:Regexp@Global+Variables):
  #
  #     'hello'[/ell/]     # => "ell"
  #     'hello'[/l+/]      # => "ll"
  #     'hello'[//]        # => ""
  #     'hello'[/nosuch/]  # => nil
  #
  # With `capture` as a positive integer `n`, returns the +n+th matched group:
  #
  #     'hello'[/(h)(e)(l+)(o)/]    # => "hello"
  #     'hello'[/(h)(e)(l+)(o)/, 1] # => "h"
  #     $1                          # => "h"
  #     'hello'[/(h)(e)(l+)(o)/, 2] # => "e"
  #     $2                          # => "e"
  #     'hello'[/(h)(e)(l+)(o)/, 3] # => "ll"
  #     'hello'[/(h)(e)(l+)(o)/, 4] # => "o"
  #     'hello'[/(h)(e)(l+)(o)/, 5] # => nil
  #
  # **Form `self[substring]`**
  #
  # With string argument `substring` given, returns the matching substring of
  # `self`, if found:
  #
  #     'hello'['ell']      # => "ell"
  #     'hello'['']         # => ""
  #     'hello'['nosuch']   # => nil
  #     'Привет'['ив']      # => "ив"
  #     'こんにちは'['んにち'] # => "んにち"
  #
  # Related: see [Converting to New
  # String](rdoc-ref:String@Converting+to+New+String).
  #
  def []: (int start, ?int length) -> String?
        | (range[int?] range) -> String?
        | (Regexp regexp, ?MatchData::capture backref) -> String?
        | (String substring) -> String?

  # <!--
  #   rdoc-file=string.c
  #   - self[index] = other_string -> new_string
  #   - self[start, length] = other_string -> new_string
  #   - self[range] = other_string -> new_string
  #   - self[regexp, capture = 0] = other_string -> new_string
  #   - self[substring] = other_string -> new_string
  # -->
  # Returns `self` with all, a substring, or none of its contents replaced;
  # returns the argument `other_string`.
  #
  # **Form `self[index] = other_string`**
  #
  # With non-negative integer argument `index` given, searches for the 1-character
  # substring found in self at character offset index:
  #
  #     s = 'hello'
  #     s[0] = 'foo' # => "foo"
  #     s            # => "fooello"
  #
  #     s = 'hello'
  #     s[4] = 'foo' # => "foo"
  #     s            # => "hellfoo"
  #
  #     s = 'hello'
  #     s[5] = 'foo' # => "foo"
  #     s            # => "hellofoo"
  #
  #     s = 'hello'
  #     s[6] = 'foo' # Raises IndexError: index 6 out of string.
  #
  # With negative integer argument `index` given, counts backward from the end of
  # `self`:
  #
  #     s = 'hello'
  #     s[-1] = 'foo'  # => "foo"
  #     s              # => "hellfoo"
  #
  #     s = 'hello'
  #     s[-5] = 'foo'  # => "foo"
  #     s              # => "fooello"
  #
  #     s = 'hello'
  #     s[-6] = 'foo'  # Raises IndexError: index -6 out of string.
  #
  # **Form `self[start, length] = other_string`**
  #
  # With integer arguments `start` and `length` given, searches for a substring of
  # size `length` characters (as available) beginning at character offset
  # specified by `start`.
  #
  # If argument `start` is non-negative, the offset is `start`:
  #
  #     s = 'hello'
  #     s[0, 1] = 'foo'  # => "foo"
  #     s                # => "fooello"
  #
  #     s = 'hello'
  #     s[0, 5] = 'foo'  # => "foo"
  #     s                # => "foo"
  #
  #     s = 'hello'
  #     s[0, 9] = 'foo'  # => "foo"
  #     s                # => "foo"
  #
  #     s = 'hello'
  #     s[2, 0] = 'foo'  # => "foo"
  #     s                # => "hefoollo"
  #
  #     s = 'hello'
  #     s[2, -1] = 'foo' # Raises IndexError: negative length -1.
  #
  # If argument `start` is negative, counts backward from the end of `self`:
  #
  #     s = 'hello'
  #     s[-1, 1] = 'foo' # => "foo"
  #     s                # => "hellfoo"
  #
  #     s = 'hello'
  #     s[-1, 9] = 'foo' # => "foo"
  #     s                # => "hellfoo"
  #
  #     s = 'hello'
  #     s[-5, 2] = 'foo' # => "foo"
  #     s                # => "foollo"
  #
  #     s = 'hello'
  #     s[-3, 0] = 'foo' # => "foo"
  #     s                # => "hefoollo"
  #
  #     s = 'hello'
  #     s[-6, 2] = 'foo' # Raises IndexError: index -6 out of string.
  #
  # Special case: if `start` equals the length of `self`, the argument is appended
  # to `self`:
  #
  #     s = 'hello'
  #     s[5, 3] = 'foo' # => "foo"
  #     s               # => "hellofoo"
  #
  # **Form `self[range] = other_string`**
  #
  # With Range argument `range` given, equivalent to `self[range.start,
  # range.size] = other_string`:
  #
  #     s0 = 'hello'
  #     s1 = 'hello'
  #     s0[0..2] = 'foo' # => "foo"
  #     s1[0, 3] = 'foo' # => "foo"
  #     s0               # => "foolo"
  #     s1               # => "foolo"
  #
  #     s = 'hello'
  #     s[0...2] = 'foo' # => "foo"
  #     s                # => "foollo"
  #
  #     s = 'hello'
  #     s[0...0] = 'foo' # => "foo"
  #     s                # => "foohello"
  #
  #     s = 'hello'
  #     s[9..10] = 'foo' # Raises RangeError: 9..10 out of range
  #
  # **Form `self[regexp, capture = 0] = other_string`**
  #
  # With Regexp argument `regexp` given and `capture` as zero, searches for a
  # matching substring in `self`; updates [Regexp-related global
  # variables](rdoc-ref:Regexp@Global+Variables):
  #
  #     s = 'hello'
  #     s[/l/] = 'L'       # => "L"
  #     [$`, $&, $']       # => ["he", "l", "lo"]
  #     s[/eLlo/] = 'owdy' # => "owdy"
  #     [$`, $&, $']       # => ["h", "eLlo", ""]
  #     s[/eLlo/] = 'owdy' # Raises IndexError: regexp not matched.
  #     [$`, $&, $']       # => [nil, nil, nil]
  #
  # With `capture` as a positive integer `n`, searches for the +n+th matched
  # group:
  #
  #     s = 'hello'
  #     s[/(h)(e)(l+)(o)/] = 'foo'    # => "foo"
  #     [$`, $&, $']                  # => ["", "hello", ""]
  #
  #     s = 'hello'
  #     s[/(h)(e)(l+)(o)/, 1] = 'foo' # => "foo"
  #     s                             # => "fooello"
  #     [$`, $&, $']                  # => ["", "hello", ""]
  #
  #     s = 'hello'
  #     s[/(h)(e)(l+)(o)/, 2] = 'foo' # => "foo"
  #     s                             # => "hfoollo"
  #     [$`, $&, $']                  # => ["", "hello", ""]
  #
  #     s = 'hello'
  #     s[/(h)(e)(l+)(o)/, 4] = 'foo' # => "foo"
  #     s                             # => "hellfoo"
  #     [$`, $&, $']                  # => ["", "hello", ""]
  #
  #     s = 'hello'
  #     # => "hello"
  #     s[/(h)(e)(l+)(o)/, 5] = 'foo  # Raises IndexError: index 5 out of regexp.
  #
  #     s = 'hello'
  #     s[/nosuch/] = 'foo'           # Raises IndexError: regexp not matched.
  #
  # **Form `self[substring] = other_string`**
  #
  # With string argument `substring` given:
  #
  #     s = 'hello'
  #     s['l'] = 'foo'  # => "foo"
  #     s  # => "hefoolo"
  #
  #     s = 'hello'
  #     s['ll'] = 'foo'  # => "foo"
  #     s  # => "hefooo"
  #
  #     s = 'тест'
  #     s['ес'] = 'foo'  # => "foo"
  #     s  # => "тfooт"
  #
  #     s = 'こんにちは'
  #     s['んにち'] = 'foo'  # => "foo"
  #     s  # => "こfooは"
  #
  #     s['nosuch'] = 'foo' # Raises IndexError: string not matched.
  #
  # Related: see [Modifying](rdoc-ref:String@Modifying).
  #
  def []=: [T < _ToStr] (int index, T replacement) -> T
         | [T < _ToStr] (int start, int length, T replacement) -> T
         | [T < _ToStr] (range[int?] range, T replacement) -> T
         | [T < _ToStr] (Regexp regexp, T replacement) -> T
         | [T < _ToStr] (Regexp regexp, MatchData::capture backref, T replacement) -> T
         | [T < _ToStr] (String substring, T replacement) -> T

  # <!--
  #   rdoc-file=string.c
  #   - append_as_bytes(*objects) -> self
  # -->
  # Concatenates each object in `objects` into `self`; returns `self`; performs no
  # encoding validation or conversion:
  #
  #     s = 'foo'
  #     s.append_as_bytes(" \xE2\x82") # => "foo \xE2\x82"
  #     s.valid_encoding?              # => false
  #     s.append_as_bytes("\xAC 12")
  #     s.valid_encoding?              # => true
  #
  # When a given object is an integer, the value is considered an 8-bit byte; if
  # the integer occupies more than one byte (i.e,. is greater than 255), appends
  # only the low-order byte (similar to String#setbyte):
  #
  #     s = ""
  #     s.append_as_bytes(0, 257) # => "\u0000\u0001"
  #     s.bytesize                # => 2
  #
  # Related: see [Modifying](rdoc-ref:String@Modifying).
  #
  def append_as_bytes: (String) -> String

  # <!--
  #   rdoc-file=string.c
  #   - ascii_only? -> true or false
  # -->
  # Returns whether `self` contains only ASCII characters:
  #
  #     'abc'.ascii_only?         # => true
  #     "abc\u{6666}".ascii_only? # => false
  #
  # Related: see [Querying](rdoc-ref:String@Querying).
  #
  def ascii_only?: () -> bool

  # <!--
  #   rdoc-file=string.c
  #   - b -> new_string
  # -->
  # Returns a copy of `self` that has ASCII-8BIT encoding; the underlying bytes
  # are not modified:
  #
  #     s = "\x99"
  #     s.encoding   # => #<Encoding:UTF-8>
  #     t = s.b      # => "\x99"
  #     t.encoding   # => #<Encoding:ASCII-8BIT>
  #
  #     s = "\u4095" # => "䂕"
  #     s.encoding   # => #<Encoding:UTF-8>
  #     s.bytes      # => [228, 130, 149]
  #     t = s.b      # => "\xE4\x82\x95"
  #     t.encoding   # => #<Encoding:ASCII-8BIT>
  #     t.bytes      # => [228, 130, 149]
  #
  # Related: see [Converting to New
  # String](rdoc-ref:String@Converting+to+New+String).
  #
  def b: () -> String

  # <!--
  #   rdoc-file=string.c
  #   - byteindex(object, offset = 0) -> integer or nil
  # -->
  # Returns the 0-based integer index of a substring of `self` specified by
  # `object` (a string or Regexp) and `offset`, or `nil` if there is no such
  # substring; the returned index is the count of *bytes* (not characters).
  #
  # When `object` is a string, returns the index of the first found substring
  # equal to `object`:
  #
  #     s = 'foo'          # => "foo"
  #     s.size             # => 3 # Three 1-byte characters.
  #     s.bytesize         # => 3 # Three bytes.
  #     s.byteindex('f')   # => 0
  #     s.byteindex('o')   # => 1
  #     s.byteindex('oo')  # => 1
  #     s.byteindex('ooo') # => nil
  #
  # When `object` is a Regexp, returns the index of the first found substring
  # matching `object`; updates [Regexp-related global
  # variables](rdoc-ref:Regexp@Global+Variables):
  #
  #     s = 'foo'
  #     s.byteindex(/f/)   # => 0
  #     $~                 # => #<MatchData "f">
  #     s.byteindex(/o/)   # => 1
  #     s.byteindex(/oo/)  # => 1
  #     s.byteindex(/ooo/) # => nil
  #     $~                 # => nil
  #
  # Integer argument `offset`, if given, specifies the 0-based index of the byte
  # where searching is to begin.
  #
  # When `offset` is non-negative, searching begins at byte position `offset`:
  #
  #     s = 'foo'
  #     s.byteindex('o', 1) # => 1
  #     s.byteindex('o', 2) # => 2
  #     s.byteindex('o', 3) # => nil
  #
  # When `offset` is negative, counts backward from the end of `self`:
  #
  #     s = 'foo'
  #     s.byteindex('o', -1) # => 2
  #     s.byteindex('o', -2) # => 1
  #     s.byteindex('o', -3) # => 1
  #     s.byteindex('o', -4) # => nil
  #
  # Raises IndexError if the byte at `offset` is not the first byte of a
  # character:
  #
  #     s = "\uFFFF\uFFFF"       # => "\uFFFF\uFFFF"
  #     s.size                   # => 2 # Two 3-byte characters.
  #     s.bytesize               # => 6 # Six bytes.
  #     s.byteindex("\uFFFF")    # => 0
  #     s.byteindex("\uFFFF", 1) # Raises IndexError
  #     s.byteindex("\uFFFF", 2) # Raises IndexError
  #     s.byteindex("\uFFFF", 3) # => 3
  #     s.byteindex("\uFFFF", 4) # Raises IndexError
  #     s.byteindex("\uFFFF", 5) # Raises IndexError
  #     s.byteindex("\uFFFF", 6) # => nil
  #
  # Related: see [Querying](rdoc-ref:String@Querying).
  #
  def byteindex: (Regexp | string pattern, ?int offset) -> Integer?

  # <!--
  #   rdoc-file=string.c
  #   - byterindex(object, offset = self.bytesize) -> integer or nil
  # -->
  # Returns the 0-based integer index of a substring of `self` that is the *last*
  # match for the given `object` (a string or Regexp) and `offset`, or `nil` if
  # there is no such substring; the returned index is the count of *bytes* (not
  # characters).
  #
  # When `object` is a string, returns the index of the *last* found substring
  # equal to `object`:
  #
  #     s = 'foo'           # => "foo"
  #     s.size              # => 3 # Three 1-byte characters.
  #     s.bytesize          # => 3 # Three bytes.
  #     s.byterindex('f')   # => 0
  #     s.byterindex('o')   # => 2
  #     s.byterindex('oo')  # => 1
  #     s.byterindex('ooo') # => nil
  #
  # When `object` is a Regexp, returns the index of the last found substring
  # matching `object`; updates [Regexp-related global
  # variables](rdoc-ref:Regexp@Global+Variables):
  #
  #     s = 'foo'
  #     s.byterindex(/f/)   # => 0
  #     $~                  # => #<MatchData "f">
  #     s.byterindex(/o/)   # => 2
  #     s.byterindex(/oo/)  # => 1
  #     s.byterindex(/ooo/) # => nil
  #     $~                  # => nil
  #
  # The last match means starting at the possible last position, not the last of
  # the longest matches:
  #
  #     s = 'foo'
  #     s.byterindex(/o+/) # => 2
  #     $~                 #=> #<MatchData "o">
  #
  # To get the last longest match, use a negative lookbehind:
  #
  #     s = 'foo'
  #     s.byterindex(/(?<!o)o+/) # => 1
  #     $~                       # => #<MatchData "oo">
  #
  # Or use method #byteindex with negative lookahead:
  #
  #     s = 'foo'
  #     s.byteindex(/o+(?!.*o)/) # => 1
  #     $~                       #=> #<MatchData "oo">
  #
  # Integer argument `offset`, if given, specifies the 0-based index of the byte
  # where searching is to end.
  #
  # When `offset` is non-negative, searching ends at byte position `offset`:
  #
  #     s = 'foo'
  #     s.byterindex('o', 0) # => nil
  #     s.byterindex('o', 1) # => 1
  #     s.byterindex('o', 2) # => 2
  #     s.byterindex('o', 3) # => 2
  #
  # When `offset` is negative, counts backward from the end of `self`:
  #
  #     s = 'foo'
  #     s.byterindex('o', -1) # => 2
  #     s.byterindex('o', -2) # => 1
  #     s.byterindex('o', -3) # => nil
  #
  # Raises IndexError if the byte at `offset` is not the first byte of a
  # character:
  #
  #     s = "\uFFFF\uFFFF"        # => "\uFFFF\uFFFF"
  #     s.size                    # => 2 # Two 3-byte characters.
  #     s.bytesize                # => 6 # Six bytes.
  #     s.byterindex("\uFFFF")    # => 3
  #     s.byterindex("\uFFFF", 1) # Raises IndexError
  #     s.byterindex("\uFFFF", 2) # Raises IndexError
  #     s.byterindex("\uFFFF", 3) # => 3
  #     s.byterindex("\uFFFF", 4) # Raises IndexError
  #     s.byterindex("\uFFFF", 5) # Raises IndexError
  #     s.byterindex("\uFFFF", 6) # => nil
  #
  # Related: see [Querying](rdoc-ref:String@Querying).
  #
  def byterindex: (Regexp | string pattern, ?int offset) -> Integer?

  # <!--
  #   rdoc-file=string.c
  #   - bytes -> array_of_bytes
  # -->
  # Returns an array of the bytes in `self`:
  #
  #     'hello'.bytes # => [104, 101, 108, 108, 111]
  #     'тест'.bytes  # => [209, 130, 208, 181, 209, 129, 209, 130]
  #     'こんにちは'.bytes
  #     # => [227, 129, 147, 227, 130, 147, 227, 129, 171, 227, 129, 161, 227, 129, 175]
  #
  # Related: see [Converting to
  # Non-String](rdoc-ref:String@Converting+to+Non--5CString).
  #
  def bytes: () -> Array[Integer]
           | () { (Integer byte) -> void } -> self

  # <!--
  #   rdoc-file=string.c
  #   - bytesize -> integer
  # -->
  # Returns the count of bytes in `self`.
  #
  # Note that the byte count may be different from the character count (returned
  # by #size):
  #
  #     s = 'foo'
  #     s.bytesize # => 3
  #     s.size     # => 3
  #     s = 'тест'
  #     s.bytesize # => 8
  #     s.size     # => 4
  #     s = 'こんにちは'
  #     s.bytesize # => 15
  #     s.size     # => 5
  #
  # Related: see [Querying](rdoc-ref:String@Querying).
  #
  def bytesize: () -> Integer

  # <!--
  #   rdoc-file=string.c
  #   - byteslice(offset, length = 1) -> string or nil
  #   - byteslice(range) -> string or nil
  # -->
  # Returns a substring of `self`, or `nil` if the substring cannot be
  # constructed.
  #
  # With integer arguments `offset` and `length` given, returns the substring
  # beginning at the given `offset` and of the given `length` (as available):
  #
  #     s = '0123456789'   # => "0123456789"
  #     s.byteslice(2)     # => "2"
  #     s.byteslice(200)   # => nil
  #     s.byteslice(4, 3)  # => "456"
  #     s.byteslice(4, 30) # => "456789"
  #
  # Returns `nil` if `length` is negative or `offset` falls outside of `self`:
  #
  #     s.byteslice(4, -1) # => nil
  #     s.byteslice(40, 2) # => nil
  #
  # Counts backwards from the end of `self` if `offset` is negative:
  #
  #     s = '0123456789'   # => "0123456789"
  #     s.byteslice(-4)    # => "6"
  #     s.byteslice(-4, 3) # => "678"
  #
  # With Range argument `range` given, returns `byteslice(range.begin,
  # range.size)`:
  #
  #     s = '0123456789'    # => "0123456789"
  #     s.byteslice(4..6)   # => "456"
  #     s.byteslice(-6..-4) # => "456"
  #     s.byteslice(5..2)   # => "" # range.size is zero.
  #     s.byteslice(40..42) # => nil
  #
  # The starting and ending offsets need not be on character boundaries:
  #
  #     s = 'こんにちは'
  #     s.byteslice(0, 3) # => "こ"
  #     s.byteslice(1, 3) # => "\x81\x93\xE3"
  #
  # The encodings of `self` and the returned substring are always the same:
  #
  #     s.encoding                 # => #<Encoding:UTF-8>
  #     s.byteslice(0, 3).encoding # => #<Encoding:UTF-8>
  #     s.byteslice(1, 3).encoding # => #<Encoding:UTF-8>
  #
  # But, depending on the character boundaries, the encoding of the returned
  # substring may not be valid:
  #
  #     s.valid_encoding?                 # => true
  #     s.byteslice(0, 3).valid_encoding? # => true
  #     s.byteslice(1, 3).valid_encoding? # => false
  #
  # Related: see [Converting to New
  # String](rdoc-ref:String@Converting+to+New+String).
  #
  def byteslice: (int start, ?int length) -> String?
               | (range[int?] range) -> String?

  # <!--
  #   rdoc-file=string.c
  #   - bytesplice(offset, length, str) -> self
  #   - bytesplice(offset, length, str, str_offset, str_length) -> self
  #   - bytesplice(range, str) -> self
  #   - bytesplice(range, str, str_range) -> self
  # -->
  # Replaces *target bytes* in `self` with *source bytes* from the given string
  # `str`; returns `self`.
  #
  # In the first form, arguments `offset` and `length` determine the target bytes,
  # and the source bytes are all of the given `str`:
  #
  #     '0123456789'.bytesplice(0, 3, 'abc')  # => "abc3456789"
  #     '0123456789'.bytesplice(3, 3, 'abc')  # => "012abc6789"
  #     '0123456789'.bytesplice(0, 50, 'abc') # => "abc"
  #     '0123456789'.bytesplice(50, 3, 'abc') # Raises IndexError.
  #
  # The counts of the target bytes and source source bytes may be different:
  #
  #     '0123456789'.bytesplice(0, 6, 'abc') # => "abc6789"      # Shorter source.
  #     '0123456789'.bytesplice(0, 1, 'abc') # => "abc123456789" # Shorter target.
  #
  # And either count may be zero (i.e., specifying an empty string):
  #
  #     '0123456789'.bytesplice(0, 3, '')    # => "3456789"       # Empty source.
  #     '0123456789'.bytesplice(0, 0, 'abc') # => "abc0123456789" # Empty target.
  #
  # In the second form, just as in the first, arugments `offset` and `length`
  # determine the target bytes; argument `str` *contains* the source bytes, and
  # the additional arguments `str_offset` and `str_length` determine the actual
  # source bytes:
  #
  #     '0123456789'.bytesplice(0, 3, 'abc', 0, 3) # => "abc3456789"
  #     '0123456789'.bytesplice(0, 3, 'abc', 1, 1) # => "b3456789"      # Shorter source.
  #     '0123456789'.bytesplice(0, 1, 'abc', 0, 3) # => "abc123456789"  # Shorter target.
  #     '0123456789'.bytesplice(0, 3, 'abc', 1, 0) # => "3456789"       # Empty source.
  #     '0123456789'.bytesplice(0, 0, 'abc', 0, 3) # => "abc0123456789" # Empty target.
  #
  # In the third form, argument `range` determines the target bytes and the source
  # bytes are all of the given `str`:
  #
  #     '0123456789'.bytesplice(0..2, 'abc')  # => "abc3456789"
  #     '0123456789'.bytesplice(3..5, 'abc')  # => "012abc6789"
  #     '0123456789'.bytesplice(0..5, 'abc')  # => "abc6789"       # Shorter source.
  #     '0123456789'.bytesplice(0..0, 'abc')  # => "abc123456789"  # Shorter target.
  #     '0123456789'.bytesplice(0..2, '')     # => "3456789"       # Empty source.
  #     '0123456789'.bytesplice(0...0, 'abc') # => "abc0123456789" # Empty target.
  #
  # In the fourth form, just as in the third, arugment `range` determines the
  # target bytes; argument `str` *contains* the source bytes, and the additional
  # argument `str_range` determines the actual source bytes:
  #
  #     '0123456789'.bytesplice(0..2, 'abc', 0..2)  # => "abc3456789"
  #     '0123456789'.bytesplice(3..5, 'abc', 0..2)  # => "012abc6789"
  #     '0123456789'.bytesplice(0..2, 'abc', 0..1)  # => "ab3456789"     # Shorter source.
  #     '0123456789'.bytesplice(0..1, 'abc', 0..2)  # => "abc23456789"   # Shorter target.
  #     '0123456789'.bytesplice(0..2, 'abc', 0...0) # => "3456789"       # Empty source.
  #     '0123456789'.bytesplice(0...0, 'abc', 0..2) # => "abc0123456789" # Empty target.
  #
  # In any of the forms, the beginnings and endings of both source and target must
  # be on character boundaries.
  #
  # In these examples, `self` has five 3-byte characters, and so has character
  # boundaries at offsets 0, 3, 6, 9, 12, and 15.
  #
  #     'こんにちは'.bytesplice(0, 3, 'abc') # => "abcんにちは"
  #     'こんにちは'.bytesplice(1, 3, 'abc') # Raises IndexError.
  #     'こんにちは'.bytesplice(0, 2, 'abc') # Raises IndexError.
  #
  def bytesplice: (Integer start, int length, string str) -> String
                | (int start, int length, string str, int str_start, int str_length) -> String
                | (range[int?] range, string str, ?range[int?] str_range) -> String

  # <!--
  #   rdoc-file=string.c
  #   - capitalize(mapping = :ascii) -> new_string
  # -->
  # Returns a string containing the characters in `self`, each with possibly
  # changed case:
  #
  # *   The first character made uppercase.
  # *   All other characters are made lowercase.
  #
  # Examples:
  #
  #     'hello'.capitalize  # => "Hello"
  #     'HELLO'.capitalize  # => "Hello"
  #     'straße'.capitalize # => "Straße"  # Lowercase 'ß' not changed.
  #     'STRAẞE'.capitalize # => "Straße"  # Uppercase 'ẞ' downcased to 'ß'.
  #     'привет'.capitalize # => "Привет"
  #     'ПРИВЕТ'.capitalize # => "Привет"
  #
  # Some characters (and some character sets) do not have upcase and downcase
  # versions; see [Case Mapping](rdoc-ref:case_mapping.rdoc):
  #
  #     s = '1, 2, 3, ...'
  #     s.capitalize == s # => true
  #     s = 'こんにちは'
  #     s.capitalize == s # => true
  #
  # The casing is affected by the given `mapping`, which may be `:ascii`, `:fold`,
  # or `:turkic`; see [Case Mappings](rdoc-ref:case_mapping.rdoc@Case+Mappings).
  #
  # Related: see [Converting to New
  # String](rdoc-ref:String@Converting+to+New+String).
  #
  def capitalize: () -> String
                | (:ascii | :lithuanian | :turkic) -> String
                | (:lithuanian, :turkic) -> String
                | (:turkic, :lithuanian) -> String

  # <!--
  #   rdoc-file=string.c
  #   - capitalize!(mapping = :ascii) -> self or nil
  # -->
  # Like String#capitalize, except that:
  #
  # *   Changes character casings in `self` (not in a copy of `self`).
  # *   Returns `self` if any changes are made, `nil` otherwise.
  #
  # Related: See [Modifying](rdoc-ref:String@Modifying).
  #
  def capitalize!: () -> self?
                 | (:ascii | :lithuanian | :turkic) -> self?
                 | (:lithuanian, :turkic) -> self?
                 | (:turkic, :lithuanian) -> self?

  # <!--
  #   rdoc-file=string.c
  #   - casecmp(other_string) -> -1, 0, 1, or nil
  # -->
  # Ignoring case, compares `self` and `other_string`; returns:
  #
  # *   -1 if `self.downcase` is smaller than `other_string.downcase`.
  # *   0 if the two are equal.
  # *   1 if `self.downcase` is larger than `other_string.downcase`.
  # *   `nil` if the two are incomparable.
  #
  # See [Case Mapping](rdoc-ref:case_mapping.rdoc).
  #
  # Examples:
  #
  #     'foo'.casecmp('goo')  # => -1
  #     'goo'.casecmp('foo')  # => 1
  #     'foo'.casecmp('food') # => -1
  #     'food'.casecmp('foo') # => 1
  #     'FOO'.casecmp('foo')  # => 0
  #     'foo'.casecmp('FOO')  # => 0
  #     'foo'.casecmp(1)      # => nil
  #
  # Related: see [Comparing](rdoc-ref:String@Comparing).
  #
  def casecmp: (string other) -> (-1 | 0 | 1)
             | (untyped) -> (-1 | 0 | 1)?

  # <!--
  #   rdoc-file=string.c
  #   - casecmp?(other_string) -> true, false, or nil
  # -->
  # Returns `true` if `self` and `other_string` are equal after Unicode case
  # folding, `false` if unequal, `nil` if incomparable.
  #
  # See [Case Mapping](rdoc-ref:case_mapping.rdoc).
  #
  # Examples:
  #
  #     'foo'.casecmp?('goo')  # => false
  #     'goo'.casecmp?('foo')  # => false
  #     'foo'.casecmp?('food') # => false
  #     'food'.casecmp?('foo') # => false
  #     'FOO'.casecmp?('foo')  # => true
  #     'foo'.casecmp?('FOO')  # => true
  #     'foo'.casecmp?(1)      # => nil
  #
  # Related: see [Comparing](rdoc-ref:String@Comparing).
  #
  def casecmp?: (string other) -> bool
              | (untyped) -> bool?

  # <!--
  #   rdoc-file=string.c
  #   - center(size, pad_string = ' ') -> new_string
  # -->
  # Returns a centered copy of `self`.
  #
  # If integer argument `size` is greater than the size (in characters) of `self`,
  # returns a new string of length `size` that is a copy of `self`, centered and
  # padded on one or both ends with `pad_string`:
  #
  #     'hello'.center(6)             # => "hello "               # Padded on one end.
  #     'hello'.center(10)            # => "  hello   "           # Padded on both ends.
  #     'hello'.center(20, '-|')      # => "-|-|-|-hello-|-|-|-|" # Some padding repeated.
  #     'hello'.center(10, 'abcdefg') # => "abhelloabc"           # Some padding not used.
  #     '  hello  '.center(13)        # => "    hello    "
  #     'тест'.center(10)             # => "   тест   "
  #     'こんにちは'.center(10)         # => "  こんにちは   "      # Multi-byte characters.
  #
  # If `size` is less than or equal to the size of `self`, returns an unpadded
  # copy of `self`:
  #
  #     'hello'.center(5)   # => "hello"
  #     'hello'.center(-10) # => "hello"
  #
  # Related: see [Converting to New
  # String](rdoc-ref:String@Converting+to+New+String).
  #
  def center: (int width, ?string pad_string) -> String

  # <!--
  #   rdoc-file=string.c
  #   - chars -> array_of_characters
  # -->
  # Returns an array of the characters in `self`:
  #
  #     'hello'.chars     # => ["h", "e", "l", "l", "o"]
  #     'тест'.chars      # => ["т", "е", "с", "т"]
  #     'こんにちは'.chars # => ["こ", "ん", "に", "ち", "は"]
  #     ''.chars          # => []
  #
  # Related: see [Converting to
  # Non-String](rdoc-ref:String@Converting+to+Non--5CString).
  #
  def chars: () -> Array[String]
           | () { (String char) -> void } -> self

  # <!--
  #   rdoc-file=string.c
  #   - chomp(line_sep = $/) -> new_string
  # -->
  # Returns a new string copied from `self`, with trailing characters possibly
  # removed:
  #
  # When `line_sep` is `"\n"`, removes the last one or two characters if they are
  # `"\r"`, `"\n"`, or `"\r\n"` (but not `"\n\r"`):
  #
  #     $/                    # => "\n"
  #     "abc\r".chomp         # => "abc"
  #     "abc\n".chomp         # => "abc"
  #     "abc\r\n".chomp       # => "abc"
  #     "abc\n\r".chomp       # => "abc\n"
  #     "тест\r\n".chomp      # => "тест"
  #     "こんにちは\r\n".chomp  # => "こんにちは"
  #
  # When `line_sep` is `''` (an empty string), removes multiple trailing
  # occurrences of `"\n"` or `"\r\n"` (but not `"\r"` or `"\n\r"`):
  #
  #     "abc\n\n\n".chomp('')           # => "abc"
  #     "abc\r\n\r\n\r\n".chomp('')     # => "abc"
  #     "abc\n\n\r\n\r\n\n\n".chomp('') # => "abc"
  #     "abc\n\r\n\r\n\r".chomp('')     # => "abc\n\r\n\r\n\r"
  #     "abc\r\r\r".chomp('')           # => "abc\r\r\r"
  #
  # When `line_sep` is neither `"\n"` nor `''`, removes a single trailing line
  # separator if there is one:
  #
  #     'abcd'.chomp('cd')   # => "ab"
  #     'abcdcd'.chomp('cd') # => "abcd"
  #     'abcd'.chomp('xx')   # => "abcd"
  #
  # Related: see [Converting to New
  # String](rdoc-ref:String@Converting+to+New+String).
  #
  def chomp: (?string? separator) -> String

  # <!--
  #   rdoc-file=string.c
  #   - chomp!(line_sep = $/) -> self or nil
  # -->
  # Like String#chomp, except that:
  #
  # *   Removes trailing characters from `self` (not from a copy of `self`).
  # *   Returns `self` if any characters are removed, `nil` otherwise.
  #
  # Related: see [Modifying](rdoc-ref:String@Modifying).
  #
  def chomp!: (nil) -> nil
          # | (?string separator) -> self? # https://github.com/ruby/rbs/pull/1672#discussion_r1423324796
            | (?string? separator) -> self?

  # <!--
  #   rdoc-file=string.c
  #   - chop -> new_string
  # -->
  # Returns a new string copied from `self`, with trailing characters possibly
  # removed.
  #
  # Removes `"\r\n"` if those are the last two characters.
  #
  #     "abc\r\n".chop      # => "abc"
  #     "тест\r\n".chop     # => "тест"
  #     "こんにちは\r\n".chop # => "こんにちは"
  #
  # Otherwise removes the last character if it exists.
  #
  #     'abcd'.chop     # => "abc"
  #     'тест'.chop     # => "тес"
  #     'こんにちは'.chop # => "こんにち"
  #     ''.chop         # => ""
  #
  # If you only need to remove the newline separator at the end of the string,
  # String#chomp is a better alternative.
  #
  # Related: see [Converting to New
  # String](rdoc-ref:String@Converting+to+New+String).
  #
  def chop: () -> String

  # <!--
  #   rdoc-file=string.c
  #   - chop! -> self or nil
  # -->
  # Like String#chop, except that:
  #
  # *   Removes trailing characters from `self` (not from a copy of `self`).
  # *   Returns `self` if any characters are removed, `nil` otherwise.
  #
  # Related: see [Modifying](rdoc-ref:String@Modifying).
  #
  def chop!: () -> self?

  # <!--
  #   rdoc-file=string.c
  #   - chr -> string
  # -->
  # Returns a string containing the first character of `self`:
  #
  #     'hello'.chr     # => "h"
  #     'тест'.chr      # => "т"
  #     'こんにちは'.chr # => "こ"
  #     ''.chr          # => ""
  #
  # Related: see [Converting to New
  # String](rdoc-ref:String@Converting+to+New+String).
  #
  def chr: () -> String

  # <!--
  #   rdoc-file=string.c
  #   - clear -> self
  # -->
  # Removes the contents of `self`:
  #
  #     s = 'foo'
  #     s.clear # => ""
  #     s       # => ""
  #
  # Related: see [Modifying](rdoc-ref:String@Modifying).
  #
  def clear: () -> self

  # <!--
  #   rdoc-file=string.c
  #   - codepoints -> array_of_integers
  # -->
  # Returns an array of the codepoints in `self`; each codepoint is the integer
  # value for a character:
  #
  #     'hello'.codepoints     # => [104, 101, 108, 108, 111]
  #     'тест'.codepoints      # => [1090, 1077, 1089, 1090]
  #     'こんにちは'.codepoints # => [12371, 12435, 12395, 12385, 12399]
  #     ''.codepoints          # => []
  #
  # Related: see [Converting to
  # Non-String](rdoc-ref:String@Converting+to+Non--5CString).
  #
  def codepoints: () -> Array[Integer]
                | () { (Integer codepoint) -> void } -> self

  # <!--
  #   rdoc-file=string.c
  #   - concat(*objects) -> string
  # -->
  # Concatenates each object in `objects` to `self`; returns `self`:
  #
  #     'foo'.concat('bar', 'baz') # => "foobarbaz"
  #
  # For each given object `object` that is an integer, the value is considered a
  # codepoint and converted to a character before concatenation:
  #
  #     'foo'.concat(32, 'bar', 32, 'baz') # => "foo bar baz" # Embeds spaces.
  #     'те'.concat(1089, 1090)            # => "тест"
  #     'こん'.concat(12395, 12385, 12399)  # => "こんにちは"
  #
  # Related: see [Converting to New
  # String](rdoc-ref:String@Converting+to+New+String).
  #
  def concat: (*string | Integer string_or_codepoints) -> self

  # <!--
  #   rdoc-file=string.c
  #   - count(*selectors) -> integer
  # -->
  # Returns the total number of characters in `self` that are specified by the
  # given selectors.
  #
  # For one 1-character selector, returns the count of instances of that
  # character:
  #
  #     s = 'abracadabra'
  #     s.count('a') # => 5
  #     s.count('b') # => 2
  #     s.count('x') # => 0
  #     s.count('')  # => 0
  #
  #     s = 'тест'
  #     s.count('т')  # => 2
  #     s.count('е')  # => 1
  #
  #     s = 'よろしくお願いします'
  #     s.count('よ')  # => 1
  #     s.count('し')  # => 2
  #
  # For one multi-character selector, returns the count of instances for all
  # specified characters:
  #
  #     s = 'abracadabra'
  #     s.count('ab')     # => 7
  #     s.count('abc')    # => 8
  #     s.count('abcd')   # => 9
  #     s.count('abcdr')  # => 11
  #     s.count('abcdrx') # => 11
  #
  # Order and repetition do not matter:
  #
  #     s.count('ba')   == s.count('ab') # => true
  #     s.count('baab') == s.count('ab') # => true
  #
  # For multiple selectors, forms a single selector that is the intersection of
  # characters in all selectors and returns the count of instances for that
  # selector:
  #
  #     s = 'abcdefg'
  #     s.count('abcde', 'dcbfg') == s.count('bcd') # => true
  #     s.count('abc', 'def')     == s.count('')    # => true
  #
  # In a character selector, three characters get special treatment:
  #
  # *   A caret (`'^'`) functions as a *negation* operator for the immediately
  #     following characters:
  #
  #         s = 'abracadabra'
  #         s.count('^bc') # => 8  # Count of all except 'b' and 'c'.
  #
  # *   A hyphen (`'-'`) between two other characters defines a *range* of
  #     characters:
  #
  #         s = 'abracadabra'
  #         s.count('a-c') # => 8  # Count of all 'a', 'b', and 'c'.
  #
  # *   A backslash (`'\'`) acts as an escape for a caret, a hyphen, or another
  #     backslash:
  #
  #         s = 'abracadabra'
  #         s.count('\^bc')           # => 3  # Count of '^', 'b', and 'c'.
  #         s.count('a\-c')           # => 6  # Count of 'a', '-', and 'c'.
  #         'foo\bar\baz'.count('\\') # => 2  # Count of '\'.
  #
  # These usages may be mixed:
  #
  #     s = 'abracadabra'
  #     s.count('a-cq-t') # => 10  # Multiple ranges.
  #     s.count('ac-d')   # => 7   # Range mixed with plain characters.
  #     s.count('^a-c')   # => 3   # Range mixed with negation.
  #
  # For multiple selectors, all forms may be used, including negations, ranges,
  # and escapes.
  #
  #     s = 'abracadabra'
  #     s.count('^abc', '^def') == s.count('^abcdef') # => true
  #     s.count('a-e', 'c-g')   == s.count('cde')     # => true
  #     s.count('^abc', 'c-g')  == s.count('defg')    # => true
  #
  # Related: see [Querying](rdoc-ref:String@Querying).
  #
  def count: (selector selector_0, *selector more_selectors) -> Integer

  # <!--
  #   rdoc-file=string.c
  #   - crypt(salt_str) -> new_string
  # -->
  # Returns the string generated by calling `crypt(3)` standard library function
  # with `str` and `salt_str`, in this order, as its arguments.  Please do not use
  # this method any longer.  It is legacy; provided only for backward
  # compatibility with ruby scripts in earlier days.  It is bad to use in
  # contemporary programs for several reasons:
  #
  # *   Behaviour of C's `crypt(3)` depends on the OS it is run.  The generated
  #     string lacks data portability.
  #
  # *   On some OSes such as Mac OS, `crypt(3)` never fails (i.e. silently ends up
  #     in unexpected results).
  #
  # *   On some OSes such as Mac OS, `crypt(3)` is not thread safe.
  #
  # *   So-called "traditional" usage of `crypt(3)` is very very very weak.
  #     According to its manpage, Linux's traditional `crypt(3)` output has only
  #     2**56 variations; too easy to brute force today.  And this is the default
  #     behaviour.
  #
  # *   In order to make things robust some OSes implement so-called "modular"
  #     usage. To go through, you have to do a complex build-up of the `salt_str`
  #     parameter, by hand. Failure in generation of a proper salt string tends
  #     not to yield any errors; typos in parameters are normally not detectable.
  #
  #     *   For instance, in the following example, the second invocation of
  #         String#crypt is wrong; it has a typo in "round=" (lacks "s").  However
  #         the call does not fail and something unexpected is generated.
  #
  #             "foo".crypt("$5$rounds=1000$salt$") # OK, proper usage
  #             "foo".crypt("$5$round=1000$salt$")  # Typo not detected
  #
  # *   Even in the "modular" mode, some hash functions are considered archaic and
  #     no longer recommended at all; for instance module `$1$` is officially
  #     abandoned by its author: see http://phk.freebsd.dk/sagas/md5crypt_eol/ .
  #     For another instance module `$3$` is considered completely broken: see the
  #     manpage of FreeBSD.
  #
  # *   On some OS such as Mac OS, there is no modular mode. Yet, as written
  #     above, `crypt(3)` on Mac OS never fails. This means even if you build up a
  #     proper salt string it generates a traditional DES hash anyways, and there
  #     is no way for you to be aware of.
  #
  #         "foo".crypt("$5$rounds=1000$salt$") # => "$5fNPQMxC5j6."
  #
  # If for some reason you cannot migrate to other secure contemporary password
  # hashing algorithms, install the string-crypt gem and `require 'string/crypt'`
  # to continue using it.
  #
  def crypt: (string salt_str) -> String

  # <!-- rdoc-file=string.c -->
  # Returns a frozen string equal to `self`.
  #
  # The returned string is `self` if and only if all of the following are true:
  #
  # *   `self` is already frozen.
  # *   `self` is an instance of String (rather than of a subclass of String)
  # *   `self` has no instance variables set on it.
  #
  # Otherwise, the returned string is a frozen copy of `self`.
  #
  # Returning `self`, when possible, saves duplicating `self`; see [Data
  # deduplication](https://en.wikipedia.org/wiki/Data_deduplication).
  #
  # It may also save duplicating other, already-existing, strings:
  #
  #     s0 = 'foo'
  #     s1 = 'foo'
  #     s0.object_id == s1.object_id       # => false
  #     (-s0).object_id == (-s1).object_id # => true
  #
  # Note that method #-@ is convenient for defining a constant:
  #
  #     FileName = -'config/database.yml'
  #
  # While its alias #dedup is better suited for chaining:
  #
  #     'foo'.dedup.gsub!('o')
  #
  # Related: see [Freezing/Unfreezing](rdoc-ref:String@Freezing-2FUnfreezing).
  #
  alias dedup -@

  # <!--
  #   rdoc-file=string.c
  #   - delete(*selectors) -> new_string
  # -->
  # Returns a new string that is a copy of `self` with certain characters removed;
  # the removed characters are all instances of those specified by the given
  # string `selectors`.
  #
  # For one 1-character selector, removes all instances of that character:
  #
  #     s = 'abracadabra'
  #     s.delete('a') # => "brcdbr"
  #     s.delete('b') # => "aracadara"
  #     s.delete('x') # => "abracadabra"
  #     s.delete('')  # => "abracadabra"
  #
  #     s = 'тест'
  #     s.delete('т') # => "ес"
  #     s.delete('е') # => "тст"
  #
  #     s = 'よろしくお願いします'
  #     s.delete('よ') # => "ろしくお願いします"
  #     s.delete('し') # => "よろくお願います"
  #
  # For one multi-character selector, removes all instances of the specified
  # characters:
  #
  #     s = 'abracadabra'
  #     s.delete('ab')     # => "rcdr"
  #     s.delete('abc')    # => "rdr"
  #     s.delete('abcd')   # => "rr"
  #     s.delete('abcdr')  # => ""
  #     s.delete('abcdrx') # => ""
  #
  # Order and repetition do not matter:
  #
  #     s.delete('ba')   == s.delete('ab') # => true
  #     s.delete('baab') == s.delete('ab') # => true
  #
  # For multiple selectors, forms a single selector that is the intersection of
  # characters in all selectors and removes all instances of characters specified
  # by that selector:
  #
  #     s = 'abcdefg'
  #     s.delete('abcde', 'dcbfg') == s.delete('bcd') # => true
  #     s.delete('abc', 'def')     == s.delete('')    # => true
  #
  # In a character selector, three characters get special treatment:
  #
  # *   A caret (`'^'`) functions as a *negation* operator for the immediately
  #     following characters:
  #
  #         s = 'abracadabra'
  #         s.delete('^bc') # => "bcb"  # Deletes all except 'b' and 'c'.
  #
  # *   A hyphen (`'-'`) between two other characters defines a *range* of
  #     characters:
  #
  #         s = 'abracadabra'
  #         s.delete('a-c') # => "rdr"  # Deletes all 'a', 'b', and 'c'.
  #
  # *   A backslash (`'\'`) acts as an escape for a caret, a hyphen, or another
  #     backslash:
  #
  #         s = 'abracadabra'
  #         s.delete('\^bc')           # => "araadara"   # Deletes all '^', 'b', and 'c'.
  #         s.delete('a\-c')           # => "brdbr"      # Deletes all 'a', '-', and 'c'.
  #         'foo\bar\baz'.delete('\\') # => "foobarbaz"  # Deletes all '\'.
  #
  # These usages may be mixed:
  #
  #     s = 'abracadabra'
  #     s.delete('a-cq-t') # => "d"         # Multiple ranges.
  #     s.delete('ac-d')   # => "brbr"      # Range mixed with plain characters.
  #     s.delete('^a-c')   # => "abacaaba"  # Range mixed with negation.
  #
  # For multiple selectors, all forms may be used, including negations, ranges,
  # and escapes.
  #
  #     s = 'abracadabra'
  #     s.delete('^abc', '^def') == s.delete('^abcdef') # => true
  #     s.delete('a-e', 'c-g')   == s.delete('cde')     # => true
  #     s.delete('^abc', 'c-g')  == s.delete('defg')    # => true
  #
  # Related: see [Converting to New
  # String](rdoc-ref:String@Converting+to+New+String).
  #
  def delete: (selector selector_0, *selector more_selectors) -> String

  # <!--
  #   rdoc-file=string.c
  #   - delete!(*selectors) -> self or nil
  # -->
  # Like String#delete, but modifies `self` in place; returns `self` if any
  # characters were deleted, `nil` otherwise.
  #
  # Related: see [Modifying](rdoc-ref:String@Modifying).
  #
  def delete!: (selector selector_0, *selector more_selectors) -> self?

  # <!--
  #   rdoc-file=string.c
  #   - delete_prefix(prefix) -> new_string
  # -->
  # Returns a copy of `self` with leading substring `prefix` removed:
  #
  #     'oof'.delete_prefix('o')          # => "of"
  #     'oof'.delete_prefix('oo')         # => "f"
  #     'oof'.delete_prefix('oof')        # => ""
  #     'oof'.delete_prefix('x')          # => "oof"
  #     'тест'.delete_prefix('те')        # => "ст"
  #     'こんにちは'.delete_prefix('こん')  # => "にちは"
  #
  # Related: see [Converting to New
  # String](rdoc-ref:String@Converting+to+New+String).
  #
  def delete_prefix: (string prefix) -> String

  # <!--
  #   rdoc-file=string.c
  #   - delete_prefix!(prefix) -> self or nil
  # -->
  # Like String#delete_prefix, except that `self` is modified in place; returns
  # `self` if the prefix is removed, `nil` otherwise.
  #
  # Related: see [Modifying](rdoc-ref:String@Modifying).
  #
  def delete_prefix!: (string prefix) -> self?

  # <!--
  #   rdoc-file=string.c
  #   - delete_suffix(suffix) -> new_string
  # -->
  # Returns a copy of `self` with trailing substring `suffix` removed:
  #
  #     'foo'.delete_suffix('o')           # => "fo"
  #     'foo'.delete_suffix('oo')          # => "f"
  #     'foo'.delete_suffix('foo')         # => ""
  #     'foo'.delete_suffix('f')           # => "foo"
  #     'foo'.delete_suffix('x')           # => "foo"
  #     'тест'.delete_suffix('ст')         # => "те"
  #     'こんにちは'.delete_suffix('ちは')  # => "こんに"
  #
  # Related: see [Converting to New
  # String](rdoc-ref:String@Converting+to+New+String).
  #
  def delete_suffix: (string suffix) -> String

  # <!--
  #   rdoc-file=string.c
  #   - delete_suffix!(suffix) -> self or nil
  # -->
  # Like String#delete_suffix, except that `self` is modified in place; returns
  # `self` if the suffix is removed, `nil` otherwise.
  #
  # Related: see [Modifying](rdoc-ref:String@Modifying).
  #
  def delete_suffix!: (string suffix) -> self?

  # <!--
  #   rdoc-file=string.c
  #   - downcase(mapping = :ascii) -> new_string
  # -->
  # Returns a new string containing the downcased characters in `self`:
  #
  #     'HELLO'.downcase        # => "hello"
  #     'STRAẞE'.downcase       # => "straße"
  #     'ПРИВЕТ'.downcase       # => "привет"
  #     'RubyGems.org'.downcase # => "rubygems.org"
  #
  # Some characters (and some character sets) do not have upcase and downcase
  # versions; see [Case Mapping](rdoc-ref:case_mapping.rdoc):
  #
  #     s = '1, 2, 3, ...'
  #     s.downcase == s # => true
  #     s = 'こんにちは'
  #     s.downcase == s # => true
  #
  # The casing is affected by the given `mapping`, which may be `:ascii`, `:fold`,
  # or `:turkic`; see [Case Mappings](rdoc-ref:case_mapping.rdoc@Case+Mappings).
  #
  # Related: see [Converting to New
  # String](rdoc-ref:String@Converting+to+New+String).
  #
  def downcase: () -> String
              | (:ascii | :fold | :lithuanian | :turkic) -> String
              | (:lithuanian, :turkic) -> String
              | (:turkic, :lithuanian) -> String

  # <!--
  #   rdoc-file=string.c
  #   - downcase!(mapping) -> self or nil
  # -->
  # Like String#downcase, except that:
  #
  # *   Changes character casings in `self` (not in a copy of `self`).
  # *   Returns `self` if any changes are made, `nil` otherwise.
  #
  # Related: See [Modifying](rdoc-ref:String@Modifying).
  #
  def downcase!: () -> self?
               | (:ascii | :fold | :lithuanian | :turkic) -> self?
               | (:lithuanian, :turkic) -> self?
               | (:turkic, :lithuanian) -> self?

  # <!--
  #   rdoc-file=string.c
  #   - dump -> new_string
  # -->
  # For an ordinary string, this method, +String#dump+, returns a printable
  # ASCII-only version of `self`, enclosed in double-quotes.
  #
  # For a dumped string, method String#undump is the inverse of +String#dump+; it
  # returns a "restored" version of `self`, where all the dumping changes have
  # been undone.
  #
  # In the simplest case, the dumped string contains the original string, enclosed
  # in double-quotes; this example is done in `irb` (interactive Ruby), which uses
  # method `inspect` to render the results:
  #
  #     s = 'hello'   # => "hello"
  #     s.dump        # => "\"hello\""
  #     s.dump.undump # => "hello"
  #
  # Keep in mind that in the second line above:
  #
  # *   The outer double-quotes are put on by `inspect`, and *are* *not* part of
  #     the output of #dump.
  # *   The inner double-quotes *are* part of the output of `dump`, and are
  #     escaped by `inspect` because they are within the outer double-quotes.
  #
  # To avoid confusion, we'll use this helper method to omit the outer
  # double-quotes:
  #
  #     def dump(s)
  #       print "String:   ", s, "\n"
  #       print "Dumped:   ", s.dump, "\n"
  #       print "Undumped: ", s.dump.undump, "\n"
  #     end
  #
  # So that for string `'hello'`, we'll see:
  #
  #     String:    hello
  #     Dumped:    "hello"
  #     Undumped:  hello
  #
  # In a dump, certain special characters are escaped:
  #
  #     String:    "
  #     Dumped:    "\""
  #     Undumped:  "
  #
  #     String:    \
  #     Dumped:    "\\"
  #     Undumped:  \
  #
  # In a dump, unprintable characters are replaced by printable ones; the
  # unprintable characters are the whitespace characters (other than space
  # itself); here we see the ordinals for those characers, together with
  # explanatory text:
  #
  #     h = {
  #        7 => 'Alert (BEL)',
  #        8 => 'Backspace (BS)',
  #        9 => 'Horizontal tab (HT)',
  #       10 => 'Linefeed (LF)',
  #       11 => 'Vertical tab (VT)',
  #       12 => 'Formfeed (FF)',
  #       13 => 'Carriage return (CR)'
  #     }
  #
  # In this example, the dumped output is printed by method #inspect, and so
  # contains both outer double-quotes and escaped inner double-quotes:
  #
  #     s = ''
  #     h.keys.each {|i| s << i } # => [7, 8, 9, 10, 11, 12, 13]
  #     s                         # => "\a\b\t\n\v\f\r"
  #     s.dump                    # => "\"\\a\\b\\t\\n\\v\\f\\r\""
  #
  # If `self` is encoded in UTF-8 and contains Unicode characters, each Unicode
  # character is dumped as a Unicode escape sequence:
  #
  #     String:    тест
  #     Dumped:    "\u0442\u0435\u0441\u0442"
  #     Undumped:  тест
  #
  #     String:    こんにちは
  #     Dumped:    "\u3053\u3093\u306B\u3061\u306F"
  #     Undumped:  こんにちは
  #
  # If the encoding of `self` is not ASCII-compatible (i.e., if
  # `self.encoding.ascii_compatible?` returns `false`), each ASCII-compatible byte
  # is dumped as an ASCII character, and all other bytes are dumped as
  # hexadecimal; also appends `.dup.force_encoding(\"encoding\")`, where
  # `<encoding>` is `self.encoding.name`:
  #
  #     String:    hello
  #     Dumped:    "\xFE\xFF\x00h\x00e\x00l\x00l\x00o".dup.force_encoding("UTF-16")
  #     Undumped:  hello
  #
  #     String:    тест
  #     Dumped:    "\xFE\xFF\x04B\x045\x04A\x04B".dup.force_encoding("UTF-16")
  #     Undumped:  тест
  #
  #     String:    こんにちは
  #     Dumped:    "\xFE\xFF0S0\x930k0a0o".dup.force_encoding("UTF-16")
  #     Undumped:  こんにちは
  #
  def dump: () -> String

  # <!--
  #   rdoc-file=string.c
  #   - each_byte {|byte| ... } -> self
  #   - each_byte               -> enumerator
  # -->
  # With a block given, calls the block with each successive byte from `self`;
  # returns `self`:
  #
  #     a = []
  #     'hello'.each_byte {|byte| a.push(byte) }     # Five 1-byte characters.
  #     a # => [104, 101, 108, 108, 111]
  #     a = []
  #     'тест'.each_byte {|byte| a.push(byte) }      # Four 2-byte characters.
  #     a # => [209, 130, 208, 181, 209, 129, 209, 130]
  #     a = []
  #     'こんにちは'.each_byte {|byte| a.push(byte) }  # Five 3-byte characters.
  #     a # => [227, 129, 147, 227, 130, 147, 227, 129, 171, 227, 129, 161, 227, 129, 175]
  #
  # With no block given, returns an enumerator.
  #
  # Related: see [Iterating](rdoc-ref:String@Iterating).
  #
  def each_byte: () -> Enumerator[Integer, self]
               | () { (Integer byte) -> void } -> self

  # <!--
  #   rdoc-file=string.c
  #   - each_char {|char| ... } -> self
  #   - each_char            -> enumerator
  # -->
  # With a block given, calls the block with each successive character from
  # `self`; returns `self`:
  #
  #     a = []
  #     'hello'.each_char do |char|
  #       a.push(char)
  #     end
  #     a # => ["h", "e", "l", "l", "o"]
  #     a = []
  #     'тест'.each_char do |char|
  #       a.push(char)
  #     end
  #     a # => ["т", "е", "с", "т"]
  #     a = []
  #     'こんにちは'.each_char do |char|
  #       a.push(char)
  #     end
  #     a # => ["こ", "ん", "に", "ち", "は"]
  #
  # With no block given, returns an enumerator.
  #
  # Related: see [Iterating](rdoc-ref:String@Iterating).
  #
  def each_char: () -> Enumerator[String, self]
               | () { (String char) -> void } -> self

  # <!--
  #   rdoc-file=string.c
  #   - each_codepoint {|codepoint| ... } -> self
  #   - each_codepoint                  -> enumerator
  # -->
  # With a block given, calls the block with each successive codepoint from
  # `self`; each [codepoint](https://en.wikipedia.org/wiki/Code_point) is the
  # integer value for a character; returns `self`:
  #
  #     a = []
  #     'hello'.each_codepoint do |codepoint|
  #       a.push(codepoint)
  #     end
  #     a # => [104, 101, 108, 108, 111]
  #     a = []
  #     'тест'.each_codepoint do |codepoint|
  #       a.push(codepoint)
  #     end
  #     a # => [1090, 1077, 1089, 1090]
  #     a = []
  #     'こんにちは'.each_codepoint do |codepoint|
  #       a.push(codepoint)
  #     end
  #     a # => [12371, 12435, 12395, 12385, 12399]
  #
  # With no block given, returns an enumerator.
  #
  # Related: see [Iterating](rdoc-ref:String@Iterating).
  #
  def each_codepoint: () -> Enumerator[Integer, self]
                    | () { (Integer codepoint) -> void } -> self

  # <!--
  #   rdoc-file=string.c
  #   - each_grapheme_cluster {|grapheme_cluster| ... } -> self
  #   - each_grapheme_cluster             -> enumerator
  # -->
  # With a block given, calls the given block with each successive grapheme
  # cluster from `self` (see [Unicode Grapheme Cluster
  # Boundaries](https://www.unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries)
  # ); returns `self`:
  #
  #     a = []
  #     'hello'.each_grapheme_cluster do |grapheme_cluster|
  #       a.push(grapheme_cluster)
  #     end
  #     a  # => ["h", "e", "l", "l", "o"]
  #
  #     a = []
  #     'тест'.each_grapheme_cluster do |grapheme_cluster|
  #       a.push(grapheme_cluster)
  #     end
  #     a # => ["т", "е", "с", "т"]
  #
  #     a = []
  #     'こんにちは'.each_grapheme_cluster do |grapheme_cluster|
  #       a.push(grapheme_cluster)
  #     end
  #     a # => ["こ", "ん", "に", "ち", "は"]
  #
  # With no block given, returns an enumerator.
  #
  # Related: see [Iterating](rdoc-ref:String@Iterating).
  #
  def each_grapheme_cluster: () -> Enumerator[String, self]
                           | () { (String grapheme_cluter) -> void } -> self

  # <!--
  #   rdoc-file=string.c
  #   - each_line(record_separator = $/, chomp: false) {|substring| ... } -> self
  #   - each_line(record_separator = $/, chomp: false)                    -> enumerator
  # -->
  # With a block given, forms the substrings (lines) that are the result of
  # splitting `self` at each occurrence of the given `record_separator`; passes
  # each line to the block; returns `self`.
  #
  # With the default `record_separator`:
  #
  #     $/ # => "\n"
  #     s = <<~EOT
  #     This is the first line.
  #     This is line two.
  #
  #     This is line four.
  #     This is line five.
  #     EOT
  #     s.each_line {|line| p line }
  #
  # Output:
  #
  #     "This is the first line.\n"
  #     "This is line two.\n"
  #     "\n"
  #     "This is line four.\n"
  #     "This is line five.\n"
  #
  # With a different `record_separator`:
  #
  #     record_separator = ' is '
  #     s.each_line(record_separator) {|line| p line }
  #
  # Output:
  #
  #     "This is "
  #     "the first line.\nThis is "
  #     "line two.\n\nThis is "
  #     "line four.\nThis is "
  #     "line five.\n"
  #
  # With `chomp` as `true`, removes the trailing `record_separator` from each
  # line:
  #
  #     s.each_line(chomp: true) {|line| p line }
  #
  # Output:
  #
  #     "This is the first line."
  #     "This is line two."
  #     ""
  #     "This is line four."
  #     "This is line five."
  #
  # With an empty string as `record_separator`, forms and passes "paragraphs" by
  # splitting at each occurrence of two or more newlines:
  #
  #     record_separator = ''
  #     s.each_line(record_separator) {|line| p line }
  #
  # Output:
  #
  #     "This is the first line.\nThis is line two.\n\n"
  #     "This is line four.\nThis is line five.\n"
  #
  # With no block given, returns an enumerator.
  #
  # Related: see [Iterating](rdoc-ref:String@Iterating).
  #
  def each_line: (?string? separator, ?chomp: boolish) -> Enumerator[String, self]
               | (?string? separator, ?chomp: boolish) { (String line) -> void } -> self

  # <!--
  #   rdoc-file=string.c
  #   - empty? -> true or false
  # -->
  # Returns whether the length of `self` is zero:
  #
  #     'hello'.empty? # => false
  #     ' '.empty? # => false
  #     ''.empty? # => true
  #
  # Related: see [Querying](rdoc-ref:String@Querying).
  #
  def empty?: () -> bool

  # <!--
  #   rdoc-file=transcode.c
  #   - encode(dst_encoding = Encoding.default_internal, **enc_opts) -> string
  #   - encode(dst_encoding, src_encoding, **enc_opts)   -> string
  # -->
  # Returns a copy of `self` transcoded as determined by `dst_encoding`; see
  # [Encodings](rdoc-ref:encodings.rdoc).
  #
  # By default, raises an exception if `self` contains an invalid byte or a
  # character not defined in `dst_encoding`; that behavior may be modified by
  # encoding options; see below.
  #
  # With no arguments:
  #
  # *   Uses the same encoding if `Encoding.default_internal` is `nil` (the
  #     default):
  #
  #         Encoding.default_internal # => nil
  #         s = "Ruby\x99".force_encoding('Windows-1252')
  #         s.encoding                # => #<Encoding:Windows-1252>
  #         s.bytes                   # => [82, 117, 98, 121, 153]
  #         t = s.encode              # => "Ruby\x99"
  #         t.encoding                # => #<Encoding:Windows-1252>
  #         t.bytes                   # => [82, 117, 98, 121, 226, 132, 162]
  #
  # *   Otherwise, uses the encoding `Encoding.default_internal`:
  #
  #         Encoding.default_internal = 'UTF-8'
  #         t = s.encode              # => "Ruby™"
  #         t.encoding                # => #<Encoding:UTF-8>
  #
  # With only argument `dst_encoding` given, uses that encoding:
  #
  #     s = "Ruby\x99".force_encoding('Windows-1252')
  #     s.encoding            # => #<Encoding:Windows-1252>
  #     t = s.encode('UTF-8') # => "Ruby™"
  #     t.encoding            # => #<Encoding:UTF-8>
  #
  # With arguments `dst_encoding` and `src_encoding` given, interprets `self`
  # using `src_encoding`, encodes the new string using `dst_encoding`:
  #
  #     s = "Ruby\x99"
  #     t = s.encode('UTF-8', 'Windows-1252') # => "Ruby™"
  #     t.encoding                            # => #<Encoding:UTF-8>
  #
  # Optional keyword arguments `enc_opts` specify encoding options; see [Encoding
  # Options](rdoc-ref:encodings.rdoc@Encoding+Options).
  #
  # Please note that, unless `invalid: :replace` option is given, conversion from
  # an encoding `enc` to the same encoding `enc` (independent of whether `enc` is
  # given explicitly or implicitly) is a no-op, i.e. the string is simply copied
  # without any changes, and no exceptions are raised, even if there are invalid
  # bytes.
  #
  # Related: see [Converting to New
  # String](rdoc-ref:String@Converting+to+New+String).
  #
  def encode: (
    ?encoding source_encoding,
    ?encoding? from_encoding,
    ?invalid: :replace ?,
    ?undef: :replace ?,
    ?replace: string?,
    ?xml: (:text | :attr)?,
    ?newline: (:universal | :crlf | :cr | :lf)?,
    ?universal_newline: boolish,
    ?cr_newline: boolish,
    ?crlf_newline: boolish,
    ?lf_newline: boolish,
    ?fallback: ^(String) -> string? | Method | _EncodeFallbackAref
  ) -> self

  interface _EncodeFallbackAref
    def []: (String) -> string?
  end

  # <!--
  #   rdoc-file=transcode.c
  #   - encode!(dst_encoding = Encoding.default_internal, **enc_opts) -> self
  #   - encode!(dst_encoding, src_encoding, **enc_opts)   -> self
  # -->
  # Like #encode, but applies encoding changes to `self`; returns `self`.
  #
  # Related: see [Modifying](rdoc-ref:String@Modifying).
  #
  def encode!: (
    ?encoding source_encoding,
    ?encoding? from_encoding,
    ?invalid: :replace ?,
    ?undef: :replace ?,
    ?replace: string?,
    ?xml: (:text | :attr)?,
    ?newline: (:universal | :crlf | :cr | :lf)?,
    ?universal_newline: boolish,
    ?cr_newline: boolish,
    ?crlf_newline: boolish,
    ?lf_newline: boolish,
    ?fallback: ^(String) -> string? | Method | _EncodeFallbackAref
  ) -> self

  # <!--
  #   rdoc-file=string.c
  #   - encoding -> encoding
  # -->
  # Returns an Encoding object that represents the encoding of `self`; see
  # [Encodings](rdoc-ref:encodings.rdoc).
  #
  # Related: see [Querying](rdoc-ref:String@Querying).
  #
  def encoding: () -> Encoding

  # <!--
  #   rdoc-file=string.c
  #   - end_with?(*strings) -> true or false
  # -->
  # Returns whether `self` ends with any of the given `strings`:
  #
  #     'foo'.end_with?('oo')         # => true
  #     'foo'.end_with?('bar', 'oo')  # => true
  #     'foo'.end_with?('bar', 'baz') # => false
  #     'foo'.end_with?('')           # => true
  #     'тест'.end_with?('т')         # => true
  #     'こんにちは'.end_with?('は')   # => true
  #
  # Related: see [Querying](rdoc-ref:String@Querying).
  #
  def end_with?: (*string suffixes) -> bool

  # <!--
  #   rdoc-file=string.c
  #   - eql?(object) -> true or false
  # -->
  # Returns whether `self` and `object` have the same length and content:
  #
  #     s = 'foo'
  #     s.eql?('foo')  # => true
  #     s.eql?('food') # => false
  #     s.eql?('FOO')  # => false
  #
  # Returns `false` if the two strings' encodings are not compatible:
  #
  #     s0 = "äöü"                           # => "äöü"
  #     s1 = s0.encode(Encoding::ISO_8859_1) # => "\xE4\xF6\xFC"
  #     s0.encoding                          # => #<Encoding:UTF-8>
  #     s1.encoding                          # => #<Encoding:ISO-8859-1>
  #     s0.eql?(s1)                          # => false
  #
  # See [Encodings](rdoc-ref:encodings.rdoc).
  #
  # Related: see [Querying](rdoc-ref:String@Querying).
  #
  def eql?: (untyped other) -> bool

  # <!--
  #   rdoc-file=string.c
  #   - force_encoding(encoding) -> self
  # -->
  # Changes the encoding of `self` to the given `encoding`, which may be a string
  # encoding name or an Encoding object; does not change the underlying bytes;
  # returns self:
  #
  #     s = 'łał'
  #     s.bytes                   # => [197, 130, 97, 197, 130]
  #     s.encoding                # => #<Encoding:UTF-8>
  #     s.force_encoding('ascii') # => "\xC5\x82a\xC5\x82"
  #     s.encoding                # => #<Encoding:US-ASCII>
  #     s.valid_encoding?         # => true
  #     s.bytes                   # => [197, 130, 97, 197, 130]
  #
  # Makes the change even if the given `encoding` is invalid for `self` (as is the
  # change above):
  #
  #     s.valid_encoding?         # => false
  #
  # See [Encodings](rdoc-ref:encodings.rdoc).
  #
  # Related: see [Modifying](rdoc-ref:String@Modifying).
  #
  def force_encoding: (encoding enc) -> self

  # <!--
  #   rdoc-file=string.c
  #   - freeze()
  # -->
  #
  def freeze: () -> self

  # <!--
  #   rdoc-file=string.c
  #   - getbyte(index) -> integer or nil
  # -->
  # Returns the byte at zero-based `index` as an integer:
  #
  #     s = 'foo'
  #     s.getbyte(0)    # => 102
  #     s.getbyte(1)    # => 111
  #     s.getbyte(2)    # => 111
  #
  # Counts backward from the end if `index` is negative:
  #
  #     s.getbyte(-3) # => 102
  #
  # Returns `nil` if `index` is out of range:
  #
  #     s.getbyte(3)  # => nil
  #     s.getbyte(-4) # => nil
  #
  # More examples:
  #
  #     s = 'тест'
  #     s.bytes      # => [209, 130, 208, 181, 209, 129, 209, 130]
  #     s.getbyte(2) # => 208
  #     s = 'こんにちは'
  #     s.bytes      # => [227, 129, 147, 227, 130, 147, 227, 129, 171, 227, 129, 161, 227, 129, 175]
  #     s.getbyte(2) # => 147
  #
  # Related: see [Converting to
  # Non-String](rdoc-ref:String@Converting+to+Non--5CString).
  #
  def getbyte: (int index) -> Integer?

  # <!--
  #   rdoc-file=string.c
  #   - grapheme_clusters -> array_of_grapheme_clusters
  # -->
  # Returns an array of the grapheme clusters in `self` (see [Unicode Grapheme
  # Cluster
  # Boundaries](https://www.unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries)
  # ):
  #
  #     s = "ä-pqr-b̈-xyz-c̈"
  #     s.size                   # => 16
  #     s.bytesize               # => 19
  #     s.grapheme_clusters.size # => 13
  #     s.grapheme_clusters
  #     # => ["ä", "-", "p", "q", "r", "-", "b̈", "-", "x", "y", "z", "-", "c̈"]
  #
  # Details:
  #
  #     s = "ä"
  #     s.grapheme_clusters             # => ["ä"]           # One grapheme cluster.
  #     s.bytes                         # => [97, 204, 136]  # Three bytes.
  #     s.chars                         # => ["a", "̈"]       # Two characters.
  #     s.chars.map {|char| char.ord }  # => [97, 776]       # Their values.
  #
  # Related: see [Converting to
  # Non-String](rdoc-ref:String@Converting+to+Non--5CString).
  #
  def grapheme_clusters: () -> Array[String]
                       | () { (String grapheme_cluter) -> void } -> self

  # <!--
  #   rdoc-file=string.c
  #   - gsub(pattern, replacement)   -> new_string
  #   - gsub(pattern) {|match| ... } -> new_string
  #   - gsub(pattern)                -> enumerator
  # -->
  # Returns a copy of `self` with zero or more substrings replaced.
  #
  # Argument `pattern` may be a string or a Regexp; argument `replacement` may be
  # a string or a Hash. Varying types for the argument values makes this method
  # very versatile.
  #
  # Below are some simple examples; for many more examples, see [Substitution
  # Methods](rdoc-ref:String@Substitution+Methods).
  #
  # With arguments `pattern` and string `replacement` given, replaces each
  # matching substring with the given `replacement` string:
  #
  #     s = 'abracadabra'
  #     s.gsub('ab', 'AB')   # => "ABracadABra"
  #     s.gsub(/[a-c]/, 'X') # => "XXrXXXdXXrX"
  #
  # With arguments `pattern` and hash `replacement` given, replaces each matching
  # substring with a value from the given `replacement` hash, or removes it:
  #
  #     h = {'a' => 'A', 'b' => 'B', 'c' => 'C'}
  #     s.gsub(/[a-c]/, h) # => "ABrACAdABrA"  # 'a', 'b', 'c' replaced.
  #     s.gsub(/[a-d]/, h) # => "ABrACAABrA"   # 'd' removed.
  #
  # With argument `pattern` and a block given, calls the block with each matching
  # substring; replaces that substring with the block's return value:
  #
  #     s.gsub(/[a-d]/) {|substring| substring.upcase }
  #     # => "ABrACADABrA"
  #
  # With argument `pattern` and no block given, returns a new Enumerator.
  #
  # Related: see [Converting to New
  # String](rdoc-ref:String@Converting+to+New+String).
  #
  def gsub: (Regexp | string pattern, string | hash[String, _ToS] replacement) -> String
          | (Regexp | string pattern) -> Enumerator[String, String]
          | (Regexp | string pattern) { (String match) -> _ToS } -> String

  # <!--
  #   rdoc-file=string.c
  #   - gsub!(pattern, replacement)   -> self or nil
  #   - gsub!(pattern) {|match| ... } -> self or nil
  #   - gsub!(pattern)                -> an_enumerator
  # -->
  # Like String#gsub, except that:
  #
  # *   Performs substitutions in `self` (not in a copy of `self`).
  # *   Returns `self` if any characters are removed, `nil` otherwise.
  #
  # Related: see [Modifying](rdoc-ref:String@Modifying).
  #
  def gsub!: (Regexp | string pattern, string | hash[String, _ToS] replacement) -> self?
           | (Regexp | string pattern) -> Enumerator[String, self?]
           | (Regexp | string pattern) { (String match) -> _ToS } -> self?

  # <!--
  #   rdoc-file=string.c
  #   - hash -> integer
  # -->
  # Returns the integer hash value for `self`.
  #
  # Two String objects that have identical content and compatible encodings also
  # have the same hash value; see Object#hash and
  # [Encodings](rdoc-ref:encodings.rdoc):
  #
  #     s = 'foo'
  #     h = s.hash       # => -569050784
  #     h == 'foo'.hash  # => true
  #     h == 'food'.hash # => false
  #     h == 'FOO'.hash  # => false
  #
  #     s0 = "äöü"
  #     s1 = s0.encode(Encoding::ISO_8859_1)
  #     s0.encoding        # => #<Encoding:UTF-8>
  #     s1.encoding        # => #<Encoding:ISO-8859-1>
  #     s0.hash == s1.hash # => false
  #
  # Related: see [Querying](rdoc-ref:String@Querying).
  #
  def hash: () -> Integer

  # <!--
  #   rdoc-file=string.c
  #   - hex -> integer
  # -->
  # Interprets the leading substring of `self` as hexadecimal, possibly signed;
  # returns its value as an integer.
  #
  # The leading substring is interpreted as hexadecimal when it begins with:
  #
  # *   One or more character representing hexadecimal digits (each in one of the
  #     ranges `'0'..'9'`, `'a'..'f'`, or `'A'..'F'`); the string to be
  #     interpreted ends at the first character that does not represent a
  #     hexadecimal digit:
  #
  #         'f'.hex        # => 15
  #         '11'.hex       # => 17
  #         'FFF'.hex      # => 4095
  #         'fffg'.hex     # => 4095
  #         'foo'.hex      # => 15   # 'f' hexadecimal, 'oo' not.
  #         'bar'.hex      # => 186  # 'ba' hexadecimal, 'r' not.
  #         'deadbeef'.hex # => 3735928559
  #
  # *   `'0x'` or `'0X'`, followed by one or more hexadecimal digits:
  #
  #         '0xfff'.hex    # => 4095
  #         '0xfffg'.hex   # => 4095
  #
  # Any of the above may prefixed with `'-'`, which negates the interpreted value:
  #
  #     '-fff'.hex      # => -4095
  #     '-0xFFF'.hex    # => -4095
  #
  # For any substring not described above, returns zero:
  #
  #     'xxx'.hex     # => 0
  #     ''.hex        # => 0
  #
  # Note that, unlike #oct, this method interprets only hexadecimal, and not
  # binary, octal, or decimal notations:
  #
  #     '0b111'.hex   # => 45329
  #     '0o777'.hex   # => 0
  #     '0d999'.hex   # => 55705
  #
  # Related: See [Converting to
  # Non-String](rdoc-ref:String@Converting+to+Non--5CString).
  #
  def hex: () -> Integer

  # <!--
  #   rdoc-file=string.c
  #   - include?(other_string) -> true or false
  # -->
  # Returns whether `self` contains `other_string`:
  #
  #     s = 'bar'
  #     s.include?('ba')  # => true
  #     s.include?('ar')  # => true
  #     s.include?('bar') # => true
  #     s.include?('a')   # => true
  #     s.include?('')    # => true
  #     s.include?('foo') # => false
  #
  # Related: see [Querying](rdoc-ref:String@Querying).
  #
  def include?: (string other_string) -> bool

  # <!--
  #   rdoc-file=string.c
  #   - index(pattern, offset = 0) -> integer or nil
  # -->
  # Returns the integer position of the first substring that matches the given
  # argument `pattern`, or `nil` if none found.
  #
  # When `pattern` is a string, returns the index of the first matching substring
  # in `self`:
  #
  #     'foo'.index('f')         # => 0
  #     'foo'.index('o')         # => 1
  #     'foo'.index('oo')        # => 1
  #     'foo'.index('ooo')       # => nil
  #     'тест'.index('с')        # => 2  # Characters, not bytes.
  #     'こんにちは'.index('ち')  # => 3
  #
  # When `pattern` is a Regexp, returns the index of the first match in `self`:
  #
  #     'foo'.index(/o./) # => 1
  #     'foo'.index(/.o/) # => 0
  #
  # When `offset` is non-negative, begins the search at position `offset`; the
  # returned index is relative to the beginning of `self`:
  #
  #     'bar'.index('r', 0)        # => 2
  #     'bar'.index('r', 1)        # => 2
  #     'bar'.index('r', 2)        # => 2
  #     'bar'.index('r', 3)        # => nil
  #     'bar'.index(/[r-z]/, 0)    # => 2
  #     'тест'.index('с', 1)       # => 2
  #     'тест'.index('с', 2)       # => 2
  #     'тест'.index('с', 3)       # => nil  # Offset in characters, not bytes.
  #     'こんにちは'.index('ち', 2) # => 3
  #
  # With negative integer argument `offset`, selects the search position by
  # counting backward from the end of `self`:
  #
  #     'foo'.index('o', -1)  # => 2
  #     'foo'.index('o', -2)  # => 1
  #     'foo'.index('o', -3)  # => 1
  #     'foo'.index('o', -4)  # => nil
  #     'foo'.index(/o./, -2) # => 1
  #     'foo'.index(/.o/, -2) # => 1
  #
  # Related: see [Querying](rdoc-ref:String@Querying).
  #
  def index: (Regexp | string pattern, ?int offset) -> Integer?

  # <!--
  #   rdoc-file=string.c
  #   - insert(offset, other_string) -> self
  # -->
  # Inserts the given `other_string` into `self`; returns `self`.
  #
  # If the given `index` is non-negative, inserts `other_string` at offset
  # `index`:
  #
  #     'foo'.insert(0, 'bar')       # => "barfoo"
  #     'foo'.insert(1, 'bar')       # => "fbaroo"
  #     'foo'.insert(3, 'bar')       # => "foobar"
  #     'тест'.insert(2, 'bar')      # => "теbarст"  # Characters, not bytes.
  #     'こんにちは'.insert(2, 'bar') # => "こんbarにちは"
  #
  # If the `index` is negative, counts backward from the end of `self` and inserts
  # `other_string` *after* the offset:
  #
  #     'foo'.insert(-2, 'bar') # => "fobaro"
  #
  # Related: see [Modifying](rdoc-ref:String@Modifying).
  #
  def insert: (int index, string other_str) -> self

  # <!--
  #   rdoc-file=string.c
  #   - inspect -> string
  # -->
  # Returns a printable version of `self`, enclosed in double-quotes.
  #
  # Most printable characters are rendered simply as themselves:
  #
  #     'abc'.inspect        # => "\"abc\""
  #     '012'.inspect        # => "\"012\""
  #     ''.inspect           # => "\"\""
  #     "\u000012".inspect   # => "\"\\u000012\""
  #     'тест'.inspect       # => "\"тест\""
  #     'こんにちは'.inspect  # => "\"こんにちは\""
  #
  # But printable characters double-quote (`'"'`) and backslash and (`'\\'`) are
  # escaped:
  #
  #     '"'.inspect  # => "\"\\\"\""
  #     '\\'.inspect # => "\"\\\\\""
  #
  # Unprintable characters are the [ASCII
  # characters](https://en.wikipedia.org/wiki/ASCII) whose values are in range
  # `0..31`, along with the character whose value is `127`.
  #
  # Most of these characters are rendered thus:
  #
  #     0.chr.inspect # => "\"\\x00\""
  #     1.chr.inspect # => "\"\\x01\""
  #     2.chr.inspect # => "\"\\x02\""
  #     # ...
  #
  # A few, however, have special renderings:
  #
  #     7.chr.inspect  # => "\"\\a\""  # BEL
  #     8.chr.inspect  # => "\"\\b\""  # BS
  #     9.chr.inspect  # => "\"\\t\""  # TAB
  #     10.chr.inspect # => "\"\\n\""  # LF
  #     11.chr.inspect # => "\"\\v\""  # VT
  #     12.chr.inspect # => "\"\\f\""  # FF
  #     13.chr.inspect # => "\"\\r\""  # CR
  #     27.chr.inspect # => "\"\\e\""  # ESC
  #
  # Related: see [Converting to
  # Non-String](rdoc-ref:String@Converting+to+Non--5CString).
  #
  def inspect: () -> String

  # <!--
  #   rdoc-file=string.c
  #   - intern   -> symbol
  # -->
  # Returns the Symbol object derived from `self`, creating it if it did not
  # already exist:
  #
  #     'foo'.intern       # => :foo
  #     'тест'.intern      # => :тест
  #     'こんにちは'.intern # => :こんにちは
  #
  # Related: see [Converting to
  # Non-String](rdoc-ref:String@Converting+to+Non--5CString).
  #
  def intern: () -> Symbol

  # <!--
  #   rdoc-file=string.c
  #   - length -> integer
  # -->
  # Returns the count of characters (not bytes) in `self`:
  #
  #     'foo'.length        # => 3
  #     'тест'.length       # => 4
  #     'こんにちは'.length  # => 5
  #
  # Contrast with String#bytesize:
  #
  #     'foo'.bytesize        # => 3
  #     'тест'.bytesize       # => 8
  #     'こんにちは'.bytesize  # => 15
  #
  # Related: see [Querying](rdoc-ref:String@Querying).
  #
  def length: () -> Integer

  # <!--
  #   rdoc-file=string.c
  #   - lines(record_separator = $/, chomp: false) -> array_of_strings
  # -->
  # Returns substrings ("lines") of `self` according to the given arguments:
  #
  #     s = <<~EOT
  #     This is the first line.
  #     This is line two.
  #
  #     This is line four.
  #     This is line five.
  #     EOT
  #
  # With the default argument values:
  #
  #     $/ # => "\n"
  #     s.lines
  #     # =>
  #     ["This is the first line.\n",
  #      "This is line two.\n",
  #      "\n",
  #      "This is line four.\n",
  #      "This is line five.\n"]
  #
  # With a different `record_separator`:
  #
  #     record_separator = ' is '
  #     s.lines(record_separator)
  #     # =>
  #     ["This is ",
  #      "the first line.\nThis is ",
  #      "line two.\n\nThis is ",
  #      "line four.\nThis is ",
  #      "line five.\n"]
  #
  # With keyword argument `chomp` as `true`, removes the trailing newline from
  # each line:
  #
  #     s.lines(chomp: true)
  #     # =>
  #     ["This is the first line.",
  #      "This is line two.",
  #      "",
  #      "This is line four.",
  #      "This is line five."]
  #
  # Related: see [Converting to
  # Non-String](rdoc-ref:String@Converting+to+Non--5CString).
  #
  def lines: (?string? separator, ?chomp: boolish) -> Array[String]
           | (?string? separator, ?chomp: boolish) { (String line) -> void } -> self

  # <!--
  #   rdoc-file=string.c
  #   - ljust(width, pad_string = ' ') -> new_string
  # -->
  # Returns a copy of `self`, left-justified and, if necessary, right-padded with
  # the `pad_string`:
  #
  #     'hello'.ljust(10)       # => "hello     "
  #     '  hello'.ljust(10)     # => "  hello   "
  #     'hello'.ljust(10, 'ab') # => "helloababa"
  #     'тест'.ljust(10)        # => "тест      "
  #     'こんにちは'.ljust(10)   # => "こんにちは     "
  #
  # If `width <= self.length`, returns a copy of `self`:
  #
  #     'hello'.ljust(5)  # => "hello"
  #     'hello'.ljust(1)  # => "hello"  # Does not truncate to width.
  #
  # Related: see [Converting to New
  # String](rdoc-ref:String@Converting+to+New+String).
  #
  def ljust: (int size, ?string pad_string) -> String

  # <!--
  #   rdoc-file=string.c
  #   - lstrip(*selectors) -> new_string
  # -->
  # Returns a copy of `self` with leading whitespace removed; see [Whitespace in
  # Strings](rdoc-ref:String@Whitespace+in+Strings):
  #
  #     whitespace = "\x00\t\n\v\f\r "
  #     s = whitespace + 'abc' + whitespace
  #     # => "\u0000\t\n\v\f\r abc\u0000\t\n\v\f\r "
  #     s.lstrip
  #     # => "abc\u0000\t\n\v\f\r "
  #
  # If `selectors` are given, removes characters of `selectors` from the beginning
  # of `self`:
  #
  #     s = "---abc+++"
  #     s.lstrip("-") # => "abc+++"
  #
  # `selectors` must be valid character selectors (see [Character
  # Selectors](rdoc-ref:character_selectors.rdoc)), and may use any of its valid
  # forms, including negation, ranges, and escapes:
  #
  #     "01234abc56789".lstrip("0-9") # "abc56789"
  #     "01234abc56789".lstrip("0-9", "^4-6") # "4abc56789"
  #
  # Related: see [Converting to New
  # String](rdoc-ref:String@Converting+to+New+String).
  #
  def lstrip: () -> String

  # <!--
  #   rdoc-file=string.c
  #   - lstrip!(*selectors) -> self or nil
  # -->
  # Like String#lstrip, except that:
  #
  # *   Performs stripping in `self` (not in a copy of `self`).
  # *   Returns `self` if any characters are stripped, `nil` otherwise.
  #
  # Related: see [Modifying](rdoc-ref:String@Modifying).
  #
  def lstrip!: () -> self?

  # <!--
  #   rdoc-file=string.c
  #   - match(pattern, offset = 0) -> matchdata or nil
  #   - match(pattern, offset = 0) {|matchdata| ... } -> object
  # -->
  # Creates a MatchData object based on `self` and the given arguments; updates
  # [Regexp Global Variables](rdoc-ref:Regexp@Global+Variables).
  #
  # *   Computes `regexp` by converting `pattern` (if not already a Regexp).
  #
  #         regexp = Regexp.new(pattern)
  #
  # *   Computes `matchdata`, which will be either a MatchData object or `nil`
  #     (see Regexp#match):
  #
  #         matchdata = regexp.match(self[offset..])
  #
  # With no block given, returns the computed `matchdata` or `nil`:
  #
  #     'foo'.match('f')    # => #<MatchData "f">
  #     'foo'.match('o')    # => #<MatchData "o">
  #     'foo'.match('x')    # => nil
  #     'foo'.match('f', 1) # => nil
  #     'foo'.match('o', 1) # => #<MatchData "o">
  #
  # With a block given and computed `matchdata` non-nil, calls the block with
  # `matchdata`; returns the block's return value:
  #
  #     'foo'.match(/o/) {|matchdata| matchdata } # => #<MatchData "o">
  #
  # With a block given and `nil` `matchdata`, does not call the block:
  #
  #     'foo'.match(/x/) {|matchdata| fail 'Cannot happen' } # => nil
  #
  # Related: see [Querying](rdoc-ref:String@Querying).
  #
  def match: (Regexp | string pattern, ?int offset) -> MatchData?
           | [T] (Regexp | string pattern, ?int offset) { (MatchData matchdata) -> T } -> T?

  # <!--
  #   rdoc-file=string.c
  #   - match?(pattern, offset = 0) -> true or false
  # -->
  # Returns whether a match is found for `self` and the given arguments; does not
  # update [Regexp Global Variables](rdoc-ref:Regexp@Global+Variables).
  #
  # Computes `regexp` by converting `pattern` (if not already a Regexp):
  #
  #     regexp = Regexp.new(pattern)
  #
  # Returns `true` if `self[offset..].match(regexp)` returns a MatchData object,
  # `false` otherwise:
  #
  #     'foo'.match?(/o/) # => true
  #     'foo'.match?('o') # => true
  #     'foo'.match?(/x/) # => false
  #     'foo'.match?('f', 1) # => false
  #     'foo'.match?('o', 1) # => true
  #
  # Related: see [Querying](rdoc-ref:String@Querying).
  #
  def match?: (Regexp | string pattern, ?int offset) -> bool

  # <!-- rdoc-file=string.c -->
  # Returns the successor to `self`. The successor is calculated by incrementing
  # characters.
  #
  # The first character to be incremented is the rightmost alphanumeric: or, if no
  # alphanumerics, the rightmost character:
  #
  #     'THX1138'.succ   # => "THX1139"
  #     '<<koala>>'.succ # => "<<koalb>>"
  #     '***'.succ       # => '**+'
  #     'тест'.succ      # => "тесу"
  #     'こんにちは'.succ  # => "こんにちば"
  #
  # The successor to a digit is another digit, "carrying" to the next-left
  # character for a "rollover" from 9 to 0, and prepending another digit if
  # necessary:
  #
  #     '00'.succ # => "01"
  #     '09'.succ # => "10"
  #     '99'.succ # => "100"
  #
  # The successor to a letter is another letter of the same case, carrying to the
  # next-left character for a rollover, and prepending another same-case letter if
  # necessary:
  #
  #     'aa'.succ # => "ab"
  #     'az'.succ # => "ba"
  #     'zz'.succ # => "aaa"
  #     'AA'.succ # => "AB"
  #     'AZ'.succ # => "BA"
  #     'ZZ'.succ # => "AAA"
  #
  # The successor to a non-alphanumeric character is the next character in the
  # underlying character set's collating sequence, carrying to the next-left
  # character for a rollover, and prepending another character if necessary:
  #
  #     s = 0.chr * 3   # => "\x00\x00\x00"
  #     s.succ        # => "\x00\x00\x01"
  #     s = 255.chr * 3 # => "\xFF\xFF\xFF"
  #     s.succ        # => "\x01\x00\x00\x00"
  #
  # Carrying can occur between and among mixtures of alphanumeric characters:
  #
  #     s = 'zz99zz99' # => "zz99zz99"
  #     s.succ         # => "aaa00aa00"
  #     s = '99zz99zz' # => "99zz99zz"
  #     s.succ         # => "100aa00aa"
  #
  # The successor to an empty `String` is a new empty `String`:
  #
  #     ''.succ # => ""
  #
  # Related: see [Converting to New
  # String](rdoc-ref:String@Converting+to+New+String).
  #
  alias next succ

  # <!-- rdoc-file=string.c -->
  # Like String#succ, but modifies `self` in place; returns `self`.
  #
  # Related: see [Modifying](rdoc-ref:String@Modifying).
  #
  alias next! succ!

  # <!--
  #   rdoc-file=string.c
  #   - oct -> integer
  # -->
  # Interprets the leading substring of `self` as octal, binary, decimal, or
  # hexadecimal, possibly signed; returns their value as an integer.
  #
  # In brief:
  #
  #     # Interpreted as octal.
  #     '777'.oct   # => 511
  #     '777x'.oct  # => 511
  #     '0777'.oct  # => 511
  #     '0o777'.oct # => 511
  #     '-777'.oct  # => -511
  #     # Not interpreted as octal.
  #     '0b111'.oct # => 7     # Interpreted as binary.
  #     '0d999'.oct # => 999   # Interpreted as decimal.
  #     '0xfff'.oct # => 4095  # Interpreted as hexadecimal.
  #
  # The leading substring is interpreted as octal when it begins with:
  #
  # *   One or more character  representing octal digits (each in the range
  #     `'0'..'7'`); the string to be interpreted ends at the first character that
  #     does not represent an octal digit:
  #
  #         '7'.oct      @ => 7
  #         '11'.oct     # => 9
  #         '777'.oct    # => 511
  #         '0777'.oct   # => 511
  #         '7778'.oct   # => 511
  #         '777x'.oct   # => 511
  #
  # *   `'0o'`, followed by one or more octal digits:
  #
  #         '0o777'.oct  # => 511
  #         '0o7778'.oct # => 511
  #
  # The leading substring is *not* interpreted as octal when it begins with:
  #
  # *   `'0b'`, followed by one or more characters representing binary digits
  #     (each in the range `'0'..'1'`); the string to be interpreted ends at the
  #     first character that does not represent a binary digit. the string is
  #     interpreted as binary digits (base 2):
  #
  #         '0b111'.oct  # => 7
  #         '0b1112'.oct # => 7
  #
  # *   `'0d'`, followed by one or more characters representing decimal digits
  #     (each in the range `'0'..'9'`); the string to be interpreted ends at the
  #     first character that does not represent a decimal digit. the string is
  #     interpreted as decimal digits (base 10):
  #
  #         '0d999'.oct  # => 999
  #         '0d999x'.oct # => 999
  #
  # *   `'0x'`, followed by one or more characters representing hexadecimal digits
  #     (each in one of the ranges `'0'..'9'`, `'a'..'f'`, or `'A'..'F'`); the
  #     string to be interpreted ends at the first character that does not
  #     represent a hexadecimal digit. the string is interpreted as hexadecimal
  #     digits (base 16):
  #
  #         '0xfff'.oct  # => 4095
  #         '0xfffg'.oct # => 4095
  #
  # Any of the above may prefixed with `'-'`, which negates the interpreted value:
  #
  #     '-777'.oct   # => -511
  #     '-0777'.oct  # => -511
  #     '-0b111'.oct # => -7
  #     '-0xfff'.oct # => -4095
  #
  # For any substring not described above, returns zero:
  #
  #     'foo'.oct      # => 0
  #     ''.oct         # => 0
  #
  # Related: see [Converting to
  # Non-String](rdoc-ref:String@Converting+to+Non--5CString).
  #
  def oct: () -> Integer

  # <!--
  #   rdoc-file=string.c
  #   - ord -> integer
  # -->
  # Returns the integer ordinal of the first character of `self`:
  #
  #     'h'.ord         # => 104
  #     'hello'.ord     # => 104
  #     'тест'.ord      # => 1090
  #     'こんにちは'.ord  # => 12371
  #
  # Related: see [Converting to
  # Non-String](rdoc-ref:String@Converting+to+Non--5CString).
  #
  def ord: () -> Integer

  # <!--
  #   rdoc-file=string.c
  #   - partition(pattern) -> [pre_match, first_match, post_match]
  # -->
  # Returns a 3-element array of substrings of `self`.
  #
  # If `pattern` is matched, returns the array:
  #
  #     [pre_match, first_match, post_match]
  #
  # where:
  #
  # *   `first_match` is the first-found matching substring.
  # *   `pre_match` and `post_match` are the preceding and following substrings.
  #
  # If `pattern` is not matched, returns the array:
  #
  #     [self.dup, "", ""]
  #
  # Note that in the examples below, a returned string `'hello'` is a copy of
  # `self`, not `self`.
  #
  # If `pattern` is a Regexp, performs the equivalent of `self.match(pattern)`
  # (also setting [pattern-matching global
  # variables](rdoc-ref:language/globals.md@Pattern+Matching)):
  #
  #     'hello'.partition(/h/)  # => ["", "h", "ello"]
  #     'hello'.partition(/l/)  # => ["he", "l", "lo"]
  #     'hello'.partition(/l+/) # => ["he", "ll", "o"]
  #     'hello'.partition(/o/)  # => ["hell", "o", ""]
  #     'hello'.partition(/^/)  # => ["", "", "hello"]
  #     'hello'.partition(//)   # => ["", "", "hello"]
  #     'hello'.partition(/$/)  # => ["hello", "", ""]
  #     'hello'.partition(/x/)  # => ["hello", "", ""]
  #
  # If `pattern` is not a Regexp, converts it to a string (if it is not already
  # one), then performs the equivalent of `self.index(pattern)` (and does *not*
  # set [pattern-matching global
  # variables](rdoc-ref:language/globals.md@Pattern+Matching)):
  #
  #     'hello'.partition('h')     # => ["", "h", "ello"]
  #     'hello'.partition('l')     # => ["he", "l", "lo"]
  #     'hello'.partition('ll')    # => ["he", "ll", "o"]
  #     'hello'.partition('o')     # => ["hell", "o", ""]
  #     'hello'.partition('')      # => ["", "", "hello"]
  #     'hello'.partition('x')     # => ["hello", "", ""]
  #     'тест'.partition('т')      # => ["", "т", "ест"]
  #     'こんにちは'.partition('に') # => ["こん", "に", "ちは"]
  #
  # Related: see [Converting to
  # Non-String](rdoc-ref:String@Converting+to+Non--5CString).
  #
  def partition: (Regexp | string pattern) -> [String, String, String]

  # <!--
  #   rdoc-file=string.c
  #   - prepend(*other_strings) -> new_string
  # -->
  # Prefixes to `self` the concatenation of the given `other_strings`; returns
  # `self`:
  #
  #     'baz'.prepend('foo', 'bar') # => "foobarbaz"
  #
  # Related: see [Modifying](rdoc-ref:String@Modifying).
  #
  def prepend: (*string other_strings) -> self

  # <!--
  #   rdoc-file=string.c
  #   - replace(other_string) -> self
  # -->
  # Replaces the contents of `self` with the contents of `other_string`; returns
  # `self`:
  #
  #     s = 'foo'        # => "foo"
  #     s.replace('bar') # => "bar"
  #
  # Related: see [Modifying](rdoc-ref:String@Modifying).
  #
  def replace: (string other_string) -> self

  # <!--
  #   rdoc-file=string.c
  #   - reverse -> new_string
  # -->
  # Returns a new string with the characters from `self` in reverse order.
  #
  #     'drawer'.reverse       # => "reward"
  #     'reviled'.reverse      # => "deliver"
  #     'stressed'.reverse     # => "desserts"
  #     'semordnilaps'.reverse # => "spalindromes"
  #
  # Related: see [Converting to New
  # String](rdoc-ref:String@Converting+to+New+String).
  #
  def reverse: () -> String

  # <!--
  #   rdoc-file=string.c
  #   - reverse! -> self
  # -->
  # Returns `self` with its characters reversed:
  #
  #     'drawer'.reverse!       # => "reward"
  #     'reviled'.reverse!      # => "deliver"
  #     'stressed'.reverse!     # => "desserts"
  #     'semordnilaps'.reverse! # => "spalindromes"
  #
  # Related: see [Modifying](rdoc-ref:String@Modifying).
  #
  def reverse!: () -> self

  # <!--
  #   rdoc-file=string.c
  #   - rindex(pattern, offset = self.length) -> integer or nil
  # -->
  # Returns the integer position of the *last* substring that matches the given
  # argument `pattern`, or `nil` if none found.
  #
  # When `pattern` is a string, returns the index of the last matching substring
  # in self:
  #
  #     'foo'.rindex('f')       # => 0
  #     'foo'.rindex('o')       # => 2
  #     'foo'.rindex('oo'       # => 1
  #     'foo'.rindex('ooo')     # => nil
  #     'тест'.rindex('т')      # => 3
  #     'こんにちは'.rindex('ち') # => 3
  #
  # When `pattern` is a Regexp, returns the index of the last match in self:
  #
  #     'foo'.rindex(/f/)   # => 0
  #     'foo'.rindex(/o/)   # => 2
  #     'foo'.rindex(/oo/)  # => 1
  #     'foo'.rindex(/ooo/) # => nil
  #
  # When `offset` is non-negative, it specifies the maximum starting position in
  # the string to end the search:
  #
  #     'foo'.rindex('o', 0) # => nil
  #     'foo'.rindex('o', 1) # => 1
  #     'foo'.rindex('o', 2) # => 2
  #     'foo'.rindex('o', 3) # => 2
  #
  # With negative integer argument `offset`, selects the search position by
  # counting backward from the end of `self`:
  #
  #     'foo'.rindex('o', -1) # => 2
  #     'foo'.rindex('o', -2) # => 1
  #     'foo'.rindex('o', -3) # => nil
  #     'foo'.rindex('o', -4) # => nil
  #
  # The last match means starting at the possible last position, not the last of
  # longest matches:
  #
  #     'foo'.rindex(/o+/) # => 2
  #     $~                 # => #<MatchData "o">
  #
  # To get the last longest match, combine with negative lookbehind:
  #
  #     'foo'.rindex(/(?<!o)o+/) # => 1
  #     $~                       # => #<MatchData "oo">
  #
  # Or String#index with negative lookforward.
  #
  #     'foo'.index(/o+(?!.*o)/) # => 1
  #     $~                       # => #<MatchData "oo">
  #
  # Related: see [Querying](rdoc-ref:String@Querying).
  #
  def rindex: (Regexp | string pattern, ?int offset) -> Integer?

  # <!--
  #   rdoc-file=string.c
  #   - rjust(width, pad_string = ' ') -> new_string
  # -->
  # Returns a right-justified copy of `self`.
  #
  # If integer argument `width` is greater than the size (in characters) of
  # `self`, returns a new string of length `width` that is a copy of `self`, right
  # justified and padded on the left with `pad_string`:
  #
  #     'hello'.rjust(10)       # => "     hello"
  #     'hello  '.rjust(10)     # => "   hello  "
  #     'hello'.rjust(10, 'ab') # => "ababahello"
  #     'тест'.rjust(10)        # => "      тест"
  #     'こんにちは'.rjust(10)    # => "     こんにちは"
  #
  # If `width <= self.size`, returns a copy of `self`:
  #
  #     'hello'.rjust(5, 'ab')  # => "hello"
  #     'hello'.rjust(1, 'ab')  # => "hello"
  #
  # Related: see [Converting to New
  # String](rdoc-ref:String@Converting+to+New+String).
  #
  def rjust: (int size, ?string pad_string) -> String

  # <!--
  #   rdoc-file=string.c
  #   - rpartition(pattern) -> [pre_match, last_match, post_match]
  # -->
  # Returns a 3-element array of substrings of `self`.
  #
  # Searches `self` for a match of `pattern`, seeking the *last* match.
  #
  # If `pattern` is not matched, returns the array:
  #
  #     ["", "", self.dup]
  #
  # If `pattern` is matched, returns the array:
  #
  #     [pre_match, last_match, post_match]
  #
  # where:
  #
  # *   `last_match` is the last-found matching substring.
  # *   `pre_match` and `post_match` are the preceding and following substrings.
  #
  # The pattern used is:
  #
  # *   `pattern` itself, if it is a Regexp.
  # *   `Regexp.quote(pattern)`, if `pattern` is a string.
  #
  # Note that in the examples below, a returned string `'hello'` is a copy of
  # `self`, not `self`.
  #
  # If `pattern` is a Regexp, searches for the last matching substring (also
  # setting [pattern-matching global
  # variables](rdoc-ref:language/globals.md@Pattern+Matching)):
  #
  #     'hello'.rpartition(/l/)     # => ["hel", "l", "o"]
  #     'hello'.rpartition(/ll/)    # => ["he", "ll", "o"]
  #     'hello'.rpartition(/h/)     # => ["", "h", "ello"]
  #     'hello'.rpartition(/o/)     # => ["hell", "o", ""]
  #     'hello'.rpartition(//)      # => ["hello", "", ""]
  #     'hello'.rpartition(/x/)     # => ["", "", "hello"]
  #     'тест'.rpartition(/т/)      # => ["тес", "т", ""]
  #     'こんにちは'.rpartition(/に/) # => ["こん", "に", "ちは"]
  #
  # If `pattern` is not a Regexp, converts it to a string (if it is not already
  # one), then searches for the last matching substring (and does *not* set
  # [pattern-matching global
  # variables](rdoc-ref:language/globals.md@Pattern+Matching)):
  #
  #     'hello'.rpartition('l')     # => ["hel", "l", "o"]
  #     'hello'.rpartition('ll')    # => ["he", "ll", "o"]
  #     'hello'.rpartition('h')     # => ["", "h", "ello"]
  #     'hello'.rpartition('o')     # => ["hell", "o", ""]
  #     'hello'.rpartition('')      # => ["hello", "", ""]
  #     'тест'.rpartition('т')      # => ["тес", "т", ""]
  #     'こんにちは'.rpartition('に') # => ["こん", "に", "ちは"]
  #
  # Related: see [Converting to
  # Non-String](rdoc-ref:String@Converting+to+Non--5CString).
  #
  def rpartition: (Regexp | string pattern) -> [String, String, String]

  # <!--
  #   rdoc-file=string.c
  #   - rstrip(*selectors) -> new_string
  # -->
  # Returns a copy of `self` with trailing whitespace removed; see [Whitespace in
  # Strings](rdoc-ref:String@Whitespace+in+Strings):
  #
  #     whitespace = "\x00\t\n\v\f\r "
  #     s = whitespace + 'abc' + whitespace
  #     s        # => "\u0000\t\n\v\f\r abc\u0000\t\n\v\f\r "
  #     s.rstrip # => "\u0000\t\n\v\f\r abc"
  #
  # If `selectors` are given, removes characters of `selectors` from the end of
  # `self`:
  #
  #     s = "---abc+++"
  #     s.rstrip("+") # => "---abc"
  #
  # `selectors` must be valid character selectors (see [Character
  # Selectors](rdoc-ref:character_selectors.rdoc)), and may use any of its valid
  # forms, including negation, ranges, and escapes:
  #
  #     "01234abc56789".rstrip("0-9") # "01234abc"
  #     "01234abc56789".rstrip("0-9", "^4-6") # "01234abc56"
  #
  # Related: see [Converting to New
  # String](rdoc-ref:String@Converting+to+New+String).
  #
  def rstrip: () -> String

  # <!--
  #   rdoc-file=string.c
  #   - rstrip!(*selectors) -> self or nil
  # -->
  # Like String#rstrip, except that:
  #
  # *   Performs stripping in `self` (not in a copy of `self`).
  # *   Returns `self` if any characters are stripped, `nil` otherwise.
  #
  # Related: see [Modifying](rdoc-ref:String@Modifying).
  #
  def rstrip!: () -> self?

  # <!--
  #   rdoc-file=string.c
  #   - scan(pattern) -> array_of_results
  #   - scan(pattern) {|result| ... } -> self
  # -->
  # Matches a pattern against `self`:
  #
  # *   If `pattern` is a Regexp, the pattern used is `pattern` itself.
  # *   If `pattern` is a string, the pattern used is `Regexp.quote(pattern)`.
  #
  # Generates a collection of matching results and updates [regexp-related global
  # variables](rdoc-ref:Regexp@Global+Variables):
  #
  # *   If the pattern contains no groups, each result is a matched substring.
  # *   If the pattern contains groups, each result is an array containing a
  #     matched substring for each group.
  #
  # With no block given, returns an array of the results:
  #
  #     'cruel world'.scan(/\w+/)      # => ["cruel", "world"]
  #     'cruel world'.scan(/.../)      # => ["cru", "el ", "wor"]
  #     'cruel world'.scan(/(...)/)    # => [["cru"], ["el "], ["wor"]]
  #     'cruel world'.scan(/(..)(..)/) # => [["cr", "ue"], ["l ", "wo"]]
  #     'тест'.scan(/../)              # => ["те", "ст"]
  #     'こんにちは'.scan(/../)         # => ["こん", "にち"]
  #     'abracadabra'.scan('ab')       # => ["ab", "ab"]
  #     'abracadabra'.scan('nosuch')   # => []
  #
  # With a block given, calls the block with each result; returns `self`:
  #
  #     'cruel world'.scan(/\w+/) {|w| p w }
  #     # => "cruel"
  #     # => "world"
  #     'cruel world'.scan(/(.)(.)/) {|x, y| p [x, y] }
  #     # => ["c", "r"]
  #     # => ["u", "e"]
  #     # => ["l", " "]
  #     # => ["w", "o"]
  #     # => ["r", "l"]
  #
  # Related: see [Converting to
  # Non-String](rdoc-ref:String@Converting+to+Non--5CString).
  #
  def scan: (Regexp pattern) -> Array[String | Array[String?]]
          | (Regexp pattern) { (String | Array[String?] matches) -> void } -> self
          | (string pattern) -> Array[String]
          | (string pattern) { (String match) -> void } -> self

  # <!--
  #   rdoc-file=string.c
  #   - scrub(replacement_string = default_replacement_string) -> new_string
  #   - scrub{|sequence| ... } -> new_string
  # -->
  # Returns a copy of `self` with each invalid byte sequence replaced by the given
  # `replacement_string`.
  #
  # With no block given, replaces each invalid sequence with the given
  # `default_replacement_string` (by default, `"�"` for a Unicode encoding, `'?'`
  # otherwise):
  #
  #     "foo\x81\x81bar"scrub                             # => "foo��bar"
  #     "foo\x81\x81bar".force_encoding('US-ASCII').scrub # => "foo??bar"
  #     "foo\x81\x81bar".scrub('xyzzy')                   # => "fooxyzzyxyzzybar"
  #
  # With a block given, calls the block with each invalid sequence, and replaces
  # that sequence with the return value of the block:
  #
  #     "foo\x81\x81bar".scrub {|sequence| p sequence; 'XYZZY' } # => "fooXYZZYXYZZYbar"
  #
  # Output :
  #
  #     "\x81"
  #     "\x81"
  #
  # Related: see [Converting to New
  # String](rdoc-ref:String@Converting+to+New+String).
  #
  def scrub: (?string? replacement) -> String
           | (?nil) { (String bytes) -> string } -> String

  # <!--
  #   rdoc-file=string.c
  #   - scrub!(replacement_string = default_replacement_string) -> self
  #   - scrub!{|sequence| ... } -> self
  # -->
  # Like String#scrub, except that:
  #
  # *   Any replacements are made in `self`.
  # *   Returns `self`.
  #
  # Related: see [Modifying](rdoc-ref:String@Modifying).
  #
  def scrub!: (?string? replacement) -> self
            | (?nil) { (String bytes) -> string } -> self

  # <!--
  #   rdoc-file=string.c
  #   - setbyte(index, integer) -> integer
  # -->
  # Sets the byte at zero-based offset `index` to the value of the given
  # `integer`; returns `integer`:
  #
  #     s = 'xyzzy'
  #     s.setbyte(2, 129) # => 129
  #     s                 # => "xy\x81zy"
  #
  # Related: see [Modifying](rdoc-ref:String@Modifying).
  #
  def setbyte: [T < _ToInt] (int index, T byte) -> T

  # <!-- rdoc-file=string.c -->
  # Returns the count of characters (not bytes) in `self`:
  #
  #     'foo'.length        # => 3
  #     'тест'.length       # => 4
  #     'こんにちは'.length  # => 5
  #
  # Contrast with String#bytesize:
  #
  #     'foo'.bytesize        # => 3
  #     'тест'.bytesize       # => 8
  #     'こんにちは'.bytesize  # => 15
  #
  # Related: see [Querying](rdoc-ref:String@Querying).
  #
  alias size length

  # <!-- rdoc-file=string.c -->
  # Returns the substring of `self` specified by the arguments.
  #
  # **Form `self[index]`**
  #
  # With non-negative integer argument `index` given, returns the 1-character
  # substring found in self at character offset index:
  #
  #     'hello'[0]    # => "h"
  #     'hello'[4]    # => "o"
  #     'hello'[5]    # => nil
  #     'Привет'[2]   # => "и"
  #     'こんにちは'[4] # => "は"
  #
  # With negative integer argument `index` given, counts backward from the end of
  # `self`:
  #
  #     'hello'[-1] # => "o"
  #     'hello'[-5] # => "h"
  #     'hello'[-6] # => nil
  #
  # **Form `self[start, length]`**
  #
  # With integer arguments `start` and `length` given, returns a substring of size
  # `length` characters (as available) beginning at character offset specified by
  # `start`.
  #
  # If argument `start` is non-negative, the offset is `start`:
  #
  #     'hello'[0, 1]  # => "h"
  #     'hello'[0, 5]  # => "hello"
  #     'hello'[0, 6]  # => "hello"
  #     'hello'[2, 3]  # => "llo"
  #     'hello'[2, 0]  # => ""
  #     'hello'[2, -1] # => nil
  #
  # If argument `start` is negative, counts backward from the end of `self`:
  #
  #     'hello'[-1, 1] # => "o"
  #     'hello'[-5, 5] # => "hello"
  #     'hello'[-1, 0] # => ""
  #     'hello'[-6, 5] # => nil
  #
  # Special case: if `start` equals the length of `self`, returns a new empty
  # string:
  #
  #     'hello'[5, 3]  # => ""
  #
  # **Form `self[range]`**
  #
  # With Range argument `range` given, forms substring `self[range.start,
  # range.size]`:
  #
  #     'hello'[0..2]  # => "hel"
  #     'hello'[0, 3]  # => "hel"
  #
  #     'hello'[0...2] # => "he"
  #     'hello'[0, 2]  # => "he"
  #
  #     'hello'[0, 0]  # => ""
  #     'hello'[0...0] # => ""
  #
  # **Form `self[regexp, capture = 0]`**
  #
  # With Regexp argument `regexp` given and `capture` as zero, searches for a
  # matching substring in `self`; updates [Regexp-related global
  # variables](rdoc-ref:Regexp@Global+Variables):
  #
  #     'hello'[/ell/]     # => "ell"
  #     'hello'[/l+/]      # => "ll"
  #     'hello'[//]        # => ""
  #     'hello'[/nosuch/]  # => nil
  #
  # With `capture` as a positive integer `n`, returns the +n+th matched group:
  #
  #     'hello'[/(h)(e)(l+)(o)/]    # => "hello"
  #     'hello'[/(h)(e)(l+)(o)/, 1] # => "h"
  #     $1                          # => "h"
  #     'hello'[/(h)(e)(l+)(o)/, 2] # => "e"
  #     $2                          # => "e"
  #     'hello'[/(h)(e)(l+)(o)/, 3] # => "ll"
  #     'hello'[/(h)(e)(l+)(o)/, 4] # => "o"
  #     'hello'[/(h)(e)(l+)(o)/, 5] # => nil
  #
  # **Form `self[substring]`**
  #
  # With string argument `substring` given, returns the matching substring of
  # `self`, if found:
  #
  #     'hello'['ell']      # => "ell"
  #     'hello'['']         # => ""
  #     'hello'['nosuch']   # => nil
  #     'Привет'['ив']      # => "ив"
  #     'こんにちは'['んにち'] # => "んにち"
  #
  # Related: see [Converting to New
  # String](rdoc-ref:String@Converting+to+New+String).
  #
  alias slice []

  # <!--
  #   rdoc-file=string.c
  #   - slice!(index)               -> new_string or nil
  #   - slice!(start, length)       -> new_string or nil
  #   - slice!(range)               -> new_string or nil
  #   - slice!(regexp, capture = 0) -> new_string or nil
  #   - slice!(substring)           -> new_string or nil
  # -->
  # Like String#[] (and its alias String#slice), except that:
  #
  # *   Performs substitutions in `self` (not in a copy of `self`).
  # *   Returns the removed substring if any modifications were made, `nil`
  #     otherwise.
  #
  # A few examples:
  #
  #     s = 'hello'
  #     s.slice!('e') # => "e"
  #     s             # => "hllo"
  #     s.slice!('e') # => nil
  #     s             # => "hllo"
  #
  # Related: see [Modifying](rdoc-ref:String@Modifying).
  #
  def slice!: (int index, ?int length) -> String?
            | (range[int?] range) -> String?
            | (String substring) -> String?
            | (Regexp regexp, ?MatchData::capture backref) -> String?

  # <!--
  #   rdoc-file=string.c
  #   - split(field_sep = $;, limit = 0) -> array_of_substrings
  #   - split(field_sep = $;, limit = 0) {|substring| ... } -> self
  # -->
  # Creates an array of substrings by splitting `self` at each occurrence of the
  # given field separator `field_sep`.
  #
  # With no arguments given, splits using the field separator `$;`, whose default
  # value is `nil`.
  #
  # With no block given, returns the array of substrings:
  #
  #     'abracadabra'.split('a') # => ["", "br", "c", "d", "br"]
  #
  # When `field_sep` is `nil` or `' '` (a single space), splits at each sequence
  # of whitespace:
  #
  #     'foo bar baz'.split(nil)          # => ["foo", "bar", "baz"]
  #     'foo bar baz'.split(' ')          # => ["foo", "bar", "baz"]
  #     "foo \n\tbar\t\n  baz".split(' ') # => ["foo", "bar", "baz"]
  #     'foo  bar   baz'.split(' ')       # => ["foo", "bar", "baz"]
  #     ''.split(' ')                     # => []
  #
  # When `field_sep` is an empty string, splits at every character:
  #
  #     'abracadabra'.split('') # => ["a", "b", "r", "a", "c", "a", "d", "a", "b", "r", "a"]
  #     ''.split('')            # => []
  #     'тест'.split('')        # => ["т", "е", "с", "т"]
  #     'こんにちは'.split('')   # => ["こ", "ん", "に", "ち", "は"]
  #
  # When `field_sep` is a non-empty string and different from `' '` (a single
  # space), uses that string as the separator:
  #
  #     'abracadabra'.split('a')  # => ["", "br", "c", "d", "br"]
  #     'abracadabra'.split('ab') # => ["", "racad", "ra"]
  #     ''.split('a')             # => []
  #     'тест'.split('т')         # => ["", "ес"]
  #     'こんにちは'.split('に')    # => ["こん", "ちは"]
  #
  # When `field_sep` is a Regexp, splits at each occurrence of a matching
  # substring:
  #
  #     'abracadabra'.split(/ab/) # => ["", "racad", "ra"]
  #     '1 + 1 == 2'.split(/\W+/) # => ["1", "1", "2"]
  #     'abracadabra'.split(//)   # => ["a", "b", "r", "a", "c", "a", "d", "a", "b", "r", "a"]
  #
  # If the Regexp contains groups, their matches are included in the returned
  # array:
  #
  #     '1:2:3'.split(/(:)()()/, 2) # => ["1", ":", "", "", "2:3"]
  #
  # Argument `limit` sets a limit on the size of the returned array; it also
  # determines whether trailing empty strings are included in the returned array.
  #
  # When `limit` is zero, there is no limit on the size of the array, but trailing
  # empty strings are omitted:
  #
  #     'abracadabra'.split('', 0)  # => ["a", "b", "r", "a", "c", "a", "d", "a", "b", "r", "a"]
  #     'abracadabra'.split('a', 0) # => ["", "br", "c", "d", "br"]  # Empty string after last 'a' omitted.
  #
  # When `limit` is a positive integer, there is a limit on the size of the array
  # (no more than `n - 1` splits occur), and trailing empty strings are included:
  #
  #     'abracadabra'.split('', 3)   # => ["a", "b", "racadabra"]
  #     'abracadabra'.split('a', 3)  # => ["", "br", "cadabra"]
  #     'abracadabra'.split('', 30)  # => ["a", "b", "r", "a", "c", "a", "d", "a", "b", "r", "a", ""]
  #     'abracadabra'.split('a', 30) # => ["", "br", "c", "d", "br", ""]
  #     'abracadabra'.split('', 1)   # => ["abracadabra"]
  #     'abracadabra'.split('a', 1)  # => ["abracadabra"]
  #
  # When `limit` is negative, there is no limit on the size of the array, and
  # trailing empty strings are omitted:
  #
  #     'abracadabra'.split('', -1)  # => ["a", "b", "r", "a", "c", "a", "d", "a", "b", "r", "a", ""]
  #     'abracadabra'.split('a', -1) # => ["", "br", "c", "d", "br", ""]
  #
  # If a block is given, it is called with each substring and returns `self`:
  #
  #     'foo bar baz'.split(' ') {|substring| p substring }
  #
  # Output :
  #
  #     "foo"
  #     "bar"
  #     "baz"
  #
  # Note that the above example is functionally equivalent to:
  #
  #     'foo bar baz'.split(' ').each {|substring| p substring }
  #
  # Output :
  #
  #     "foo"
  #     "bar"
  #     "baz"
  #
  # But the latter:
  #
  # *   Has poorer performance because it creates an intermediate array.
  # *   Returns an array (instead of `self`).
  #
  # Related: see [Converting to
  # Non-String](rdoc-ref:String@Converting+to+Non--5CString).
  #
  def split: (?Regexp | string | nil pattern, ?int limit) -> Array[String]
           | (?Regexp | string | nil pattern, ?int limit) { (String substring) -> void } -> self

  # <!--
  #   rdoc-file=string.c
  #   - squeeze(*selectors) -> new_string
  # -->
  # Returns a copy of `self` with each tuple (doubling, tripling, etc.) of
  # specified characters "squeezed" down to a single character.
  #
  # The tuples to be squeezed are specified by arguments `selectors`, each of
  # which is a string; see [Character
  # Selectors](rdoc-ref:character_selectors.rdoc@Character+Selectors).
  #
  # A single argument may be a single character:
  #
  #     'Noooooo!'.squeeze('o')      # => "No!"
  #     'foo  bar  baz'.squeeze(' ') # => "foo bar baz"
  #     'Mississippi'.squeeze('s')   # => "Misisippi"
  #     'Mississippi'.squeeze('p')   # => "Mississipi"
  #     'Mississippi'.squeeze('x')   # => "Mississippi"  # Unused selector character is ignored.
  #     'бессонница'.squeeze('с')    # => "бесонница"
  #     'бессонница'.squeeze('н')    # => "бессоница"
  #
  # A single argument may be a string of characters:
  #
  #     'Mississippi'.squeeze('sp')       # => "Misisipi"
  #     'Mississippi'.squeeze('ps')       # => "Misisipi"   # Order doesn't matter.
  #     'Mississippi'.squeeze('nonsense') # => "Misisippi"  # Unused selector characters are ignored.
  #
  # A single argument may be a range of characters:
  #
  #     'Mississippi'.squeeze('a-p') # => "Mississipi"
  #     'Mississippi'.squeeze('q-z') # => "Misisippi"
  #     'Mississippi'.squeeze('a-z') # => "Misisipi"
  #
  # Multiple arguments are allowed; see [Multiple Character
  # Selectors](rdoc-ref:character_selectors.rdoc@Multiple+Character+Selectors).
  #
  # Related: see [Converting to New
  # String](rdoc-ref:String@Converting+to+New+String).
  #
  def squeeze: (*selector selectors) -> String

  # <!--
  #   rdoc-file=string.c
  #   - squeeze!(*selectors) -> self or nil
  # -->
  # Like String#squeeze, except that:
  #
  # *   Characters are squeezed in `self` (not in a copy of `self`).
  # *   Returns `self` if any changes are made, `nil` otherwise.
  #
  # Related: See [Modifying](rdoc-ref:String@Modifying).
  #
  def squeeze!: (*selector selectors) -> self?

  # <!--
  #   rdoc-file=string.c
  #   - start_with?(*patterns) -> true or false
  # -->
  # Returns whether `self` starts with any of the given `patterns`.
  #
  # For each argument, the pattern used is:
  #
  # *   The pattern itself, if it is a Regexp.
  # *   `Regexp.quote(pattern)`, if it is a string.
  #
  # Returns `true` if any pattern matches the beginning, `false` otherwise:
  #
  #     'hello'.start_with?('hell')               # => true
  #     'hello'.start_with?(/H/i)                 # => true
  #     'hello'.start_with?('heaven', 'hell')     # => true
  #     'hello'.start_with?('heaven', 'paradise') # => false
  #     'тест'.start_with?('т')                   # => true
  #     'こんにちは'.start_with?('こ')              # => true
  #
  # Related: see [Querying](rdoc-ref:String@Querying).
  #
  def start_with?: (*Regexp | string prefixes) -> bool

  # <!--
  #   rdoc-file=string.c
  #   - strip(*selectors) -> new_string
  # -->
  # Returns a copy of `self` with leading and trailing whitespace removed; see
  # [Whitespace in Strings](rdoc-ref:String@Whitespace+in+Strings):
  #
  #     whitespace = "\x00\t\n\v\f\r "
  #     s = whitespace + 'abc' + whitespace
  #     # => "\u0000\t\n\v\f\r abc\u0000\t\n\v\f\r "
  #     s.strip # => "abc"
  #
  # If `selectors` are given, removes characters of `selectors` from both ends of
  # `self`:
  #
  #     s = "---abc+++"
  #     s.strip("-+") # => "abc"
  #     s.strip("+-") # => "abc"
  #
  # `selectors` must be valid character selectors (see [Character
  # Selectors](rdoc-ref:character_selectors.rdoc)), and may use any of its valid
  # forms, including negation, ranges, and escapes:
  #
  #     "01234abc56789".strip("0-9") # "abc"
  #     "01234abc56789".strip("0-9", "^4-6") # "4abc56"
  #
  # Related: see [Converting to New
  # String](rdoc-ref:String@Converting+to+New+String).
  #
  def strip: () -> String

  # <!--
  #   rdoc-file=string.c
  #   - strip!(*selectors) -> self or nil
  # -->
  # Like String#strip, except that:
  #
  # *   Any modifications are made to `self`.
  # *   Returns `self` if any modification are made, `nil` otherwise.
  #
  # Related: see [Modifying](rdoc-ref:String@Modifying).
  #
  def strip!: () -> self?

  # <!--
  #   rdoc-file=string.c
  #   - sub(pattern, replacement)   -> new_string
  #   - sub(pattern) {|match| ... } -> new_string
  # -->
  # Returns a copy of self, possibly with a substring replaced.
  #
  # Argument `pattern` may be a string or a Regexp; argument `replacement` may be
  # a string or a Hash.
  #
  # Varying types for the argument values makes this method very versatile.
  #
  # Below are some simple examples; for many more examples, see [Substitution
  # Methods](rdoc-ref:String@Substitution+Methods).
  #
  # With arguments `pattern` and string `replacement` given, replaces the first
  # matching substring with the given replacement string:
  #
  #     s = 'abracadabra'       # => "abracadabra"
  #     s.sub('bra', 'xyzzy')   # => "axyzzycadabra"
  #     s.sub(/bra/, 'xyzzy')   # => "axyzzycadabra"
  #     s.sub('nope', 'xyzzy')  # => "abracadabra"
  #
  # With arguments `pattern` and hash `replacement` given, replaces the first
  # matching substring with a value from the given replacement hash, or removes
  # it:
  #
  #     h = {'a' => 'A', 'b' => 'B', 'c' => 'C'}
  #     s.sub('b', h)  # => "aBracadabra"
  #     s.sub(/b/, h)  # => "aBracadabra"
  #     s.sub(/d/, h)  # => "abracaabra"  # 'd' removed.
  #
  # With argument `pattern` and a block given, calls the block with each matching
  # substring; replaces that substring with the block’s return value:
  #
  #     s.sub('b') {|match| match.upcase } # => "aBracadabra"
  #
  # Related: see [Converting to New
  # String](rdoc-ref:String@Converting+to+New+String).
  #
  def sub: (Regexp | string pattern, string | hash[String, _ToS] replacement) -> String
         | (Regexp | string pattern) { (String match) -> _ToS } -> String

  # <!--
  #   rdoc-file=string.c
  #   - sub!(pattern, replacement)   -> self or nil
  #   - sub!(pattern) {|match| ... } -> self or nil
  # -->
  # Like String#sub, except that:
  #
  # *   Changes are made to `self`, not to copy of `self`.
  # *   Returns `self` if any changes are made, `nil` otherwise.
  #
  # Related: see [Modifying](rdoc-ref:String@Modifying).
  #
  def sub!: (Regexp | string pattern, string | hash[String, _ToS] replacement) -> self?
          | (Regexp | string pattern) { (String match) -> _ToS } -> self?

  # <!--
  #   rdoc-file=string.c
  #   - succ -> new_str
  # -->
  # Returns the successor to `self`. The successor is calculated by incrementing
  # characters.
  #
  # The first character to be incremented is the rightmost alphanumeric: or, if no
  # alphanumerics, the rightmost character:
  #
  #     'THX1138'.succ   # => "THX1139"
  #     '<<koala>>'.succ # => "<<koalb>>"
  #     '***'.succ       # => '**+'
  #     'тест'.succ      # => "тесу"
  #     'こんにちは'.succ  # => "こんにちば"
  #
  # The successor to a digit is another digit, "carrying" to the next-left
  # character for a "rollover" from 9 to 0, and prepending another digit if
  # necessary:
  #
  #     '00'.succ # => "01"
  #     '09'.succ # => "10"
  #     '99'.succ # => "100"
  #
  # The successor to a letter is another letter of the same case, carrying to the
  # next-left character for a rollover, and prepending another same-case letter if
  # necessary:
  #
  #     'aa'.succ # => "ab"
  #     'az'.succ # => "ba"
  #     'zz'.succ # => "aaa"
  #     'AA'.succ # => "AB"
  #     'AZ'.succ # => "BA"
  #     'ZZ'.succ # => "AAA"
  #
  # The successor to a non-alphanumeric character is the next character in the
  # underlying character set's collating sequence, carrying to the next-left
  # character for a rollover, and prepending another character if necessary:
  #
  #     s = 0.chr * 3   # => "\x00\x00\x00"
  #     s.succ        # => "\x00\x00\x01"
  #     s = 255.chr * 3 # => "\xFF\xFF\xFF"
  #     s.succ        # => "\x01\x00\x00\x00"
  #
  # Carrying can occur between and among mixtures of alphanumeric characters:
  #
  #     s = 'zz99zz99' # => "zz99zz99"
  #     s.succ         # => "aaa00aa00"
  #     s = '99zz99zz' # => "99zz99zz"
  #     s.succ         # => "100aa00aa"
  #
  # The successor to an empty `String` is a new empty `String`:
  #
  #     ''.succ # => ""
  #
  # Related: see [Converting to New
  # String](rdoc-ref:String@Converting+to+New+String).
  #
  def succ: () -> String

  # <!--
  #   rdoc-file=string.c
  #   - succ! -> self
  # -->
  # Like String#succ, but modifies `self` in place; returns `self`.
  #
  # Related: see [Modifying](rdoc-ref:String@Modifying).
  #
  def succ!: () -> self

  # <!--
  #   rdoc-file=string.c
  #   - sum(n = 16) -> integer
  # -->
  # Returns a basic `n`-bit [checksum](https://en.wikipedia.org/wiki/Checksum) of
  # the characters in `self`; the checksum is the sum of the binary value of each
  # byte in `self`, modulo `2**n - 1`:
  #
  #     'hello'.sum     # => 532
  #     'hello'.sum(4)  # => 4
  #     'hello'.sum(64) # => 532
  #     'тест'.sum      # => 1405
  #     'こんにちは'.sum  # => 2582
  #
  # This is not a particularly strong checksum.
  #
  # Related: see [Querying](rdoc-ref:String@Querying).
  #
  def sum: (?int bits) -> Integer

  # <!--
  #   rdoc-file=string.c
  #   - swapcase(mapping = :ascii) -> new_string
  # -->
  # Returns a string containing the characters in `self`, with cases reversed:
  #
  # *   Each uppercase character is downcased.
  # *   Each lowercase character is upcased.
  #
  # Examples:
  #
  #     'Hello'.swapcase        # => "hELLO"
  #     'Straße'.swapcase       # => "sTRASSE"
  #     'Привет'.swapcase       # => "пРИВЕТ"
  #     'RubyGems.org'.swapcase # => "rUBYgEMS.ORG"
  #
  # The sizes of `self` and the upcased result may differ:
  #
  #     s = 'Straße'
  #     s.size          # => 6
  #     s.swapcase      # => "sTRASSE"
  #     s.swapcase.size # => 7
  #
  # Some characters (and some character sets) do not have upcase and downcase
  # versions; see [Case Mapping](rdoc-ref:case_mapping.rdoc):
  #
  #     s = '1, 2, 3, ...'
  #     s.swapcase == s # => true
  #     s = 'こんにちは'
  #     s.swapcase == s # => true
  #
  # The casing is affected by the given `mapping`, which may be `:ascii`, `:fold`,
  # or `:turkic`; see [Case Mappings](rdoc-ref:case_mapping.rdoc@Case+Mappings).
  #
  # Related: see [Converting to New
  # String](rdoc-ref:String@Converting+to+New+String).
  #
  def swapcase: () -> String
              | (:ascii | :lithuanian | :turkic) -> String
              | (:lithuanian, :turkic) -> String
              | (:turkic, :lithuanian) -> String

  # <!--
  #   rdoc-file=string.c
  #   - swapcase!(mapping) -> self or nil
  # -->
  # Like String#swapcase, except that:
  #
  # *   Changes are made to `self`, not to copy of `self`.
  # *   Returns `self` if any changes are made, `nil` otherwise.
  #
  # Related: see [Modifying](rdoc-ref:String@Modifying).
  #
  def swapcase!: () -> self?
               | (:ascii | :lithuanian | :turkic) -> self?
               | (:lithuanian, :turkic) -> self?
               | (:turkic, :lithuanian) -> self?

  # <!--
  #   rdoc-file=complex.c
  #   - to_c -> complex
  # -->
  # Returns a Complex object: parses the leading substring of `self` to extract
  # two numeric values that become the coordinates of the complex object.
  #
  # The substring is interpreted as containing either rectangular coordinates
  # (real and imaginary parts) or polar coordinates (magnitude and angle parts),
  # depending on an included or implied "separator" character:
  #
  # *   `'+'`, `'-'`, or no separator: rectangular coordinates.
  # *   `'@'`: polar coordinates.
  #
  # **In Brief**
  #
  # In these examples, we use method Complex#rect to display rectangular
  # coordinates, and method Complex#polar to display polar coordinates.
  #
  #     # Rectangular coordinates.
  #
  #     # Real-only: no separator; imaginary part is zero.
  #     '9'.to_c.rect         # => [9, 0]         # Integer.
  #     '-9'.to_c.rect        # => [-9, 0]        # Integer (negative).
  #     '2.5'.to_c.rect       # => [2.5, 0]       # Float.
  #     '1.23e-14'.to_c.rect  # => [1.23e-14, 0]  # Float with exponent.
  #     '2.5/1'.to_c.rect     # => [(5/2), 0]     # Rational.
  #
  #     # Some things are ignored.
  #     'foo1'.to_c.rect      # => [0, 0]         # Unparsed entire substring.
  #     '1foo'.to_c.rect      # => [1, 0]         # Unparsed trailing substring.
  #     ' 1 '.to_c.rect       # => [1, 0]         # Leading and trailing whitespace.
  #     *
  #     # Imaginary only: trailing 'i' required; real part is zero.
  #     '9i'.to_c.rect        # => [0, 9]
  #     '-9i'.to_c.rect       # => [0, -9]
  #     '2.5i'.to_c.rect      # => [0, 2.5]
  #     '1.23e-14i'.to_c.rect # => [0, 1.23e-14]
  #     '2.5/1i'.to_c.rect    # => [0, (5/2)]
  #
  #     # Real and imaginary; '+' or '-' separator; trailing 'i' required.
  #     '2+3i'.to_c.rect      # => [2, 3]
  #     '-2-3i'.to_c.rect     # => [-2, -3]
  #     '2.5+3i'.to_c.rect    # => [2.5, 3]
  #     '2.5+3/2i'.to_c.rect  # => [2.5, (3/2)]
  #
  #     # Polar coordinates; '@' separator; magnitude required.
  #     '1.0@0'.to_c.polar             # => [1.0, 0.0]
  #     '1.0@'.to_c.polar              # => [1.0, 0.0]
  #     "1.0@#{Math::PI}".to_c.polar   # => [1.0, 3.141592653589793]
  #     "1.0@#{Math::PI/2}".to_c.polar # => [1.0, 1.5707963267948966]
  #
  # **Parsed Values**
  #
  # The parsing may be thought of as searching for numeric literals embedded in
  # the substring.
  #
  # This section shows how the method parses numeric values from leading
  # substrings. The examples show real-only or imaginary-only parsing; the parsing
  # is the same for each part.
  #
  #     '1foo'.to_c # => (1+0i)      # Ignores trailing unparsed characters.
  #     ' 1 '.to_c  # => (1+0i)      # Ignores leading and trailing whitespace.
  #     'x1'.to_c   # => (0+0i)      # Finds no leading numeric.
  #
  #     # Integer literal embedded in the substring.
  #     '1'.to_c       # => (1+0i)
  #     '-1'.to_c      # => (-1+0i)
  #     '1i'.to_c      # => (0+1i)
  #
  #     # Integer literals that don't work.
  #     '0b100'.to_c   # => (0+0i)   # Not parsed as binary.
  #     '0o100'.to_c   # => (0+0i)   # Not parsed as octal.
  #     '0d100'.to_c   # => (0+0i)   # Not parsed as decimal.
  #     '0x100'.to_c   # => (0+0i)   # Not parsed as hexadecimal.
  #     '010'.to_c     # => (10+0i)  # Not parsed as octal.
  #
  #     # Float literals:
  #     '3.14'.to_c    # => (3.14+0i)
  #     '3.14i'.to_c   # => (0+3.14i)
  #     '1.23e4'.to_c  # => (12300.0+0i)
  #     '1.23e+4'.to_c # => (12300.0+0i)
  #     '1.23e-4'.to_c # => (0.000123+0i)
  #
  #     # Rational literals:
  #     '1/2'.to_c     # => ((1/2)+0i)
  #     '-1/2'.to_c    # => ((-1/2)+0i)
  #     '1/2r'.to_c    # => ((1/2)+0i)
  #     '-1/2r'.to_c   # => ((-1/2)+0i)
  #
  # **Rectangular Coordinates**
  #
  # With separator `'+'` or `'-'`, or with no separator, interprets the values as
  # rectangular coordinates: real and imaginary.
  #
  # With no separator, assigns a single value to either the real or the imaginary
  # part:
  #
  #      ''.to_c  # => (0+0i)  # Defaults to zero.
  #     '1'.to_c  # => (1+0i)  # Real (no trailing 'i').
  #     '1i'.to_c # => (0+1i)  # Imaginary (trailing 'i').
  #     'i'.to_c  # => (0+1i)  # Special case (imaginary 1).
  #
  # With separator `'+'`, both parts positive (or zero):
  #
  #     # Without trailing 'i'.
  #     '+'.to_c    # => (0+0i)  # No values: defaults to zero.
  #     '+1'.to_c   # => (1+0i)  # Value after '+': real only.
  #     '1+'.to_c   # => (1+0i)  # Value before '+': real only.
  #     '2+1'.to_c  # => (2+0i)  # Values before and after '+': real and imaginary.
  #     # With trailing 'i'.
  #     '+1i'.to_c  # => (0+1i)  # Value after '+': imaginary only.
  #     '2+i'.to_c  # => (2+1i)  # Value before '+': real and imaginary 1.
  #     '2+1i'.to_c # => (2+1i)  # Values before and after '+': real and imaginary.
  #
  # With separator `'-'`, negative imaginary part:
  #
  #     # Without trailing 'i'.
  #     '-'.to_c    # => (0+0i)   # No values: defaults to zero.
  #     '-1'.to_c   # => (-1+0i)  # Value after '-': negative real, zero imaginary.
  #     '1-'.to_c   # => (1+0i)   # Value before '-': positive real, zero imaginary.
  #     '2-1'.to_c  # => (2+0i)   # Values before and after '-': positive real, zero imaginary.
  #     # With trailing 'i'.
  #     '-1i'.to_c  # => (0-1i)   # Value after '-': negative real, zero imaginary.
  #     '2-i'.to_c  # => (2-1i)   # Value before '-': positive real, negative imaginary.
  #     '2-1i'.to_c # => (2-1i)   # Values before and after '-': positive real, negative imaginary.
  #
  # Note that the suffixed character `'i'` may instead be one of `'I'`, `'j'`, or
  # `'J'`, with the same effect.
  #
  # **Polar Coordinates**
  #
  # With separator `'@'`) interprets the values as polar coordinates: magnitude
  # and angle.
  #
  #     '2@'.to_c.polar  # => [2, 0.0]    # Value before '@': magnitude only.
  #      # Values before and after '@': magnitude and angle.
  #     '2@1'.to_c.polar # => [2.0, 1.0]
  #     "1.0@#{Math::PI/2}".to_c # => (0.0+1i)
  #     "1.0@#{Math::PI}".to_c   # => (-1+0.0i)
  #     # Magnitude not given: defaults to zero.
  #     '@'.to_c.polar   # => [0, 0.0]
  #     '@1'.to_c.polar  # => [0, 0.0]
  #
  #     '1.0@0'.to_c             # => (1+0.0i)
  #
  # Note that in all cases, the suffixed character `'i'` may instead be one of
  # `'I'`, `'j'`, `'J'`, with the same effect.
  #
  # See [Converting to Non-String](rdoc-ref:String@Converting+to+Non--5CString).
  #
  def to_c: () -> Complex

  # <!--
  #   rdoc-file=string.c
  #   - to_f -> float
  # -->
  # Returns the result of interpreting leading characters in +self+ as a Float:
  #
  #       '3.14159'.to_f  # => 3.14159
  #       '1.234e-2'.to_f # => 0.01234
  #
  #     Characters past a leading valid number are ignored:
  #
  #       '3.14 (pi to two places)'.to_f # => 3.14
  #
  #     Returns zero if there is no leading valid number:
  #
  #       'abcdef'.to_f # => 0.0
  #
  # See [Converting to Non-String](rdoc-ref:String@Converting+to+Non--5CString).
  #
  def to_f: () -> Float

  # <!--
  #   rdoc-file=string.c
  #   - to_i(base = 10) -> integer
  # -->
  # Returns the result of interpreting leading characters in `self` as an integer
  # in the given `base`; `base` must be either `0` or in range `(2..36)`:
  #
  #     '123456'.to_i     # => 123456
  #     '123def'.to_i(16) # => 1195503
  #
  # With `base` zero given, string `object` may contain leading characters to
  # specify the actual base:
  #
  #     '123def'.to_i(0)   # => 123
  #     '0123def'.to_i(0)  # => 83
  #     '0b123def'.to_i(0) # => 1
  #     '0o123def'.to_i(0) # => 83
  #     '0d123def'.to_i(0) # => 123
  #     '0x123def'.to_i(0) # => 1195503
  #
  # Characters past a leading valid number (in the given `base`) are ignored:
  #
  #     '12.345'.to_i   # => 12
  #     '12345'.to_i(2) # => 1
  #
  # Returns zero if there is no leading valid number:
  #
  #     'abcdef'.to_i # => 0
  #     '2'.to_i(2)   # => 0
  #
  # Related: see [Converting to
  # Non-String](rdoc-ref:String@Converting+to+Non--5CString).
  #
  def to_i: (?int radix) -> Integer

  # <!--
  #   rdoc-file=rational.c
  #   - str.to_r -> rational
  # -->
  # Returns the result of interpreting leading characters in `self` as a rational
  # value:
  #
  #     '123'.to_r       # => (123/1)   # Integer literal.
  #     '300/2'.to_r     # => (150/1)   # Rational literal.
  #     '-9.2'.to_r      # => (-46/5)   # Float literal.
  #     '-9.2e2'.to_r    # => (-920/1)  # Float literal.
  #
  # Ignores leading and trailing whitespace, and trailing non-numeric characters:
  #
  #     ' 2 '.to_r       # => (2/1)
  #     '21-Jun-09'.to_r # => (21/1)
  #
  # Returns Rational zero if there are no leading numeric characters.
  #
  #     'BWV 1079'.to_r  # => (0/1)
  #
  # NOTE: `'0.3'.to_r` is equivalent to `3/10r`, but is different from `0.3.to_r`:
  #
  #     '0.3'.to_r # => (3/10)
  #     3/10r      # => (3/10)
  #     0.3.to_r   # => (5404319552844595/18014398509481984)
  #
  # Related: see [Converting to
  # Non-String](rdoc-ref:String@Converting+to+Non--5CString).
  #
  def to_r: () -> Rational

  # <!--
  #   rdoc-file=string.c
  #   - to_s -> self or new_string
  # -->
  # Returns `self` if `self` is a `String`, or `self` converted to a `String` if
  # `self` is a subclass of `String`.
  #
  # Related: see [Converting to New
  # String](rdoc-ref:String@Converting+to+New+String).
  #
  def to_s: () -> String

  # <!-- rdoc-file=string.c -->
  # Returns `self` if `self` is a `String`, or `self` converted to a `String` if
  # `self` is a subclass of `String`.
  #
  # Related: see [Converting to New
  # String](rdoc-ref:String@Converting+to+New+String).
  #
  alias to_str to_s

  # <!-- rdoc-file=string.c -->
  # Returns the Symbol object derived from `self`, creating it if it did not
  # already exist:
  #
  #     'foo'.intern       # => :foo
  #     'тест'.intern      # => :тест
  #     'こんにちは'.intern # => :こんにちは
  #
  # Related: see [Converting to
  # Non-String](rdoc-ref:String@Converting+to+Non--5CString).
  #
  alias to_sym intern

  # <!--
  #   rdoc-file=string.c
  #   - tr(selector, replacements) -> new_string
  # -->
  # Returns a copy of `self` with each character specified by string `selector`
  # translated to the corresponding character in string `replacements`. The
  # correspondence is *positional*:
  #
  # *   Each occurrence of the first character specified by `selector` is
  #     translated to the first character in `replacements`.
  # *   Each occurrence of the second character specified by `selector` is
  #     translated to the second character in `replacements`.
  # *   And so on.
  #
  # Example:
  #
  #     'hello'.tr('el', 'ip') #=> "hippo"
  #
  # If `replacements` is shorter than `selector`, it is implicitly padded with its
  # own last character:
  #
  #     'hello'.tr('aeiou', '-')   # => "h-ll-"
  #     'hello'.tr('aeiou', 'AA-') # => "hAll-"
  #
  # Arguments `selector` and `replacements` must be valid character selectors (see
  # [Character Selectors](rdoc-ref:character_selectors.rdoc)), and may use any of
  # its valid forms, including negation, ranges, and escapes:
  #
  #     'hello'.tr('^aeiou', '-')       # => "-e--o"     # Negation.
  #     'ibm'.tr('b-z', 'a-z')          # => "hal"       # Range.
  #     'hel^lo'.tr('\^aeiou', '-')     # => "h-l-l-"    # Escaped leading caret.
  #     'i-b-m'.tr('b\-z', 'a-z')       # => "ibabm"     # Escaped embedded hyphen.
  #     'foo\\bar'.tr('ab\\', 'XYZ')    # => "fooZYXr"   # Escaped backslash.
  #
  # Related: see [Converting to New
  # String](rdoc-ref:String@Converting+to+New+String).
  #
  def tr: (selector source, string relpacement) -> String

  # <!--
  #   rdoc-file=string.c
  #   - tr!(selector, replacements) -> self or nil
  # -->
  # Like String#tr, except:
  #
  # *   Performs substitutions in `self` (not in a copy of `self`).
  # *   Returns `self` if any modifications were made, `nil` otherwise.
  #
  # Related: [Modifying](rdoc-ref:String@Modifying).
  #
  def tr!: (selector source, string relpacement) -> self?

  # <!--
  #   rdoc-file=string.c
  #   - tr_s(selector, replacements) -> new_string
  # -->
  # Like String#tr, except:
  #
  # *   Also squeezes the modified portions of the translated string; see
  #     String#squeeze.
  # *   Returns the translated and squeezed string.
  #
  # Examples:
  #
  #     'hello'.tr_s('l', 'r')   #=> "hero"
  #     'hello'.tr_s('el', '-')  #=> "h-o"
  #     'hello'.tr_s('el', 'hx') #=> "hhxo"
  #
  # Related: see [Converting to New
  # String](rdoc-ref:String@Converting+to+New+String).
  #
  def tr_s: (selector source, string replacement) -> String

  # <!--
  #   rdoc-file=string.c
  #   - tr_s!(selector, replacements) -> self or nil
  # -->
  # Like String#tr_s, except:
  #
  # *   Modifies `self` in place (not a copy of `self`).
  # *   Returns `self` if any changes were made, `nil` otherwise.
  #
  # Related: [Modifying](rdoc-ref:String@Modifying).
  #
  def tr_s!: (selector source, string replacement) -> self?

  # <!--
  #   rdoc-file=string.c
  #   - undump -> new_string
  # -->
  # Inverse of String#dump; returns a copy of `self` with changes of the kinds
  # made by String#dump "undone."
  #
  # Related: see [Converting to New
  # String](rdoc-ref:String@Converting+to+New+String).
  #
  def undump: () -> String

  # <!--
  #   rdoc-file=string.c
  #   - unicode_normalize(form = :nfc) -> string
  # -->
  # Returns a copy of `self` with [Unicode
  # normalization](https://unicode.org/reports/tr15) applied.
  #
  # Argument `form` must be one of the following symbols (see [Unicode
  # normalization forms](https://unicode.org/reports/tr15/#Norm_Forms)):
  #
  # *   `:nfc`: Canonical decomposition, followed by canonical composition.
  # *   `:nfd`: Canonical decomposition.
  # *   `:nfkc`: Compatibility decomposition, followed by canonical composition.
  # *   `:nfkd`: Compatibility decomposition.
  #
  # The encoding of `self` must be one of:
  #
  # *   `Encoding::UTF_8`.
  # *   `Encoding::UTF_16BE`.
  # *   `Encoding::UTF_16LE`.
  # *   `Encoding::UTF_32BE`.
  # *   `Encoding::UTF_32LE`.
  # *   `Encoding::GB18030`.
  # *   `Encoding::UCS_2BE`.
  # *   `Encoding::UCS_4BE`.
  #
  # Examples:
  #
  #     "a\u0300".unicode_normalize       # => "à"  # Lowercase 'a' with grave accens.
  #     "a\u0300".unicode_normalize(:nfd) # => "à"  # Same.
  #
  # Related: see [Converting to New
  # String](rdoc-ref:String@Converting+to+New+String).
  #
  def unicode_normalize: (?:nfc | :nfd | :nfkc | :nfkd form) -> self

  # <!--
  #   rdoc-file=string.c
  #   - unicode_normalize!(form = :nfc) -> self
  # -->
  # Like String#unicode_normalize, except that the normalization is performed on
  # `self` (not on a copy of `self`).
  #
  # Related: see [Modifying](rdoc-ref:String@Modifying).
  #
  def unicode_normalize!: (?:nfc | :nfd | :nfkc | :nfkd form) -> self

  # <!--
  #   rdoc-file=string.c
  #   - unicode_normalized?(form = :nfc) -> true or false
  # -->
  # Returns whether `self` is in the given `form` of Unicode normalization; see
  # String#unicode_normalize.
  #
  # The `form` must be one of `:nfc`, `:nfd`, `:nfkc`, or `:nfkd`.
  #
  # Examples:
  #
  #     "a\u0300".unicode_normalized?       # => false
  #     "a\u0300".unicode_normalized?(:nfd) # => true
  #     "\u00E0".unicode_normalized?        # => true
  #     "\u00E0".unicode_normalized?(:nfd)  # => false
  #
  # Raises an exception if `self` is not in a Unicode encoding:
  #
  #     s = "\xE0".force_encoding(Encoding::ISO_8859_1)
  #     s.unicode_normalized? # Raises Encoding::CompatibilityError
  #
  # Related: see [Querying](rdoc-ref:String@Querying).
  #
  def unicode_normalized?: (?:nfc | :nfd | :nfkc | :nfkd) -> bool

  # <!--
  #   rdoc-file=pack.rb
  #   - unpack(template, offset: 0) {|o| .... } -> object
  #   - unpack(template, offset: 0) -> array
  # -->
  # Extracts data from `self` to form new objects; see [Packed
  # Data](rdoc-ref:language/packed_data.rdoc).
  #
  # With a block given, calls the block with each unpacked object.
  #
  # With no block given, returns an array containing the unpacked objects.
  #
  # Related: see [Converting to
  # Non-String](rdoc-ref:String@Converting+to+Non--5CString).
  #
  def unpack: (string template, ?offset: int) -> Array[Integer | Float | String | nil]
            | (string template, ?offset: int) { (Integer | Float | String | nil value) -> void } -> nil

  # <!--
  #   rdoc-file=pack.rb
  #   - unpack1(template, offset: 0) -> object
  # -->
  # Like String#unpack with no block, but unpacks and returns only the first
  # extracted object. See [Packed Data](rdoc-ref:language/packed_data.rdoc).
  #
  # Related: see [Converting to
  # Non-String](rdoc-ref:String@Converting+to+Non--5CString).
  #
  def unpack1: (string template, ?offset: int) -> (Integer | Float | String)?

  # <!--
  #   rdoc-file=string.c
  #   - upcase(mapping = :ascii) -> new_string
  # -->
  # Returns a new string containing the upcased characters in `self`:
  #
  #     'hello'.upcase        # => "HELLO"
  #     'straße'.upcase       # => "STRASSE"
  #     'привет'.upcase       # => "ПРИВЕТ"
  #     'RubyGems.org'.upcase # => "RUBYGEMS.ORG"
  #
  # The sizes of `self` and the upcased result may differ:
  #
  #     s = 'Straße'
  #     s.size        # => 6
  #     s.upcase      # => "STRASSE"
  #     s.upcase.size # => 7
  #
  # Some characters (and some character sets) do not have upcase and downcase
  # versions; see [Case Mapping](rdoc-ref:case_mapping.rdoc):
  #
  #     s = '1, 2, 3, ...'
  #     s.upcase == s # => true
  #     s = 'こんにちは'
  #     s.upcase == s # => true
  #
  # The casing is affected by the given `mapping`, which may be `:ascii`, `:fold`,
  # or `:turkic`; see [Case Mappings](rdoc-ref:case_mapping.rdoc@Case+Mappings).
  #
  # Related: see [Converting to New
  # String](rdoc-ref:String@Converting+to+New+String).
  #
  def upcase: () -> String
            | (:ascii | :lithuanian | :turkic) -> String
            | (:lithuanian, :turkic) -> String
            | (:turkic, :lithuanian) -> String

  # <!--
  #   rdoc-file=string.c
  #   - upcase!(mapping) -> self or nil
  # -->
  # Like String#upcase, except that:
  #
  # *   Changes character casings in `self` (not in a copy of `self`).
  # *   Returns `self` if any changes are made, `nil` otherwise.
  #
  # Related: See [Modifying](rdoc-ref:String@Modifying).
  #
  def upcase!: () -> self?
             | (:ascii | :lithuanian | :turkic) -> self?
             | (:lithuanian, :turkic) -> self?
             | (:turkic, :lithuanian) -> self?

  # <!--
  #   rdoc-file=string.c
  #   - upto(other_string, exclusive = false) {|string| ... } -> self
  #   - upto(other_string, exclusive = false) -> new_enumerator
  # -->
  # With a block given, calls the block with each `String` value returned by
  # successive calls to String#succ; the first value is `self`, the next is
  # `self.succ`, and so on; the sequence terminates when value `other_string` is
  # reached; returns `self`:
  #
  #     a = []
  #     'a'.upto('f') {|c| a.push(c) }
  #     a # => ["a", "b", "c", "d", "e", "f"]
  #
  #     a = []
  #     'Ж'.upto('П') {|c| a.push(c) }
  #     a # => ["Ж", "З", "И", "Й", "К", "Л", "М", "Н", "О", "П"]
  #
  #     a = []
  #     'よ'.upto('ろ') {|c| a.push(c) }
  #     a # => ["よ", "ら", "り", "る", "れ", "ろ"]
  #
  #     a = []
  #     'a8'.upto('b6') {|c| a.push(c) }
  #     a # => ["a8", "a9", "b0", "b1", "b2", "b3", "b4", "b5", "b6"]
  #
  # If argument `exclusive` is given as a truthy object, the last value is
  # omitted:
  #
  #     a = []
  #     'a'.upto('f', true) {|c| a.push(c) }
  #     a # => ["a", "b", "c", "d", "e"]
  #
  # If `other_string` would not be reached, does not call the block:
  #
  #     '25'.upto('5') {|s| fail s }
  #     'aa'.upto('a') {|s| fail s }
  #
  # With no block given, returns a new Enumerator:
  #
  #     'a8'.upto('b6') # => #<Enumerator: "a8":upto("b6")>
  #
  # Related: see [Iterating](rdoc-ref:String@Iterating).
  #
  def upto: (string other_string, ?boolish exclusive) -> Enumerator[String, self]
          | (string other_string, ?boolish exclusive) { (String s) -> void } -> self

  # <!--
  #   rdoc-file=string.c
  #   - valid_encoding? -> true or false
  # -->
  # Returns whether `self` is encoded correctly:
  #
  #     s = 'Straße'
  #     s.valid_encoding?                                 # => true
  #     s.encoding                                        # => #<Encoding:UTF-8>
  #     s.force_encoding(Encoding::ASCII).valid_encoding? # => false
  #
  # Related: see [Querying](rdoc-ref:String@Querying).
  #
  def valid_encoding?: () -> bool
end

%a{deprecated}
interface _ArefFromStringToString
  def []: (String) -> String
end

%a{deprecated}
type String::encode_fallback = Hash[String, String] | Proc | Method | String::_ArefFromStringToString

# Don't use this interface directly
#
# This is a copy of `::_ArefFromStringToString` but without deprecated attribute.
# This is a workaround to avoid deprecation warnings in `String::encode_fallback` type.
#
# This type will be deprecated soon once `::_ArefFromStringToString` and `String::encode_fallback` are removed.
#
interface String::_ArefFromStringToString
  def []: (String) -> String
end
