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
- 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.
- 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.
- Update to a newer nightly: the delegation dir changes frequently and the self-type-propagation invariant may already be fixed for your case.
- 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
- Only use self-propagating `delegate` inside impl blocks where `Self` is in scope
- Specify the propagation kind explicitly rather than relying on lowering-time inference
- Delegation + SelfTy propagation is nightly-only; pin the toolchain and syntax you tested against
- This is an ICE (panic in rustc), not a recoverable API error — file a bug with a minimized repro
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
- `Self` generic param is not found while expected
- must be at least one segment
- until inherent methods are supported
- arg must exist for infer
- shouldn't exist here
AI-assisted analysis of rust-lang/rust@22057b88b0 (2026-08-03).
Data as JSON: /data/errors/dad17b5fc54551c7.json.
Report an issue: GitHub.