Rust Error E0411: Cannot Find Type Self in This Scope
E0411 means you wrote Self somewhere Rust can’t tell what it stands for. Self is a shortcut for “the type this impl block (or trait) is about”, so it only works inside an impl, a trait, or a type definition. The usual cause is a constructor like fn new() -> Self written at the top level of a file, or a method you copied out of its impl block. It’s common and quick to fix. Unlike E0412, which became E0425 in Rust 1.93, this code hasn’t changed: rustc 1.97 still prints E0411. It’s part of the compiler errors guide.
The error message
Section titled “The error message”error[E0411]: cannot find type `Self` in this scope --> src/main.rs:5:21 |5 | fn new_counter() -> Self { // ❌ `Self` outside an `impl` | ----------- ^^^^ `Self` is only available in impls, traits, and type definitions | | | `Self` not allowed in a functionThis is the program that produces it:
struct Counter { count: u32,}
fn new_counter() -> Self { // ❌ `Self` outside an `impl` Counter { count: 0 }}
fn main() { let c = new_counter(); println!("{}", c.count);}What it means
Section titled “What it means”rustc points at two things on line 5:
- The
^^^^underSelf: “Selfis only available in impls, traits, and type definitions”. That’s the rule, in one line. - The
-----undernew_counter: “Selfnot allowed in a function”. This is the reason here:new_counteris a plain function, not part of anyimpl.
You may know that new_counter returns a Counter, because you just wrote Counter { count: 0 }. But Rust doesn’t read the body to guess what Self means. Self gets its meaning only from an enclosing impl Counter { ... } or trait ... { ... }, and here there is none.
It’s like the word “here” on a sticky note. On a map, “you are here” makes sense. On a note lying on the kitchen table, nobody knows where “here” is.
Why Rust does this
Section titled “Why Rust does this”Self is not a type of its own. It’s a placeholder that each impl or trait fills in: inside impl Counter, Self means Counter; inside impl Timer, it means Timer; inside a trait, it means “whichever type implements this trait”. That’s what makes it useful: you can rename the struct, or copy a method into another impl, and Self follows along.
A free function belongs to no type, so there’s nothing to fill in. Rust could try to guess from the body, but then a signature would depend on the code inside it, and Rust deliberately checks signatures on their own. See Structs for the usual home of fn new() -> Self.
How to fix it
Section titled “How to fix it”Fix 1: Move the function into an impl block
Section titled “Fix 1: Move the function into an impl block”Choose this most of the time. A function that creates or works with one type belongs in that type’s impl block, and there Self works as you expected. Call it with Counter::new():
struct Counter { count: u32,}
impl Counter { fn new() -> Self { Self { count: 0 } }
fn increment(&mut self) { self.count += 1; }}
fn main() { let mut c = Counter::new(); c.increment(); c.increment(); println!("{}", c.count);}Output:
2Inside the impl, you can use Self both as a type (-> Self) and to build a value (Self { count: 0 }). See Structs.
Fix 2: Write the type’s name instead of Self
Section titled “Fix 2: Write the type’s name instead of Self”Choose this when the function should stay a free function, for example a helper that builds several types, or one that lives in another module. Just write the real type, Counter, where you wrote Self:
struct Counter { count: u32,}
fn new_counter(start: u32) -> Counter { Counter { count: start }}
fn reset(c: &mut Counter) { c.count = 0;}
fn main() { let mut c = new_counter(10); println!("{}", c.count); reset(&mut c); println!("{}", c.count);}Output:
100This is also the fix for fn reset(c: &mut Self) copied out of an impl: every Self in the signature and the body becomes Counter.
Fix 3: Use a generic type if you meant “any type”
Section titled “Fix 3: Use a generic type if you meant “any type””Choose this when you used Self to mean “whatever type the caller wants”, which is a job for a generic T, not Self. Declare <T> with the traits the function needs. Here, T: Default lets the function create a starting value of any type:
fn fresh_pair<T: Default>() -> (T, T) { (T::default(), T::default())}
fn main() { let numbers: (u32, u32) = fresh_pair(); let words: (String, String) = fresh_pair(); println!("{:?}", numbers); println!("{:?}", words);}Output:
(0, 0)("", "")If you want each type to decide how it’s built, put the function in a trait: trait Reset { fn fresh() -> Self; }. Inside a trait, Self means “the type that implements it”. See Generics and Traits.
Where you’ll usually see it
Section titled “Where you’ll usually see it”Self { ... } in main or a free function. let c = Self { count: 0 }; gives E0411 with a slightly different headline: cannot find struct, variant or union type `Self` in this scope. Fix: write Counter { count: 0 }, or call Counter::new().
A helper function nested inside a method. Inside impl Counter, a method that contains its own fn helper() -> Self gets a different code, E0401: can't use `Self` from outer item. A function inside a function doesn’t inherit the outer impl. Fix: write Counter in the inner function, or use a closure, or move helper up into the impl as its own method.
Mixing up Self and self. Capital Self is the type; lowercase self is the value a method is called on. Using self outside a method is a different error, E0424. Fix for both: make sure the code sits inside the right impl block.
Related errors
Section titled “Related errors”- E0424:
self(lowercase, the value) used outside a method. - E0425: cannot find a value, function or (since Rust 1.93) type with a normal name.
- E0412: the old code for “cannot find type”, now reported as E0425.
- E0405: cannot find a trait, usually a missing
useline. - E0401:
Selffrom an outerimplused inside a nested function, shown above. - All compiler errors: the full list of error pages.
Quick check
Section titled “Quick check”Quick check
1. Where can you use Self as a type?
2. fn make_user() -> Self at the top level gives E0411. What's the usual fix?
3. Inside impl Counter, what does Self { count: 0 } create?
Score: 0 / 3
Read more
Section titled “Read more”- E0411 — Rust error codes index: the official explanation of what
Selfstands for, and why it only works in an impl, trait or type definition. - Method Syntax — The Rust Book: associated functions like
fn square(size: u32) -> Self, and howSelfworks in animpl. - The
Selfkeyword — standard library docs: whatSelfmeans in impls, traits and type definitions. Selfin paths — The Rust Reference: the exact rules, including why nested items can’t use an outerSelf.