Skip to content
rusthacks.dev
Generics

Rust Error E0599 No Method Found for This Type Fixed

E0599 means no method with that name exists on that type, or the trait providing it is not in scope or not implemented. Find which of five causes applies.

8 min read
Summarize in AI
Flat illustration for the post “Rust Error E0599 No Method Found for This Type Fixed”, composed around errors.

error[E0599]: no method named ... found for ... in the current scope says the compiler looked at the type of the value you called a method on and found no method with that name that it is allowed to use. The wording hides several different causes: the method is on a different type, the method comes from a trait that is not imported, the trait is not implemented for this type, the type is wrapped in an Option or Result you forgot to open, or you misspelled the name. They look identical until you read the type named in the message. This post goes through the five causes in order of frequency, each with the compiler's real output from Rust 1.99 and the fix. The first thing to check, always, is which type the message says the method was not found for.

Cause one: the value is wrapped in Option or Result

The most frequent cause is calling a method of the inner type on the wrapper:

src/main.rsrust
fn main() {
    let name: Option<String> = Some("ferris".to_string());
    println!("{}", name.to_uppercase());
}
Text
error[E0599]: no method named `to_uppercase` found for enum `Option<T>` in the current scope
 --> a599b.rs:3:25
  |
3 |     println!("{}", name.to_uppercase());
  |                         ^^^^^^^^^^^^ method not found in `Option<String>`
  |
note: the method `to_uppercase` exists on the type `String`
help: consider using `Option::expect` to unwrap the `String` value, panicking if the value is an `Option::None`
  |
3 |     println!("{}", name.expect("REASON").to_uppercase());
  |                        +++++++++++++++++

The note is the diagnosis: the method exists on String, and you have an Option<String>. The compiler suggests expect, which panics on None and is the wrong default for real code. Decide what a missing value should mean and write that. To transform the inside and keep the wrapper, use map; to provide a fallback, unwrap_or or unwrap_or_default; to bail out of the function, ?.

src/main.rsrust
println!("{}", name.as_deref().map(str::to_uppercase).unwrap_or_default());
Text
FERRIS

as_deref turns Option<String> into Option<&str> without consuming it, map applies the method, and unwrap_or_default returns an empty string for None. The same shape applies to Result, where map_err and ? are the companions. Some methods do exist on Option itself, and a few collide in name with inner-type methods; in the current standard library Option even has a private len, so calling .len() on an Option<String> gives E0624, "method len is private", with the same note pointing at String. The diagnosis is the same.

Cause two: the trait is not in scope

Methods that come from a trait are available only when the trait is imported, even if the type implements it:

src/main.rsrust
use std::fs::File;

fn main() {
    let mut f = File::create("out.txt").unwrap();
    f.write_all(b"hello").unwrap();
}
Text
error[E0599]: no method named `write_all` found for struct `File` in the current scope
 --> b599.rs:5:7
  |
5 |     f.write_all(b"hello").unwrap();
  |       ^^^^^^^^^
  |
  = note: the method is available for `File` here
  = help: items from traits can only be used if the trait is in scope
help: trait `Write` which provides `write_all` is implemented but not in scope; perhaps you want to import it
  |
1 + use std::io::Write;
  |

This one confuses beginners because File clearly can be written to. The message says the method is available "here" and "the trait is in scope" is the missing condition. Add the import and it compiles. The rule exists so that two traits with a method of the same name do not conflict: only the traits you imported take part in method lookup. The traits you will import most often are std::io::{Read, Write, BufRead}, std::fmt::Write, std::str::FromStr, std::iter::FromIterator and extension traits from crates like futures::StreamExt and itertools::Itertools. The compiler almost always names the one you need in the help line.

Cause three: the trait is not implemented

If the trait is defined but your type has no implementation, you get a different note:

src/main.rsrust
struct Config {
    name: String,
}

fn main() {
    let a = Config { name: "x".into() };
    let b = a.clone();
}
Text
error[E0599]: no method named `clone` found for struct `Config` in the current scope
 --> c599.rs:7:15
  |
1 | struct Config {
  | ------------- method `clone` not found for this struct
...
7 |     let b = a.clone();
  |               ^^^^^ method not found in `Config`
  |
  = help: items from traits can only be used if the trait is implemented and in scope
  = note: the following trait defines an item `clone`, perhaps you need to implement it:
          candidate #1: `Clone`

clone comes from the Clone trait, which Config does not implement. For standard traits with a mechanical implementation, add #[derive(Clone)] on the struct, and for others write the impl block. The phrase "perhaps you need to implement it" with a candidate list is the signal. Compare it with cause two, where the message says the trait is implemented but not in scope. The two notes tell you which of the two repairs applies.

Cause four: the type is not what you think

Calling a collection method on the wrong type produces a short message with little help text:

Text
error[E0599]: no method named `iter` found for type `{integer}` in the current scope
 --> d599.rs:3:20
  |
3 |     for n in total.iter() {
  |                    ^^^^ method not found in `{integer}`

total is a number and the programmer meant a collection or a range. The type in the message, {integer}, is the clue: the compiler inferred an integer and nothing else. When the named type surprises you, find where the value came from. A hover in the editor shows the inferred type of every variable, which resolves most of these in seconds. The corrected loop in the example iterates a range, for n in 0..total.

Cause five: a typo or a missing item

The remaining forms are a misspelled name and an item that does not exist:

Text
error[E0599]: no variant, associated function, or constant named `Pending` found for enum `Status` in the current scope
 --> e599.rs:7:21
  |
1 | enum Status {
  | ----------- variant, associated function, or constant `Pending` not found for this enum
...
7 |     let s = Status::Pending;
  |                     ^^^^^^^ variant, associated function, or constant not found in `Status`

error[E0599]: no method named `increment` found for struct `Counter` in the current scope
  --> f599.rs:13:7
   |
13 |     c.increment();
   |       ^^^^^^^^^ method not found in `Counter`

The enum has no Pending variant and the struct has no increment method. Add them, or fix the spelling; the compiler offers a close match when there is one. When it does not, check whether you edited the right file, whether the method sits in a different impl block under a #[cfg] that is not active, or whether you meant a method that takes &mut self and the variable is not declared mut, which has a different error. Here are the repaired versions of all of the above in one program:

src/main.rsrust
use std::fs::File;
use std::io::Write;

#[derive(Clone)]
struct Config {
    name: String,
}

struct Counter {
    count: u32,
}

impl Counter {
    fn new() -> Self {
        Counter { count: 0 }
    }
    fn increment(&mut self) {
        self.count += 1;
    }
}

enum Status {
    Active,
    Inactive,
    Pending,
}

fn main() {
    let name: Option<String> = Some("ferris".to_string());
    // Unwrap (or handle None) before calling a String method.
    println!("{}", name.as_deref().map(str::to_uppercase).unwrap_or_default());

    let mut f = File::create("out.txt").unwrap();
    f.write_all(b"hello").unwrap();

    let a = Config { name: "x".into() };
    let b = a.clone();
    println!("{} {}", a.name, b.name);

    let total = 10;
    for n in 0..total {
        if n == 9 {
            println!("{n}");
        }
    }

    let mut c = Counter::new();
    c.increment();
    println!("count {}", c.count);

    for s in [Status::Active, Status::Inactive, Status::Pending] {
        let label = match s {
            Status::Active => "active",
            Status::Inactive => "inactive",
            Status::Pending => "pending",
        };
        print!("{label} ");
    }
    println!();
}
Text
FERRIS
x x
9
count 1
active inactive pending

Cause six: the method exists, but only for some type parameters

One variant says the method does exist and still refuses the call, because an impl block carries a bound that your type fails. Here show is defined only for wrappers of printable types:

src/main.rsrust
impl<T: Display> Wrapper<T> {
    fn show(&self) -> String {
        format!("<{}>", self.0)
    }
}

println!("{}", Wrapper(5).show());
println!("{}", Wrapper(Opaque).show());
Text
error[E0599]: the method `show` exists for struct `Wrapper<Opaque>`, but its trait bounds were not satisfied
  --> g599.rs:15:36
   |
11 | struct Opaque;
   | ------------- doesn't satisfy `Opaque: std::fmt::Display`
15 |     println!("{}", Wrapper(Opaque).show());
   |                                    ^^^^ method cannot be called on `Wrapper<Opaque>` due to unsatisfied trait bounds
   |
note: trait bound `Opaque: std::fmt::Display` was not satisfied
 5 | impl<T: Display> Wrapper<T> {
   |         ^^^^^^^  ----------
   |         |
   |         unsatisfied trait bound introduced here

The first call, with an integer, compiles. The second fails because Opaque has no Display. The message tells you which impl block hides the method and which bound failed. The fix is to implement the trait for your type, or to call a different method. This pattern is how the standard library makes Vec<T>::sort available only for T: Ord and Option<T>::cloned available only where T: Clone, and it is why a method can seem to vanish when you change a type parameter.

A short procedure

Read the type in the message. If it is a wrapper (Option, Result, Box, Rc, a reference), the method may be on the inside. If it is the right type, check the note: "trait is implemented but not in scope" means add a use; "perhaps you need to implement it" means add a derive or an impl. If neither note appears and the name looks right, check generic bounds: a method on impl<T: Display> Wrapper<T> is invisible when T is not Display, and the message will say so with "the following trait bounds were not satisfied". And if the name is simply wrong, the editor's autocomplete on the value shows which methods it does have.

For the related errors, E0277 covers a missing trait where a bound demands one, and E0308 covers a value of the wrong type.

Taggede0599
Share

Keep reading

Get new posts by email

We send one email when a new post is published. No spam.

Unsubscribe in one click. No spam, ever.