Confusing error message: the trait std::ops::Fn<(char,)> is not implemented for T

6838fae
Opened by toddWannaCode at 2024-10-04 23:38:55

Hey I am a newbie trying to learn rust following th rust-book(2nd edition). So, I was trying to implement the greps project and I am stuck at the search function.

fn search<'a, T>(query: &T, contents: &'a str) -> Vec<&'a str> {
    let mut results = Vec::new();

    for line in contents.lines() {
        if line.contains(query) {
            results.push(line);
        }
    }
    results
}

I am getting this error. :

rustc 1.18.0 (03fc9d622 2017-06-06)
error[E0277]: the trait bound `T: std::ops::Fn<(char,)>` is not satisfied
  --> <anon>:39:17
   |
39 |         if line.contains(query) {
   |                 ^^^^^^^^ the trait `std::ops::Fn<(char,)>` is not implemented for `T`
   |
   = help: consider adding a `where T: std::ops::Fn<(char,)>` bound
   = note: required because of the requirements on the impl of `std::ops::FnOnce<(char,)>` for `&T`
   = note: required because of the requirements on the impl of `std::str::pattern::Pattern<'_>` for `&T`

error[E0277]: the trait bound `T: std::ops::FnOnce<(char,)>` is not satisfied
  --> <anon>:39:17
   |
39 |         if line.contains(query) {
   |                 ^^^^^^^^ the trait `std::ops::FnOnce<(char,)>` is not implemented for `T`
   |
   = help: consider adding a `where T: std::ops::FnOnce<(char,)>` bound
   = note: required because of the requirements on the impl of `std::str::pattern::Pattern<'_>` for `&T`

error[E0277]: the trait bound `str: std::marker::Sized` is not satisfied
  --> <anon>:57:40
   |
57 |         assert_eq!(vec!["KAMEHAMEHA"], search(query, contents));
   |                                        ^^^^^^ the trait `std::marker::Sized` is not implemented for `str`
   |
   = note: `str` does not have a constant size known at compile-time
   = note: required by `search`

error: aborting due to 3 previous errors

Why do I need the Fn trait? And also adding that trait isn't solving my problem. I am using generics, and I know I don't really need generics here but I am trying to understand the topic. Rust-playground gist: https://play.rust-lang.org/?gist=ca11eb8e51982f63a61ff05c542ec0db&version=stable&backtrace=0

  1. For reference, it looks like a cross-posting of an SO question.

    Masaki Hara at 2017-07-02 14:08:30

  2. Current output removes the duplicates, but nothing more:

    error[E0277]: the trait bound `T: std::ops::Fn<(char,)>` is not satisfied
     --> src/main.rs:5:17
      |
    5 |         if line.contains(query) {
      |                 ^^^^^^^^ the trait `std::ops::Fn<(char,)>` is not implemented for `T`
      |
      = help: consider adding a `where T: std::ops::Fn<(char,)>` bound
      = note: required because of the requirements on the impl of `std::ops::FnOnce<(char,)>` for `&T`
      = note: required because of the requirements on the impl of `std::str::pattern::Pattern<'_>` for `&T`
    

    Esteban Kuber at 2018-02-10 03:01:27

  3. Current output:

    error[E0277]: expected a `std::ops::Fn<(char,)>` closure, found `T`
     --> src/lib.rs:7:26
      |
    7 |         if line.contains(query) {
      |                          ^^^^^ expected an `Fn<(char,)>` closure, found `T`
      |
      = help: the trait `std::ops::Fn<(char,)>` is not implemented for `T`
      = note: required because of the requirements on the impl of `std::ops::FnOnce<(char,)>` for `&T`
      = note: required because of the requirements on the impl of `std::str::pattern::Pattern<'_>` for `&T`
    help: consider restricting type parameter `T`
      |
    3 | fn search<'a, T: std::ops::Fn<(char,)>>(query: &T, contents: &'a str) -> Vec<&'a str> {
      |                ^^^^^^^^^^^^^^^^^^^^^^^
    

    Applying the suggestion gives us the wrong closure return type:

    error[E0658]: the precise format of `Fn`-family traits' type parameters is subject to change
     --> src/lib.rs:3:18
      |
    3 | fn search<'a, T: Fn<(char,)>>(query: &T, contents: &'a str) -> Vec<&'a str> {
      |                  ^^ help: use parenthetical notation instead: `Fn(char,) -> ()`
      |
      = note: see issue #29625 <https://github.com/rust-lang/rust/issues/29625> for more information
    

    which leads to

    error[E0271]: type mismatch resolving `<&T as std::ops::FnOnce<(char,)>>::Output == bool`
     --> src/lib.rs:7:17
      |
    7 |         if line.contains(query) {
      |                 ^^^^^^^^ expected `()`, found `bool`
      |
      = note: required because of the requirements on the impl of `std::str::pattern::Pattern<'_>` for `&T`
    

    The fix is to write T: Fn(char) -> bool instead of T: Fn(char) -> ().

    This is not necessarily the correct fix for this case.

    Esteban Kuber at 2020-06-11 23:08:36

  4. Triage: a few cosmetic changes, but otherwise it's the same.

    Esteban Kuber at 2022-06-08 22:17:59

  5. Current output:

    error[E0277]: the trait bound `&T: Pattern` is not satisfied
        --> src/lib.rs:39:26
         |
    39   |         if line.contains(query) {
         |                 -------- ^^^^^ the trait `Fn(char)` is not implemented for `T`, which is required by `&T: Pattern`
         |                 |
         |                 required by a bound introduced by this call
         |
         = note: required for `&T` to implement `FnOnce(char)`
         = note: required for `&T` to implement `Pattern`
    note: required by a bound in `core::str::<impl str>::contains`
        --> /playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/str/mod.rs:1124:24
         |
    1124 |     pub fn contains<P: Pattern>(&self, pat: P) -> bool {
         |                        ^^^^^^^ required by this bound in `core::str::<impl str>::contains`
    help: consider restricting type parameter `T`
         |
    35   | fn search<'a, T: Fn(char)>(query: &T, contents: &'a str) -> Vec<&'a str> {
         |                ++++++++++
    
    error[E0277]: the size for values of type `str` cannot be known at compilation time
      --> src/lib.rs:57:47
       |
    57 |         assert_eq!(vec!["KAMEHAMEHA"], search(query, contents));
       |                                        ------ ^^^^^ doesn't have a size known at compile-time
       |                                        |
       |                                        required by a bound introduced by this call
       |
       = help: the trait `Sized` is not implemented for `str`
    note: required by an implicit `Sized` bound in `search`
      --> src/lib.rs:35:15
       |
    35 | fn search<'a, T>(query: &T, contents: &'a str) -> Vec<&'a str> {
       |               ^ required by the implicit `Sized` requirement on this type parameter in `search`
    help: consider relaxing the implicit `Sized` restriction
       |
    35 | fn search<'a, T: ?Sized>(query: &T, contents: &'a str) -> Vec<&'a str> {
       |                ++++++++
    

    Esteban Kuber at 2024-10-04 23:38:55