From 618c15eb6ce195c8ec19f4501addb728eeb81a95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Sun, 11 Jan 2026 18:16:45 +0100 Subject: [PATCH] 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. --- compiler/rustc_hir_analysis/messages.ftl | 8 ++-- compiler/rustc_hir_analysis/src/errors.rs | 7 +++- .../src/hir_ty_lowering/dyn_trait.rs | 40 +++++++++---------- ...ection-behind-trait-alias-mentions-self.rs | 22 ++++++++++ ...on-behind-trait-alias-mentions-self.stderr | 11 +++++ .../trait-alias-self-projection.rs | 12 ------ .../trait-alias-self-projection.stderr | 9 ----- ...ection-behind-trait-alias-mentions-self.rs | 18 +++++++++ ...on-behind-trait-alias-mentions-self.stderr | 20 ++++++++++ 9 files changed, 101 insertions(+), 46 deletions(-) create mode 100644 tests/ui/const-generics/associated-const-bindings/dyn-compat-const-projection-behind-trait-alias-mentions-self.rs create mode 100644 tests/ui/const-generics/associated-const-bindings/dyn-compat-const-projection-behind-trait-alias-mentions-self.stderr delete mode 100644 tests/ui/dyn-compatibility/trait-alias-self-projection.rs delete mode 100644 tests/ui/dyn-compatibility/trait-alias-self-projection.stderr create mode 100644 tests/ui/dyn-compatibility/type-projection-behind-trait-alias-mentions-self.rs create mode 100644 tests/ui/dyn-compatibility/type-projection-behind-trait-alias-mentions-self.stderr diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index 9942cddcb3cd..d9f8eba65c4a 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -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 diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index e513f053d336..2a77d0b997e2 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -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)] diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs index 40a23a1f51f1..c1cbc44953ad 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs @@ -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; - // let _: &dyn Alias = /* ... */; - // ``` + // 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( diff --git a/tests/ui/const-generics/associated-const-bindings/dyn-compat-const-projection-behind-trait-alias-mentions-self.rs b/tests/ui/const-generics/associated-const-bindings/dyn-compat-const-projection-behind-trait-alias-mentions-self.rs new file mode 100644 index 000000000000..93036fbc01a8 --- /dev/null +++ b/tests/ui/const-generics/associated-const-bindings/dyn-compat-const-projection-behind-trait-alias-mentions-self.rs @@ -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); + +trait Bound = Trait }>; + +fn main() { + let _: dyn Bound; //~ ERROR associated constant binding in trait object type mentions `Self` +} diff --git a/tests/ui/const-generics/associated-const-bindings/dyn-compat-const-projection-behind-trait-alias-mentions-self.stderr b/tests/ui/const-generics/associated-const-bindings/dyn-compat-const-projection-behind-trait-alias-mentions-self.stderr new file mode 100644 index 000000000000..109cb7602dcd --- /dev/null +++ b/tests/ui/const-generics/associated-const-bindings/dyn-compat-const-projection-behind-trait-alias-mentions-self.stderr @@ -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 }>; + | -------------------- this binding mentions `Self` +... +LL | let _: dyn Bound; + | ^^^^^^^^^ contains a mention of `Self` + +error: aborting due to 1 previous error + diff --git a/tests/ui/dyn-compatibility/trait-alias-self-projection.rs b/tests/ui/dyn-compatibility/trait-alias-self-projection.rs deleted file mode 100644 index 0badb738809e..000000000000 --- a/tests/ui/dyn-compatibility/trait-alias-self-projection.rs +++ /dev/null @@ -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(); -} diff --git a/tests/ui/dyn-compatibility/trait-alias-self-projection.stderr b/tests/ui/dyn-compatibility/trait-alias-self-projection.stderr deleted file mode 100644 index dccee02e9cd1..000000000000 --- a/tests/ui/dyn-compatibility/trait-alias-self-projection.stderr +++ /dev/null @@ -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`. diff --git a/tests/ui/dyn-compatibility/type-projection-behind-trait-alias-mentions-self.rs b/tests/ui/dyn-compatibility/type-projection-behind-trait-alias-mentions-self.rs new file mode 100644 index 000000000000..9122ddaaff7b --- /dev/null +++ b/tests/ui/dyn-compatibility/type-projection-behind-trait-alias-mentions-self.rs @@ -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: + +#![feature(trait_alias)] + +trait F = Fn() -> Self; + +trait G = H; +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` +} diff --git a/tests/ui/dyn-compatibility/type-projection-behind-trait-alias-mentions-self.stderr b/tests/ui/dyn-compatibility/type-projection-behind-trait-alias-mentions-self.stderr new file mode 100644 index 000000000000..0b7fb55a908c --- /dev/null +++ b/tests/ui/dyn-compatibility/type-projection-behind-trait-alias-mentions-self.stderr @@ -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; + | -------- this binding mentions `Self` +... +LL | let _: dyn G; + | ^^^^^ contains a mention of `Self` + +error: aborting due to 2 previous errors +