2
    let mystring = format!("the quick brown {}", "fox...");
    assert!(mystring.ends_with(mystring));

Error:

the trait `std::ops::FnMut<(char,)>` is not implemented for `std::string::String`

Changing mystring.ends_with(mystring) to mystring.ends_with(mystring.as_str()) fixes it.

Why is this error so cryptic?

If I create the string without using format, say:

let mystring = String::from_str("The quick brown fox...");
assert!(mystring.ends_with(mystring));

The error is much more understandable:

error[E0599]: no method named `ends_with` found for type
`std::result::Result<std::string::String, std::string::ParseError>`
in the current scope
marathon
  • 7,881
  • 17
  • 74
  • 137

1 Answers1

9

There's more to that error:

| assert!(mystring.ends_with(mystring));
|                  ^^^^^^^^^ 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`

critically

note: required because of the requirements on the impl of std::str::pattern::Pattern<'_> for std::string::String

String's .ends_with accepts any value that implements the Pattern trait as its search pattern, and String does not implement that trait.

If you look at the documentation for Pattern, it includes

impl<'a, 'b> Pattern<'a> for &'b String

so your snippet works fine if you change

assert!(mystring.ends_with(mystring));

to

assert!(mystring.ends_with(&mystring));

It also makes sense because otherwise you'd be trying to pass ownership of mystring to the ends_with function, which doesn't seem right.

As for the specific error you were seeing, Pattern's trait definition also includes

impl<'a, F> Pattern<'a> for F 
where
    F: FnMut(char) -> bool, 

which generically says functions accepting a char and returning a boolean count as patterns, leading to the message saying String does not match that trait implementation.

loganfsmyth
  • 156,129
  • 30
  • 331
  • 251