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:
parent
eb0e3ac687
commit
618c15eb6c
9 changed files with 101 additions and 46 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)]
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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`
|
||||
}
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
|
@ -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`.
|
||||
|
|
@ -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`
|
||||
}
|
||||
|
|
@ -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
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue