rust-lang/rust · error

must contain self type as `SelfTy` propagation kind is speci

Error message

must contain self type as `SelfTy` propagation kind is specified

What it means

This `expect` fires in the Rust `rustc_ast_lowering` delegation pass when a `DelegationSelfTyPropagationKind::SelfTy` is registered for a callee path but the resulting `QPath::Resolved` carries `None` for its leading type. Delegation macros that propagate the parent's `Self` type must always attach a self-type to the resolved path; if the path was constructed without one, this internal invariant is violated. It is an ICE (internal compiler error), not a user diagnostic — the front-end is supposed to guarantee the self type is present whenever the propagation kind is set.

Source

Thrown at compiler/rustc_ast_lowering/src/delegation/mod.rs:424

                            None => hir::Ty { kind, hir_id: self.next_id(), span },
                        };

                        Some(&*self.arena.alloc(ty))
                    }
                    _ => ty,
                };

                hir::QPath::Resolved(ty, self.arena.alloc(new_path))
            }
            hir::QPath::TypeRelative(..) => unreachable!("until inherent methods are supported"),
        };

        if let Some(hir::DelegationSelfTyPropagationKind::SelfTy(id)) =
            generics.self_ty_propagation_kind.as_mut()
        {
            *id = match new_path {
                hir::QPath::Resolved(ty, _) => {
                    ty.expect("must contain self type as `SelfTy` propagation kind is specified")
                }
                hir::QPath::TypeRelative(ty, _) => ty,
            }
            .hir_id;
        }

        let callee_path = self.arena.alloc(self.mk_expr(hir::ExprKind::Path(new_path), span));
        let args = self.arena.alloc_from_iter(args);
        let call = self.mk_expr(hir::ExprKind::Call(callee_path, args), span);

        let expr = if res.sig_mapping.map_return {
            let res = Res::SelfTyAlias {
                alias_to: res.parent.to_def_id(),
                is_trait_impl: self.tcx.def_kind(res.parent) == DefKind::Impl { of_trait: true },
            };

            let ident = Ident::new(kw::SelfUpper, span);
            let path = self.create_resolved_path(res, ident, span);

View on GitHub (pinned to 22057b88b0)

Solutions

  1. File an issue at https://github.com/rust-lang/rust/issues with the ICE backtrace and a minimal `#![feature(fn_delegation)]` reproducer; this is a compiler bug, not your code.
  2. Rewrite the delegation to avoid inherent-method / type-relative callee paths — delegate to a free function or trait method path that resolves to a unit/`Self`-typed path instead.
  3. Update to a newer nightly: the delegation dir changes frequently and the self-type-propagation invariant may already be fixed for your case.
  4. If you are hacking on rustc itself, audit `lower_qpath`/`create_generic_arg_path` (around `delegation/mod.rs:400-410`) to ensure a `Ty` is always allocated when `self_ty_propagation_kind` is set.

Example fix

// before — delegating to an inherent method path (unsupported, trips the invariant)
#![feature(fn_delegation)]
impl S {
    delegate * to self.method; // path resolves TypeRelative/Resolved(None)
}

// after — delegate to a free function or fully self-typed trait path
#![feature(fn_delegation)]
impl S {
    delegate * to Trait::method; // resolves with a self type attached
}
Defensive patterns

Strategy: validation

Validate before calling

// Self-propagating delegation requires `Self` to resolve in the
// enclosing item. Validate BEFORE relying on implicit Self propagation:
// 1. Confirm the delegate lives inside an `impl`/trait-impl with a receiver.
// 2. Prefer an explicit propagation kind instead of leaving it implicit.
//
// Safe pattern (explicit target, no implicit SelfTy inference):
//   impl T for Foo {
//       pub delegate::to(Bar::method); // Bar::method's Self == Foo
//   }
// Pre-commit grep to catch risky bare `delegate::to(...)` outside impls:
//   rg -n 'delegate::to\(' --type rust | rg -v 'impl '

Prevention

When it happens

Trigger: Triggered when lowering a `delegate`/`pub reuse` (RFC 3530 delegated items) item where `self_ty_propagation_kind` was set to `SelfTy(_)` but the path used to identify the delegated callee omitted its self-type argument (e.g. an inherent-method delegation that does not yet support a type-relative path — see the adjacent `unreachable!("until inherent methods are supported")` at line 416). The path produced a `QPath::Resolved(None, _)`, then `generics.self_ty_propagation_kind` is `Some(SelfTy(_))` at line 419, so the `.expect` at line 424 is hit.

Common situations: Developers experimenting with the nightly `fn_delegation` feature (e.g. `#![feature(fn_delegation)]`) hit this when combining delegation with method-call paths (`delegate * to self.method;`), delegating across impl blocks with unusual generic-self propagation, or using a rustc build where the delegation dir is mid-refactor. It is a known limitation area marked with `FIXME(fn_delegation)`.

Related errors


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