# Allow &\[&str\] in Pattern

**URL:** https://internals.rust-lang.org/t/allow-str-in-pattern/13961
**Category:** libs
**Created:** [February 2, 2021, 1:18pm UTC](https://internals.rust-lang.org/t/allow-str-in-pattern/13961 "2021-02-02T13:18:10Z")
**Posts on this page:** 20
**Page:** 1

<div class="post-metadata">

### Author: ![Soni](https://avatars.discourse-cdn.com/v4/letter/s/a3d4f5/32.png) [@Soni](https://internals.rust-lang.org/u/Soni)
#### Post date: [February 2, 2021, 1:18pm UTC](https://internals.rust-lang.org/t/allow-str-in-pattern/13961/1 "2021-02-02T13:18:10Z")

</div>

As some may know, [we're anti-`char`](https://github.com/rust-lang/rust-clippy/issues/5598). As such it would be nice to have `&[&str]` and `&[String]` in `std::str::pattern::Pattern`, for consistency with discouraging indiscriminate use of USVs where actual characters/grapheme clusters may be more helpful. With potential optimizations for when the strings are sorted, ofc.

---

<div class="post-metadata">

### Author: ![comex](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/comex/32/2587_2.png) [@comex](https://internals.rust-lang.org/u/comex)
#### Post date: [February 3, 2021, 4:56pm UTC](https://internals.rust-lang.org/t/allow-str-in-pattern/13961/2 "2021-02-03T16:56:31Z")

</div>

Are you suggesting that `str.find(&["a", "b", "c"])` would behave like `str.find("abc")`?

I would intuitively expect it to do something different: find _any_ of a, b, or c.

---

<div class="post-metadata">

### Author: ![Soni](https://avatars.discourse-cdn.com/v4/letter/s/a3d4f5/32.png) [@Soni](https://internals.rust-lang.org/u/Soni)
#### Post date: [February 3, 2021, 5:21pm UTC](https://internals.rust-lang.org/t/allow-str-in-pattern/13961/3 "2021-02-03T17:21:21Z")

</div>

`str.find(&["a", "b", "c", "d"])` should behave like `str.find(&['a', 'b', 'c', 'd'])`:

```rust
fn main() {
    println!("{:?}", "Hello, world!".find(&['a', 'b', 'c', 'd'] as &[char])); // Some(11)
}

```

---

<div class="post-metadata">

### Author: ![camelid](https://avatars.discourse-cdn.com/v4/letter/c/c67d28/32.png) [@camelid](https://internals.rust-lang.org/u/camelid)
#### Post date: [February 3, 2021, 5:28pm UTC](https://internals.rust-lang.org/t/allow-str-in-pattern/13961/4 "2021-02-03T17:28:54Z")

</div>

If you want to request a feature from T-libs, you probably want to open an issue on `rust-lang/rust`.

---

<div class="post-metadata">

### Author: ![Soni](https://avatars.discourse-cdn.com/v4/letter/s/a3d4f5/32.png) [@Soni](https://internals.rust-lang.org/u/Soni)
#### Post date: [February 3, 2021, 5:31pm UTC](https://internals.rust-lang.org/t/allow-str-in-pattern/13961/5 "2021-02-03T17:31:15Z")

</div>

While at it: maybe also add `&[char; N]` and `&[&str; N]`? 😅

---

<div class="post-metadata">

### Author: ![Aloso](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/aloso/32/5039_2.png) [@Aloso](https://internals.rust-lang.org/u/Aloso)
#### Post date: [February 6, 2021, 10:07pm UTC](https://internals.rust-lang.org/t/allow-str-in-pattern/13961/6 "2021-02-06T22:07:10Z")

</div>

I don't think we're "anti-char". `char` has its valid use cases. But I think that implementing `Pattern` for `&[&str]` is useful even when the strings in the slice aren't single Unicode graphemes. For example, a parser could use this:

```rust
input.find(&["//", "/*", "\"", "'"][..])

```

or a simple profanity filter:

```rust
haystack.find(&["asshat", "douchebag", /* more swear words */][..])

```

There are many more use cases.

Ideally, the `Pattern` trait would be stabilized so it could be implemented for types outside of `std`, like `Regex` 🙂

---

<div class="post-metadata">

### Author: ![burntsushi](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/burntsushi/32/279_2.png) [@burntsushi](https://internals.rust-lang.org/u/burntsushi)
#### Post date: [February 6, 2021, 11:46pm UTC](https://internals.rust-lang.org/t/allow-str-in-pattern/13961/7 "2021-02-06T23:46:17Z")

</div>

> [@Aloso](#):
>
> Ideally, the `Pattern` trait would be stabilized so it could be implemented for types outside of `std` , like `Regex`

The regex crate does implement it, but you have to enable the pattern feature: [regex::Regex - Rust](https://docs.rs/regex/1.4.3/regex/struct.Regex.html#using-the-stdstrpattern-methods-with-regex)

Also, the multi-substring search API suggested here doesn't make a ton of sense since building the multi-substring searcher is typically expensive. (Unless you don't mind using a naive and slow search algorithm.)

The crate you want to do this for you is aho-corasick.

---

<div class="post-metadata">

### Author: ![Soni](https://avatars.discourse-cdn.com/v4/letter/s/a3d4f5/32.png) [@Soni](https://internals.rust-lang.org/u/Soni)
#### Post date: [February 7, 2021, 2:21am UTC](https://internals.rust-lang.org/t/allow-str-in-pattern/13961/8 "2021-02-07T02:21:22Z")

</div>

you can optimize if the array is sorted. but please deprecate `char`, as `char` generally leads to broken unicode handling. :‌) (see also: can't get a `char` from an `str[usize]` operation)

---

<div class="post-metadata">

### Author: ![jhpratt](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jhpratt/32/11640_2.png) [@jhpratt](https://internals.rust-lang.org/u/jhpratt)
#### Post date: [February 7, 2021, 8:46am UTC](https://internals.rust-lang.org/t/allow-str-in-pattern/13961/9 "2021-02-07T08:46:22Z")

</div>

Please explain. stdlib's implementation works as expected, and nothing the user does could lead to things being broken there. Regardless, trait implementations cannot be deprecated _even if_ it was wanted.

---

<div class="post-metadata">

### Author: ![Soni](https://avatars.discourse-cdn.com/v4/letter/s/a3d4f5/32.png) [@Soni](https://internals.rust-lang.org/u/Soni)
#### Post date: [February 7, 2021, 12:06pm UTC](https://internals.rust-lang.org/t/allow-str-in-pattern/13961/10 "2021-02-07T12:06:13Z")

</div>

As we said:

> [@Soni](#):
>
> discouraging indiscriminate use of USVs where actual characters/grapheme clusters may be more helpful

Please don't use `char`, it's generally the wrong tool for the job. You can't even do e.g. `'é'` in Rust, and if you attempt to match on `'é'` it'll randomly fail even tho it'll look like it matches perfectly.

A naive and a sorted multi-substring searcher would be more than good enough.

---

<div class="post-metadata">

### Author: ![Aloso](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/aloso/32/5039_2.png) [@Aloso](https://internals.rust-lang.org/u/Aloso)
#### Post date: [February 7, 2021, 1:33pm UTC](https://internals.rust-lang.org/t/allow-str-in-pattern/13961/11 "2021-02-07T13:33:18Z")

</div>

Using a `&str` as pattern instead wouldn't help in this case. To handle it properly, you have to normalize the string first, and then it doesn't matter whether you use `'é'` or `"é"` as pattern.

---

<div class="post-metadata">

### Author: ![Soni](https://avatars.discourse-cdn.com/v4/letter/s/a3d4f5/32.png) [@Soni](https://internals.rust-lang.org/u/Soni)
#### Post date: [February 7, 2021, 2:10pm UTC](https://internals.rust-lang.org/t/allow-str-in-pattern/13961/12 "2021-02-07T14:10:54Z")

</div>

you'd use `&["é", "é"]` as the pattern.

---

<div class="post-metadata">

### Author: ![quaternic](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/quaternic/32/10440_2.png) [@quaternic](https://internals.rust-lang.org/u/quaternic)
#### Post date: [February 7, 2021, 6:24pm UTC](https://internals.rust-lang.org/t/allow-str-in-pattern/13961/13 "2021-02-07T18:24:30Z")

</div>

Imagine seeing that in some source code and wondering if it's correct, and then finding out it's actually the same bytes two times. This is the case in your post, which has most likely been normalized somewhere along the way over the web.

It's probably a good idea to use escapes when the distinction matters, so that the meaning of the code doesn't change under Unicode normalization:

```rust
["\u{e9}", "\u{65}\u{0301}"] /* two forms of é */

```

---

<div class="post-metadata">

### Author: ![Soni](https://avatars.discourse-cdn.com/v4/letter/s/a3d4f5/32.png) [@Soni](https://internals.rust-lang.org/u/Soni)
#### Post date: [February 7, 2021, 6:55pm UTC](https://internals.rust-lang.org/t/allow-str-in-pattern/13961/14 "2021-02-07T18:55:18Z")

</div>

honestly we were mostly too lazy to type in the correct unicode. besides, most ppl wouldn't know how to tell. but yes ideally you'd spell them out like that instead. :‌p

point being, &[&str] would be good. ^^

---

<div class="post-metadata">

### Author: ![CAD97](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cad97/32/3460_2.png) [@CAD97](https://internals.rust-lang.org/u/CAD97)
#### Post date: [February 7, 2021, 7:07pm UTC](https://internals.rust-lang.org/t/allow-str-in-pattern/13961/15 "2021-02-07T19:07:14Z")

</div>

> [@Soni](#):
>
> you can optimize if the array is sorted

Define "sorted". Since we're dealing with Unicode, there are at least 5 different ways of sorting strings, at least two of which are locale-sensitive.

And in any case, Rust prefers avoiding APIs (where possible) that are just magically more or less performant depending on minor source code details.

It might be reasonable to have a pattern object constructor assume sorted input and miss some matches if it isn't, but it would be expected to make that known and offer a version that does the sort for you.

The correct answer isn't to "just make `&[&str]` work as a pattern", as convenient as that would be, because of all the little pitfalls involved, which have been illustrated here.

The best solution would be to stabilize the `Pattern` trait so that you can use things like aho-corasick.

---

<div class="post-metadata">

### Author: ![Soni](https://avatars.discourse-cdn.com/v4/letter/s/a3d4f5/32.png) [@Soni](https://internals.rust-lang.org/u/Soni)
#### Post date: [February 7, 2021, 7:27pm UTC](https://internals.rust-lang.org/t/allow-str-in-pattern/13961/16 "2021-02-07T19:27:37Z")

</div>

the naive approach works for [char]. so what's the problem? but in particular, sorted by UTF-8 byte order would be fine, and would allow binary searching the pattern (altho that's kinda slow so it might be worse than the naive approach).

and the point is moot when using actual arrays, as min const generics allows rust to create a copy of the array internally and sort it then.

in any case we don't intend them to be a replacement for grep, but a replacement for `&[char]` Patterns.

(fwiw, we're pretty sure something like `trim_start_matches` would be faster even with a naive `[&str]` over an `[char]` as it entirely avoids decoding)

---

<div class="post-metadata">

### Author: ![jdahlstrom](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jdahlstrom/32/3351_2.png) [@jdahlstrom](https://internals.rust-lang.org/u/jdahlstrom)
#### Post date: [February 7, 2021, 8:36pm UTC](https://internals.rust-lang.org/t/allow-str-in-pattern/13961/17 "2021-02-07T20:36:14Z")

</div>

As an aside, the semantics of a `char` slice as a pattern (which is to say, match _any_ of the `char`s) seem to be rather poorly documented. Probably partly because the `Pattern` trait and its impls are still unstable…

> The [pattern](https://doc.rust-lang.org/std/str/pattern/index.html) can be a `&str` , [`char`](https://doc.rust-lang.org/std/primitive.char.html), a slice of [`char`](https://doc.rust-lang.org/std/primitive.char.html)s, or a function or closure that determines if a character matches.

---

<div class="post-metadata">

### Author: ![Soni](https://avatars.discourse-cdn.com/v4/letter/s/a3d4f5/32.png) [@Soni](https://internals.rust-lang.org/u/Soni)
#### Post date: [February 7, 2021, 9:19pm UTC](https://internals.rust-lang.org/t/allow-str-in-pattern/13961/18 "2021-02-07T21:19:30Z")

</div>

Oh yeah. We'd say having a slice of `&str`s as a valid pattern would also help with that.

---

<div class="post-metadata">

### Author: ![notriddle](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/notriddle/32/14082_2.png) [@notriddle](https://internals.rust-lang.org/u/notriddle)
#### Post date: [February 9, 2021, 12:15am UTC](https://internals.rust-lang.org/t/allow-str-in-pattern/13961/19 "2021-02-09T00:15:29Z")

</div>

> [@Soni](#):
>
> the naive approach works for [char]. so what's the problem?

`char` is four bytes, so backtracking isn't a problem. `&str` can be arbitrarily wrong.

---

<div class="post-metadata">

### Author: ![Soni](https://avatars.discourse-cdn.com/v4/letter/s/a3d4f5/32.png) [@Soni](https://internals.rust-lang.org/u/Soni)
#### Post date: [February 9, 2021, 1:01am UTC](https://internals.rust-lang.org/t/allow-str-in-pattern/13961/20 "2021-02-09T01:01:15Z")

</div>

`char` is anywhere between 1 and 4 bytes, when matching against `&str`. either you scan the string as chars (which means decoding) or as bytes (which means encoding). with `&str` you're just matching raw bytes against raw bytes (thanks to UTF-8-provided guarantees).

[Next page](https://internals.rust-lang.org/t/allow-str-in-pattern/13961.md?page=2)
