Skip to content

hir_analysis: add missing sizedness bounds #142712

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions compiler/rustc_hir_analysis/src/collect/predicates_of.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
18 changes: 11 additions & 7 deletions compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
15 changes: 15 additions & 0 deletions tests/ui/sized-hierarchy/bound-on-assoc-type-projection.rs
Copy link
Member

@fmease fmease Jun 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you think it would be worth adding the following regression test, too? It's probably redundant but it would be smaller:

#![feature(sized_hierarchy)]

trait Trait {}

fn f<T: Trait + std::marker::PointeeSized>() {}

On master it yields the error

error[E0277]: the size for values of type `T` cannot be known
 --> t.rs:5:9
  |
5 | fn f<T: Trait + std::marker::PointeeSized>() {}
  |         ^^^^^ doesn't have a known size

Trait should still imply MetaSized here in f's bounds, right?

Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
//@ check-pass
#![crate_type = "lib"]
#![feature(sized_hierarchy)]

trait FalseDeref {
type Target: std::marker::PointeeSized;
}

trait Bar {}

fn foo<T: FalseDeref>()
where
T::Target: Bar,
{
}
5 changes: 1 addition & 4 deletions tests/ui/sized-hierarchy/default-supertrait.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,11 @@ fn with_pointeesized_supertrait<T: PointeeSized + PointeeSized_>() {
requires_pointeesized::<T>();
}

// `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<T: PointeeSized + Bare>() {
//~^ ERROR the size for values of type `T` cannot be known
requires_sized::<T>();
//~^ ERROR the size for values of type `T` cannot be known
requires_metasized::<T>();
//~^ ERROR the size for values of type `T` cannot be known
requires_pointeesized::<T>();
}

Expand Down
37 changes: 2 additions & 35 deletions tests/ui/sized-hierarchy/default-supertrait.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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<T: PointeeSized + Bare>() {
| ^^^^ 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<T: PointeeSized + Bare + std::marker::MetaSized>() {
| ++++++++++++++++++++++++

error[E0277]: the size for values of type `T` cannot be known at compilation time
--> $DIR/default-supertrait.rs:35:22
|
Expand Down Expand Up @@ -89,11 +73,10 @@ LL | fn with_pointeesized_supertrait<T: PointeeSized + PointeeSized_ + std::mark
| ++++++++++++++++++++++++

error[E0277]: the size for values of type `T` cannot be known at compilation time
--> $DIR/default-supertrait.rs:54:22
--> $DIR/default-supertrait.rs:52:22
|
LL | fn with_bare_trait<T: PointeeSized + Bare>() {
| - this type parameter needs to be `Sized`
LL |
LL | requires_sized::<T>();
| ^ doesn't have a size known at compile-time
|
Expand All @@ -103,23 +86,7 @@ note: required by a bound in `requires_sized`
LL | fn requires_sized<T: 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::<T>();
| ^ doesn't have a known size
|
note: required by a bound in `requires_metasized`
--> $DIR/default-supertrait.rs:25:26
|
LL | fn requires_metasized<T: MetaSized>() {}
| ^^^^^^^^^ required by this bound in `requires_metasized`
help: consider further restricting type parameter `T` with unstable trait `MetaSized`
|
LL | fn with_bare_trait<T: PointeeSized + Bare + std::marker::MetaSized>() {
| ++++++++++++++++++++++++

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`.
Original file line number Diff line number Diff line change
Expand Up @@ -19,23 +19,6 @@ error[E0275]: overflow evaluating the requirement `<() as A<T>>::Assoc: A<T>`
LL | Self::Assoc: A<T>,
| ^^^^

error[E0275]: overflow evaluating the requirement `<() as A<T>>::Assoc: MetaSized`
--> $DIR/normalize-param-env-2.rs:24:22
|
LL | Self::Assoc: A<T>,
| ^^^^
|
note: required by a bound in `A`
--> $DIR/normalize-param-env-2.rs:9:1
|
LL | / trait A<T> {
LL | | type Assoc;
LL | |
LL | | fn f()
... |
LL | | }
| |_^ required by this bound in `A`

error[E0275]: overflow evaluating the requirement `<() as A<T>>::Assoc well-formed`
--> $DIR/normalize-param-env-2.rs:24:22
|
Expand Down Expand Up @@ -63,6 +46,6 @@ LL | where
LL | Self::Assoc: A<T>,
| ^^^^ 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`.
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,6 @@ error[E0275]: overflow evaluating the requirement `<T as Trait>::Assoc: Trait`
LL | <T as Trait>::Assoc: Trait,
| ^^^^^

error[E0275]: overflow evaluating the requirement `<T as Trait>::Assoc: MetaSized`
--> $DIR/normalize-param-env-4.rs:19:26
|
LL | <T as Trait>::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`.
17 changes: 12 additions & 5 deletions tests/ui/traits/non_lifetime_binders/drop-impl-pred.no.stderr
Original file line number Diff line number Diff line change
@@ -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)]
| ^^^^^^^^^^^^^^^^^^^^
Expand All @@ -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> 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>(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<T> Drop for Bar<T>
| ^^^^^^ cannot infer type for struct `Bar<T>`

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`.
3 changes: 2 additions & 1 deletion tests/ui/traits/non_lifetime_binders/drop-impl-pred.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
//@ revisions: no yes
//@[yes] check-pass

// Issue 110557

Expand All @@ -15,6 +14,8 @@ struct Bar<T>(T) where T: Foo;
struct Bar<T>(T) where for<H> H: Foo;

impl<T> Drop for Bar<T>
//[yes]~^ ERROR type annotations needed
//[no]~^^ ERROR type annotations needed
where
for<H> H: Foo,
//[no]~^ ERROR `Drop` impl requires `H: Foo` but the struct it is implemented for does not
Expand Down
11 changes: 9 additions & 2 deletions tests/ui/traits/non_lifetime_binders/drop-impl-pred.yes.stderr
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
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)]
| ^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #108185 <https://github.com/rust-lang/rust/issues/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<T> Drop for Bar<T>
| ^^^^^^ cannot infer type for struct `Bar<T>`

error: aborting due to 1 previous error; 1 warning emitted

For more information about this error, try `rustc --explain E0282`.
Loading