String::contains(字符串) 给出 "the trait bound String: FnMut<(char,)>` is not satisfied"

String::contains(String) gives "the trait bound String: FnMut<(char,)>` is not satisfied"

以下代码尝试检查 String 是否包含另一个 String。使用 String::contains 方法时出现编译器错误。我希望 String::contains(String) 可以直接使用。

当搜索的模式不是字符串文字时,在 Rust 中执行此操作的正确方法是什么?我做了 rustc --explain E0277,但似乎 String 没有实现 Pattern 特性,是这样吗?

fn main() {
    let a = String::from("abcdefgh");
    let b = String::from("def");

    if a.contains(b) {
        println!("Contained");
    } else {
        println!("Not contained");
    }
}

编译错误:

error[E0277]: the trait bound `std::string::String: std::ops::FnMut<(char,)>` is not satisfied
 --> src/main.rs:6:10
  |
6 |     if a.contains(b) {
  |          ^^^^^^^^ the trait `std::ops::FnMut<(char,)>` is not implemented for `std::string::String`
  |
  = note: required because of the requirements on the impl of `std::str::pattern::Pattern<'_>` for `std::string::String`

让我们检查一下str::contains的方法签名:

pub fn contains<'a, P>(&'a self, pat: P) -> bool 
where
    P: Pattern<'a>,

所以第二个参数必须是 实现 Pattern 的东西,正如您已经注意到的那样。我们可以通过访问 the documentation of Pattern 找出谁实现了该特征。在那里我们可以找到这些 impls:

impl<'a, 'b> Pattern<'a> for &'b str
impl<'a> Pattern<'a> for char
impl<'a, 'b> Pattern<'a> for &'b [char]
impl<'a, F> Pattern<'a> for F 
where
    F: FnMut(char) -> bool, 
impl<'a, 'b, 'c> Pattern<'a> for &'c &'b str
impl<'a, 'b> Pattern<'a> for &'b String

如您所见,特性并未直接为 String 实现。但它是 &String&str 实现的。这是有道理的:只需要读取模式,因此不需要 String 的所有权。

在您的示例中,之后您将无法使用 b,因为它已被移入方法中:

let a: String = String::from("abcdefgh");
let b: String = String::from("def");

a.contains(b);

// If this would work, `b` couldn't be used anymore because it has been moved :(

所以不是传递String (b),而是传递&String (&b):

if a.contains(&b) { ... }
//            ^