Reject const projections behind trait aliases that mention Self

This fully rewords the diagnostic that was previously only emitted for assoc ty bindings.
That's because it incorrectly called trait aliases *type aliases* and didn't really
make it clear what the root cause is.

The added test used to ICE prior to this change.

I've double-checked that the preexisting test I've modified still ICEs in
nightly-2025-03-29.
This commit is contained in:
León Orell Valerian Liehr 2026-01-11 18:16:45 +01:00
parent eb0e3ac687
commit 618c15eb6c
No known key found for this signature in database
GPG key ID: D17A07215F68E713
9 changed files with 101 additions and 46 deletions

View file

@ -165,6 +165,11 @@ hir_analysis_drop_impl_reservation = reservation `Drop` impls are not supported
hir_analysis_duplicate_precise_capture = cannot capture parameter `{$name}` twice
.label = parameter captured again here
hir_analysis_dyn_trait_assoc_item_binding_mentions_self =
{$kind} binding in trait object type mentions `Self`
.label = contains a mention of `Self`
.binding_label = this binding mentions `Self`
hir_analysis_eii_with_generics =
`{$impl_name}` cannot have generic parameters other than lifetimes
.label = required by this attribute
@ -478,9 +483,6 @@ hir_analysis_self_in_impl_self =
`Self` is not valid in the self type of an impl block
.note = replace `Self` with a different type
hir_analysis_self_in_type_alias = `Self` is not allowed in type aliases
.label = `Self` is only available in impls, traits, and concrete type definitions
hir_analysis_self_ty_not_captured = `impl Trait` must mention the `Self` type of the trait in `use<...>`
.label = `Self` type parameter is implicitly captured by this `impl Trait`
.note = currently, all type parameters are required to be mentioned in the precise captures list

View file

@ -1632,11 +1632,14 @@ pub(crate) enum SupertraitItemShadowee {
}
#[derive(Diagnostic)]
#[diag(hir_analysis_self_in_type_alias, code = E0411)]
pub(crate) struct SelfInTypeAlias {
#[diag(hir_analysis_dyn_trait_assoc_item_binding_mentions_self)]
pub(crate) struct DynTraitAssocItemBindingMentionsSelf {
#[primary_span]
#[label]
pub span: Span,
pub kind: &'static str,
#[label(hir_analysis_binding_label)]
pub binding: Span,
}
#[derive(Diagnostic)]

View file

@ -22,7 +22,7 @@ use smallvec::{SmallVec, smallvec};
use tracing::{debug, instrument};
use super::HirTyLowerer;
use crate::errors::SelfInTypeAlias;
use crate::errors::DynTraitAssocItemBindingMentionsSelf;
use crate::hir_ty_lowering::{
GenericArgCountMismatch, ImpliedBoundsContext, OverlappingAsssocItemConstraints,
PredicateFilter, RegionInferReason,
@ -140,29 +140,29 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
// Map the projection bounds onto a key that makes it easy to remove redundant
// bounds that are constrained by supertraits of the principal trait.
//
// Also make sure we detect conflicting bounds from expanding a trait alias and
// also specifying it manually, like:
// ```
// type Alias = Trait<Assoc = i32>;
// let _: &dyn Alias<Assoc = u32> = /* ... */;
// ```
// Also make sure we detect conflicting bounds from expanding trait aliases.
//
// FIXME(#150936): Since the elaborated projection bounds also include the user-written ones
// and we're separately rejecting duplicate+conflicting bindings for trait
// object types when lowering assoc item bindings, there are basic cases
// where we're emitting two distinct but very similar diagnostics.
let mut projection_bounds = FxIndexMap::default();
for (proj, proj_span) in elaborated_projection_bounds {
let proj = proj.map_bound(|mut b| {
if let Some(term_ty) = &b.term.as_type() {
let references_self = term_ty.walk().any(|arg| arg == dummy_self.into());
if references_self {
// With trait alias and type alias combined, type resolver
// may not be able to catch all illegal `Self` usages (issue 139082)
let guar = self.dcx().emit_err(SelfInTypeAlias { span });
b.term = replace_dummy_self_with_error(tcx, b.term, guar);
}
}
b
});
let item_def_id = proj.item_def_id();
let proj = proj.map_bound(|mut proj| {
let references_self = proj.term.walk().any(|arg| arg == dummy_self.into());
if references_self {
let guar = self.dcx().emit_err(DynTraitAssocItemBindingMentionsSelf {
span,
kind: tcx.def_descr(item_def_id),
binding: proj_span,
});
proj.term = replace_dummy_self_with_error(tcx, proj.term, guar);
}
proj
});
let key = (
item_def_id,
tcx.anonymize_bound_vars(

View file

@ -0,0 +1,22 @@
// Check that we reject const projections behind trait aliases that mention `Self`.
// The code below is pretty artifical and contains a type mismatch anyway but we still need to
// reject it & lower the `Self` ty param to a `{type error}` to avoid ICEs down the line.
//
// The author of the trait object type can't fix this unlike the supertrait bound
// equivalent where they just need to explicitly specify the assoc const.
#![feature(min_generic_const_args, trait_alias)]
#![expect(incomplete_features)]
trait Trait {
#[type_const]
const Y: i32;
}
struct Hold<T: ?Sized>(T);
trait Bound = Trait<Y = { Hold::<Self> }>;
fn main() {
let _: dyn Bound; //~ ERROR associated constant binding in trait object type mentions `Self`
}

View file

@ -0,0 +1,11 @@
error: associated constant binding in trait object type mentions `Self`
--> $DIR/dyn-compat-const-projection-behind-trait-alias-mentions-self.rs:21:12
|
LL | trait Bound = Trait<Y = { Hold::<Self> }>;
| -------------------- this binding mentions `Self`
...
LL | let _: dyn Bound;
| ^^^^^^^^^ contains a mention of `Self`
error: aborting due to 1 previous error

View file

@ -1,12 +0,0 @@
#![feature(trait_alias)]
trait B = Fn() -> Self;
type D = &'static dyn B;
//~^ ERROR E0411
fn a() -> D {
unreachable!();
}
fn main() {
_ = a();
}

View file

@ -1,9 +0,0 @@
error[E0411]: `Self` is not allowed in type aliases
--> $DIR/trait-alias-self-projection.rs:3:19
|
LL | type D = &'static dyn B;
| ^^^^^ `Self` is only available in impls, traits, and concrete type definitions
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0411`.

View file

@ -0,0 +1,18 @@
// Check that we reject type projections behind trait aliases that mention `Self`.
//
// The author of the trait object type can't fix this unlike the supertrait bound
// equivalent where they just need to explicitly specify the assoc type.
// issue: <https://github.com/rust-lang/rust/issues/139082>
#![feature(trait_alias)]
trait F = Fn() -> Self;
trait G = H<T = Self>;
trait H { type T: ?Sized; }
fn main() {
let _: dyn F; //~ ERROR associated type binding in trait object type mentions `Self`
let _: dyn G; //~ ERROR associated type binding in trait object type mentions `Self`
}

View file

@ -0,0 +1,20 @@
error: associated type binding in trait object type mentions `Self`
--> $DIR/type-projection-behind-trait-alias-mentions-self.rs:16:12
|
LL | trait F = Fn() -> Self;
| ---- this binding mentions `Self`
...
LL | let _: dyn F;
| ^^^^^ contains a mention of `Self`
error: associated type binding in trait object type mentions `Self`
--> $DIR/type-projection-behind-trait-alias-mentions-self.rs:17:12
|
LL | trait G = H<T = Self>;
| -------- this binding mentions `Self`
...
LL | let _: dyn G;
| ^^^^^ contains a mention of `Self`
error: aborting due to 2 previous errors