From 60d504434bf08e7b7e892c47a5d1322cb8a20f5f Mon Sep 17 00:00:00 2001 From: David Wood Date: Wed, 18 Jun 2025 17:03:15 +0000 Subject: [PATCH] hir_analysis: add missing sizedness bounds Default sizedness bounds were not being added to `explicit_super_predicates_of` and `explicit_implied_predicates_of` which meant that a trait bound added to a associated type projection would be missing the implied predicate of the default sizedness supertrait of that trait. An unexpected consequence of this change was that the check for multiple principals was now finding an additional `MetaSized` principal when eagerly expanding trait aliases - this required modifying lowering to no longer add default bounds to trait aliases. --- .../src/collect/predicates_of.rs | 8 ++++ .../src/hir_ty_lowering/bounds.rs | 18 +++++---- .../bound-on-assoc-type-projection.rs | 15 ++++++++ .../ui/sized-hierarchy/default-supertrait.rs | 5 +-- .../sized-hierarchy/default-supertrait.stderr | 37 +------------------ .../normalize/normalize-param-env-2.stderr | 19 +--------- .../normalize-param-env-4.next.stderr | 16 +------- .../drop-impl-pred.no.stderr | 17 ++++++--- .../non_lifetime_binders/drop-impl-pred.rs | 3 +- .../drop-impl-pred.yes.stderr | 11 +++++- 10 files changed, 62 insertions(+), 87 deletions(-) create mode 100644 tests/ui/sized-hierarchy/bound-on-assoc-type-projection.rs diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index c337765c5fec3..c6977135521fc 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -658,6 +658,14 @@ pub(super) fn implied_predicates_with_filter<'tcx>( | PredicateFilter::SelfOnly | PredicateFilter::SelfTraitThatDefines(_) | PredicateFilter::SelfAndAssociatedTypeBounds => { + icx.lowerer().add_sizedness_bounds( + &mut bounds, + self_param_ty, + superbounds, + None, + Some(trait_def_id), + item.span, + ); icx.lowerer().add_default_super_traits( trait_def_id, &mut bounds, diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs index ea1dfdfd80619..3a22598d0af3d 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs @@ -215,14 +215,18 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { && !collected.meta_sized.any() && !collected.pointee_sized.any() { - // `?Sized` is equivalent to `MetaSized` (but only add the bound if there aren't any - // other explicit ones) - this can happen for trait aliases as well as bounds. - add_trait_bound(tcx, bounds, self_ty, meta_sized_did, span); - } else if !collected.any() { - if trait_did.is_some() { - // If there are no explicit sizedness bounds on a trait then add a default - // `MetaSized` supertrait. + if trait_did.map(|did| !tcx.is_trait_alias(did.to_def_id())).unwrap_or(true) { + // `?Sized` is equivalent to `MetaSized` (but only add the bound if there aren't any + // other explicit ones and it isn't a trait alias). add_trait_bound(tcx, bounds, self_ty, meta_sized_did, span); + } + } else if !collected.any() { + if let Some(trait_did) = trait_did { + if !tcx.is_trait_alias(trait_did.to_def_id()) { + // If there are no explicit sizedness bounds on a trait and it is not a trait + // alias then add a default `MetaSized` supertrait. + add_trait_bound(tcx, bounds, self_ty, meta_sized_did, span); + } } else { // If there are no explicit sizedness bounds on a parameter then add a default // `Sized` bound. diff --git a/tests/ui/sized-hierarchy/bound-on-assoc-type-projection.rs b/tests/ui/sized-hierarchy/bound-on-assoc-type-projection.rs new file mode 100644 index 0000000000000..ddd3964f4180b --- /dev/null +++ b/tests/ui/sized-hierarchy/bound-on-assoc-type-projection.rs @@ -0,0 +1,15 @@ +//@ check-pass +#![crate_type = "lib"] +#![feature(sized_hierarchy)] + +trait FalseDeref { + type Target: std::marker::PointeeSized; +} + +trait Bar {} + +fn foo() +where + T::Target: Bar, +{ +} diff --git a/tests/ui/sized-hierarchy/default-supertrait.rs b/tests/ui/sized-hierarchy/default-supertrait.rs index b25acf9e6ea4f..b929a4a242439 100644 --- a/tests/ui/sized-hierarchy/default-supertrait.rs +++ b/tests/ui/sized-hierarchy/default-supertrait.rs @@ -47,14 +47,11 @@ fn with_pointeesized_supertrait() { requires_pointeesized::(); } -// `T` won't inherit the `const MetaSized` implicit supertrait of `Bare`, so there is an error on -// the bound, which is expected. +// `T` inherits the `const MetaSized` implicit supertrait of `Bare`. fn with_bare_trait() { -//~^ ERROR the size for values of type `T` cannot be known requires_sized::(); //~^ ERROR the size for values of type `T` cannot be known requires_metasized::(); - //~^ ERROR the size for values of type `T` cannot be known requires_pointeesized::(); } diff --git a/tests/ui/sized-hierarchy/default-supertrait.stderr b/tests/ui/sized-hierarchy/default-supertrait.stderr index de23936b900bc..fe3f8339eec54 100644 --- a/tests/ui/sized-hierarchy/default-supertrait.stderr +++ b/tests/ui/sized-hierarchy/default-supertrait.stderr @@ -28,22 +28,6 @@ LL | trait NegPointeeSized: ?PointeeSized { } = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0277]: the size for values of type `T` cannot be known - --> $DIR/default-supertrait.rs:52:38 - | -LL | fn with_bare_trait() { - | ^^^^ doesn't have a known size - | -note: required by a bound in `Bare` - --> $DIR/default-supertrait.rs:22:1 - | -LL | trait Bare {} - | ^^^^^^^^^^^^^ required by this bound in `Bare` -help: consider further restricting type parameter `T` with unstable trait `MetaSized` - | -LL | fn with_bare_trait() { - | ++++++++++++++++++++++++ - error[E0277]: the size for values of type `T` cannot be known at compilation time --> $DIR/default-supertrait.rs:35:22 | @@ -89,11 +73,10 @@ LL | fn with_pointeesized_supertrait $DIR/default-supertrait.rs:54:22 + --> $DIR/default-supertrait.rs:52:22 | LL | fn with_bare_trait() { | - this type parameter needs to be `Sized` -LL | LL | requires_sized::(); | ^ doesn't have a size known at compile-time | @@ -103,23 +86,7 @@ note: required by a bound in `requires_sized` LL | fn requires_sized() {} | ^^^^^ required by this bound in `requires_sized` -error[E0277]: the size for values of type `T` cannot be known - --> $DIR/default-supertrait.rs:56:26 - | -LL | requires_metasized::(); - | ^ doesn't have a known size - | -note: required by a bound in `requires_metasized` - --> $DIR/default-supertrait.rs:25:26 - | -LL | fn requires_metasized() {} - | ^^^^^^^^^ required by this bound in `requires_metasized` -help: consider further restricting type parameter `T` with unstable trait `MetaSized` - | -LL | fn with_bare_trait() { - | ++++++++++++++++++++++++ - -error: aborting due to 9 previous errors +error: aborting due to 7 previous errors Some errors have detailed explanations: E0277, E0658. For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/next-solver/normalize/normalize-param-env-2.stderr b/tests/ui/traits/next-solver/normalize/normalize-param-env-2.stderr index 8d8909625ffc8..d179c80596238 100644 --- a/tests/ui/traits/next-solver/normalize/normalize-param-env-2.stderr +++ b/tests/ui/traits/next-solver/normalize/normalize-param-env-2.stderr @@ -19,23 +19,6 @@ error[E0275]: overflow evaluating the requirement `<() as A>::Assoc: A` LL | Self::Assoc: A, | ^^^^ -error[E0275]: overflow evaluating the requirement `<() as A>::Assoc: MetaSized` - --> $DIR/normalize-param-env-2.rs:24:22 - | -LL | Self::Assoc: A, - | ^^^^ - | -note: required by a bound in `A` - --> $DIR/normalize-param-env-2.rs:9:1 - | -LL | / trait A { -LL | | type Assoc; -LL | | -LL | | fn f() -... | -LL | | } - | |_^ required by this bound in `A` - error[E0275]: overflow evaluating the requirement `<() as A>::Assoc well-formed` --> $DIR/normalize-param-env-2.rs:24:22 | @@ -63,6 +46,6 @@ LL | where LL | Self::Assoc: A, | ^^^^ required by this bound in `A::f` -error: aborting due to 6 previous errors +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/next-solver/normalize/normalize-param-env-4.next.stderr b/tests/ui/traits/next-solver/normalize/normalize-param-env-4.next.stderr index 9f7f74f94664b..f5fd9ce9864ce 100644 --- a/tests/ui/traits/next-solver/normalize/normalize-param-env-4.next.stderr +++ b/tests/ui/traits/next-solver/normalize/normalize-param-env-4.next.stderr @@ -4,20 +4,6 @@ error[E0275]: overflow evaluating the requirement `::Assoc: Trait` LL | ::Assoc: Trait, | ^^^^^ -error[E0275]: overflow evaluating the requirement `::Assoc: MetaSized` - --> $DIR/normalize-param-env-4.rs:19:26 - | -LL | ::Assoc: Trait, - | ^^^^^ - | -note: required by a bound in `Trait` - --> $DIR/normalize-param-env-4.rs:7:1 - | -LL | / trait Trait { -LL | | type Assoc; -LL | | } - | |_^ required by this bound in `Trait` - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/non_lifetime_binders/drop-impl-pred.no.stderr b/tests/ui/traits/non_lifetime_binders/drop-impl-pred.no.stderr index 1f13207e33ca3..caba33499120c 100644 --- a/tests/ui/traits/non_lifetime_binders/drop-impl-pred.no.stderr +++ b/tests/ui/traits/non_lifetime_binders/drop-impl-pred.no.stderr @@ -1,5 +1,5 @@ warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/drop-impl-pred.rs:6:12 + --> $DIR/drop-impl-pred.rs:5:12 | LL | #![feature(non_lifetime_binders)] | ^^^^^^^^^^^^^^^^^^^^ @@ -8,17 +8,24 @@ LL | #![feature(non_lifetime_binders)] = note: `#[warn(incomplete_features)]` on by default error[E0367]: `Drop` impl requires `H: Foo` but the struct it is implemented for does not - --> $DIR/drop-impl-pred.rs:19:15 + --> $DIR/drop-impl-pred.rs:20:15 | LL | for H: Foo, | ^^^ | note: the implementor must specify the same requirement - --> $DIR/drop-impl-pred.rs:12:1 + --> $DIR/drop-impl-pred.rs:11:1 | LL | struct Bar(T) where T: Foo; | ^^^^^^^^^^^^^ -error: aborting due to 1 previous error; 1 warning emitted +error[E0282]: type annotations needed + --> $DIR/drop-impl-pred.rs:16:18 + | +LL | impl Drop for Bar + | ^^^^^^ cannot infer type for struct `Bar` + +error: aborting due to 2 previous errors; 1 warning emitted -For more information about this error, try `rustc --explain E0367`. +Some errors have detailed explanations: E0282, E0367. +For more information about an error, try `rustc --explain E0282`. diff --git a/tests/ui/traits/non_lifetime_binders/drop-impl-pred.rs b/tests/ui/traits/non_lifetime_binders/drop-impl-pred.rs index db8f3de2149d4..579fc82f2dfcc 100644 --- a/tests/ui/traits/non_lifetime_binders/drop-impl-pred.rs +++ b/tests/ui/traits/non_lifetime_binders/drop-impl-pred.rs @@ -1,5 +1,4 @@ //@ revisions: no yes -//@[yes] check-pass // Issue 110557 @@ -15,6 +14,8 @@ struct Bar(T) where T: Foo; struct Bar(T) where for H: Foo; impl Drop for Bar +//[yes]~^ ERROR type annotations needed +//[no]~^^ ERROR type annotations needed where for H: Foo, //[no]~^ ERROR `Drop` impl requires `H: Foo` but the struct it is implemented for does not diff --git a/tests/ui/traits/non_lifetime_binders/drop-impl-pred.yes.stderr b/tests/ui/traits/non_lifetime_binders/drop-impl-pred.yes.stderr index 165cf2ee13da8..9f2476cfb212d 100644 --- a/tests/ui/traits/non_lifetime_binders/drop-impl-pred.yes.stderr +++ b/tests/ui/traits/non_lifetime_binders/drop-impl-pred.yes.stderr @@ -1,5 +1,5 @@ warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/drop-impl-pred.rs:6:12 + --> $DIR/drop-impl-pred.rs:5:12 | LL | #![feature(non_lifetime_binders)] | ^^^^^^^^^^^^^^^^^^^^ @@ -7,5 +7,12 @@ LL | #![feature(non_lifetime_binders)] = note: see issue #108185 for more information = note: `#[warn(incomplete_features)]` on by default -warning: 1 warning emitted +error[E0282]: type annotations needed + --> $DIR/drop-impl-pred.rs:16:18 + | +LL | impl Drop for Bar + | ^^^^^^ cannot infer type for struct `Bar` + +error: aborting due to 1 previous error; 1 warning emitted +For more information about this error, try `rustc --explain E0282`.