rust-lang/rust · error

if we had an explicit self, we wouldn't be here

Error message

if we had an explicit self, we wouldn't be here

What it means

This `unreachable!` is fired by `SelfKind::to_ref_suggestion` when the receiver is a `SelfKind::Value` (`self` / `mut self`) or `SelfKind::Explicit` (`self: TYPE`). The method only knows how to render a *reference* suggestion string (e.g. `&self`, `&pin mut self`); value/explicit selves have no reference prefix to suggest, so reaching this arm means the caller violated that contract. It is an internal rustc invariant, not a user-visible diagnostic.

Source

Thrown at compiler/rustc_ast/src/ast.rs:2952

    /// `self`, `mut self`
    Value(Mutability),
    /// `&'lt self`, `&'lt mut self`
    Region(Option<Lifetime>, Mutability),
    /// `&'lt pin const self`, `&'lt pin mut self`
    Pinned(Option<Lifetime>, Mutability),
    /// `self: TYPE`, `mut self: TYPE`
    Explicit(Box<Ty>, Mutability),
}

impl SelfKind {
    pub fn to_ref_suggestion(&self) -> String {
        match self {
            SelfKind::Region(None, mutbl) => mutbl.ref_prefix_str().to_string(),
            SelfKind::Region(Some(lt), mutbl) => format!("&{lt} {}", mutbl.prefix_str()),
            SelfKind::Pinned(None, mutbl) => format!("&pin {}", mutbl.ptr_str()),
            SelfKind::Pinned(Some(lt), mutbl) => format!("&{lt} pin {}", mutbl.ptr_str()),
            SelfKind::Value(_) | SelfKind::Explicit(_, _) => {
                unreachable!("if we had an explicit self, we wouldn't be here")
            }
        }
    }
}

pub type ExplicitSelf = Spanned<SelfKind>;

impl Param {
    /// Attempts to cast parameter to `ExplicitSelf`.
    pub fn to_self(&self) -> Option<ExplicitSelf> {
        if let PatKind::Ident(BindingMode(ByRef::No, mutbl), ident, _) = self.pat.kind {
            if ident.name == kw::SelfLower {
                return match self.ty.kind {
                    TyKind::ImplicitSelf => Some(respan(self.pat.span, SelfKind::Value(mutbl))),
                    TyKind::Ref(lt, MutTy { ref ty, mutbl }) if ty.kind.is_implicit_self() => {
                        Some(respan(self.pat.span, SelfKind::Region(lt, mutbl)))
                    }
                    TyKind::PinnedRef(lt, MutTy { ref ty, mutbl })

View on GitHub (pinned to 22057b88b0)

Solutions

  1. Match only `SelfKind::Region` and `SelfKind::Pinned` before calling `to_ref_suggestion`, and handle `Value`/`Explicit` separately.
  2. If you need a suggestion for value/explicit self, return the original receiver text or use `Mutability::prefix_str()` directly instead of this method.
  3. Add a regression test that exercises the lint/suggestion path with `self`, `mut self`, and `self: Box<Self>` receivers.

Example fix

// before
let s = self_kind.to_ref_suggestion();

// after
let s = match &self_kind {
    SelfKind::Region(..) | SelfKind::Pinned(..) => self_kind.to_ref_suggestion(),
    SelfKind::Value(mutbl) => mutbl.prefix_str().to_string(),
    SelfKind::Explicit(_, mutbl) => mutbl.prefix_str().to_string(),
};
Defensive patterns

Strategy: type-guard

Validate before calling

// Before calling to_ref_suggestion, confirm the SelfKind is a reference form.
let kind: &SelfKind = /* ... */;
let is_ref = matches!(
    kind,
    SelfKind::Region(_, _) | SelfKind::Pinned(_, _)
);
if !is_ref {
    // skip suggestion; kind is Value/Explicit and has no ref form
}

Type guard

fn is_ref_self_kind(kind: &SelfKind) -> bool {
    matches!(kind, SelfKind::Region(_, _) | SelfKind::Pinned(_, _))
}

Prevention

When it happens

Trigger: A rustc internals caller invokes `SelfKind::to_ref_suggestion()` (or a downstream helper that calls it) on a `SelfKind::Value(..)` or `SelfKind::Explicit(..)` variant — for example, code that builds a `&self`-style suggestion without first excluding value/explicit self kinds. Reachable via lints, suggestions, or HIR lowering paths that ask every `SelfKind` for a reference prefix.

Common situations: Custom rustc patches or new lints that want to emit a borrow-receiver suggestion and route all `SelfKind` variants through `to_ref_suggestion` instead of matching only `Region`/`Pinned`. Also surfaces during refactors that change how method receivers are classified.

Related errors


AI-assisted analysis of rust-lang/rust@22057b88b0 (2026-08-03). Data as JSON: /data/errors/0fb94d40baf8acc1.json. Report an issue: GitHub.