Rollup merge of #150737 - smithdb3/fix-150576, r=chenyukang

diagnostics: make implicit Sized bounds explicit in E0277

When a trait parameter depends upon Sized, the error message only referred to the full trait itself and didn't mention Sized. This makes the failure to implement Sized explicit. It also notes when the Sized trait bound is explicit or implicit.

Fixes rust-lang/rust#150576
This commit is contained in:
Guillaume Gomez 2026-01-13 23:39:08 +01:00 committed by GitHub
commit 6c700ecd6a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 186 additions and 24 deletions

View file

@ -1391,25 +1391,45 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
// return early in the caller.
let mut label = || {
// Special case `Sized` as `old_pred` will be the trait itself instead of
// `Sized` when the trait bound is the source of the error.
let is_sized = match obligation.predicate.kind().skip_binder() {
ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred)) => {
self.tcx.is_lang_item(trait_pred.def_id(), LangItem::Sized)
}
_ => false,
};
let msg = format!(
"the trait bound `{}` is not satisfied",
self.tcx.short_string(old_pred, err.long_ty_path()),
);
let self_ty_str =
self.tcx.short_string(old_pred.self_ty().skip_binder(), err.long_ty_path());
let self_ty_str = self.tcx.short_string(old_pred.self_ty(), err.long_ty_path());
let trait_path = self
.tcx
.short_string(old_pred.print_modifiers_and_trait_path(), err.long_ty_path());
if has_custom_message {
let msg = if is_sized {
"the trait bound `Sized` is not satisfied".into()
} else {
msg
};
err.note(msg);
} else {
err.messages = vec![(rustc_errors::DiagMessage::from(msg), Style::NoStyle)];
}
err.span_label(
span,
format!("the trait `{trait_path}` is not implemented for `{self_ty_str}`"),
);
if is_sized {
err.span_label(
span,
format!("the trait `Sized` is not implemented for `{self_ty_str}`"),
);
} else {
err.span_label(
span,
format!("the trait `{trait_path}` is not implemented for `{self_ty_str}`"),
);
}
};
let mut sugg_prefixes = vec![];
@ -3578,10 +3598,27 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
"unsatisfied trait bound introduced in this `derive` macro",
);
} else if !data.span.is_dummy() && !data.span.overlaps(self_ty.span) {
spans.push_span_label(
data.span,
"unsatisfied trait bound introduced here",
);
// `Sized` may be an explicit or implicit trait bound. If it is
// implicit, mention it as such.
if let Some(pred) = predicate.as_trait_clause()
&& self.tcx.is_lang_item(pred.def_id(), LangItem::Sized)
&& self
.tcx
.generics_of(data.impl_or_alias_def_id)
.own_params
.iter()
.any(|param| self.tcx.def_span(param.def_id) == data.span)
{
spans.push_span_label(
data.span,
"unsatisfied trait bound implicitly introduced here",
);
} else {
spans.push_span_label(
data.span,
"unsatisfied trait bound introduced here",
);
}
}
err.span_note(spans, msg);
point_at_assoc_type_restriction(

View file

@ -88,7 +88,7 @@ note: required for `str` to implement `Foo<'_, '_, u8>`
LL | impl<'a, 'b, T, S> Foo<'a, 'b, S> for T {}
| - ^^^^^^^^^^^^^^ ^
| |
| unsatisfied trait bound introduced here
| unsatisfied trait bound implicitly introduced here
error: aborting due to 5 previous errors

View file

@ -88,7 +88,7 @@ note: required for `str` to implement `Foo<'?0, '?1, u8>`
LL | impl<'a, 'b, T, S> Foo<'a, 'b, S> for T {}
| - ^^^^^^^^^^^^^^ ^
| |
| unsatisfied trait bound introduced here
| unsatisfied trait bound implicitly introduced here
error: aborting due to 5 previous errors

View file

@ -0,0 +1,50 @@
use std::fmt::Display;
trait ImplicitTrait {
fn foo(&self);
}
trait ExplicitTrait {
fn foo(&self);
}
trait DisplayTrait {
fn foo(&self);
}
trait UnimplementedTrait {
fn foo(&self);
}
// Implicitly requires `T: Sized`.
impl<T> ImplicitTrait for T {
fn foo(&self) {}
}
// Explicitly requires `T: Sized`.
impl<T: Sized> ExplicitTrait for T {
fn foo(&self) {}
}
// Requires `T: Display`.
impl<T: Display> DisplayTrait for T {
fn foo(&self) {}
}
fn main() {
// `[u8]` does not implement `Sized`.
let x: &[u8] = &[];
ImplicitTrait::foo(x);
//~^ ERROR: the trait bound `[u8]: ImplicitTrait` is not satisfied [E0277]
ExplicitTrait::foo(x);
//~^ ERROR: the trait bound `[u8]: ExplicitTrait` is not satisfied [E0277]
// `UnimplementedTrait` has no implementations.
UnimplementedTrait::foo(x);
//~^ ERROR: the trait bound `[u8]: UnimplementedTrait` is not satisfied [E0277]
// `[u8; 0]` implements `Sized` but not `Display`.
let x: &[u8; 0] = &[];
DisplayTrait::foo(x);
//~^ ERROR: the trait bound `[u8; 0]: DisplayTrait` is not satisfied [E0277]
}

View file

@ -0,0 +1,77 @@
error[E0277]: the trait bound `[u8]: ImplicitTrait` is not satisfied
--> $DIR/E0277-4.rs:37:24
|
LL | ImplicitTrait::foo(x);
| ------------------ ^ the trait `Sized` is not implemented for `[u8]`
| |
| required by a bound introduced by this call
|
note: required for `[u8]` to implement `ImplicitTrait`
--> $DIR/E0277-4.rs:20:9
|
LL | impl<T> ImplicitTrait for T {
| - ^^^^^^^^^^^^^ ^
| |
| unsatisfied trait bound implicitly introduced here
help: consider borrowing here
|
LL | ImplicitTrait::foo(&x);
| +
LL | ImplicitTrait::foo(&mut x);
| ++++
error[E0277]: the trait bound `[u8]: ExplicitTrait` is not satisfied
--> $DIR/E0277-4.rs:39:24
|
LL | ExplicitTrait::foo(x);
| ------------------ ^ the trait `Sized` is not implemented for `[u8]`
| |
| required by a bound introduced by this call
|
note: required for `[u8]` to implement `ExplicitTrait`
--> $DIR/E0277-4.rs:25:16
|
LL | impl<T: Sized> ExplicitTrait for T {
| ----- ^^^^^^^^^^^^^ ^
| |
| unsatisfied trait bound introduced here
help: consider borrowing here
|
LL | ExplicitTrait::foo(&x);
| +
LL | ExplicitTrait::foo(&mut x);
| ++++
error[E0277]: the trait bound `[u8]: UnimplementedTrait` is not satisfied
--> $DIR/E0277-4.rs:43:29
|
LL | UnimplementedTrait::foo(x);
| ----------------------- ^ the trait `UnimplementedTrait` is not implemented for `[u8]`
| |
| required by a bound introduced by this call
|
help: this trait has no implementations, consider adding one
--> $DIR/E0277-4.rs:15:1
|
LL | trait UnimplementedTrait {
| ^^^^^^^^^^^^^^^^^^^^^^^^
error[E0277]: the trait bound `[u8; 0]: DisplayTrait` is not satisfied
--> $DIR/E0277-4.rs:48:23
|
LL | DisplayTrait::foo(x);
| ----------------- ^ the trait `std::fmt::Display` is not implemented for `[u8; 0]`
| |
| required by a bound introduced by this call
|
note: required for `[u8; 0]` to implement `DisplayTrait`
--> $DIR/E0277-4.rs:30:18
|
LL | impl<T: Display> DisplayTrait for T {
| ------- ^^^^^^^^^^^^ ^
| |
| unsatisfied trait bound introduced here
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0277`.

View file

@ -11,7 +11,7 @@ note: required for `GetNext<<<<... as Next>::Next as Next>::Next as Next>::Next>
LL | impl<T: Next> Next for GetNext<T> {
| - ^^^^ ^^^^^^^^^^
| |
| unsatisfied trait bound introduced here
| unsatisfied trait bound implicitly introduced here
= note: the full name for the type has been written to '$TEST_BUILD_DIR/issue-23122-2.long-type-$LONG_TYPE_HASH.txt'
= note: consider using `--verbose` to print the full type name to the console

View file

@ -17,11 +17,10 @@ error[E0277]: `[i32]` is not an iterator
--> $DIR/slice-issue-87994.rs:3:12
|
LL | for _ in v[1..] {
| ^^^^^^ the trait `IntoIterator` is not implemented for `[i32]`
| ^^^^^^ the trait `Sized` is not implemented for `[i32]`
|
= note: the trait bound `[i32]: IntoIterator` is not satisfied
= note: the trait bound `Sized` is not satisfied
= note: required for `[i32]` to implement `IntoIterator`
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
help: consider borrowing here
|
LL | for _ in &v[1..] {
@ -48,11 +47,10 @@ error[E0277]: `[K]` is not an iterator
--> $DIR/slice-issue-87994.rs:11:13
|
LL | for i2 in v2[1..] {
| ^^^^^^^ the trait `IntoIterator` is not implemented for `[K]`
| ^^^^^^^ the trait `Sized` is not implemented for `[K]`
|
= note: the trait bound `[K]: IntoIterator` is not satisfied
= note: the trait bound `Sized` is not satisfied
= note: required for `[K]` to implement `IntoIterator`
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
help: consider borrowing here
|
LL | for i2 in &v2[1..] {

View file

@ -2,9 +2,9 @@ error[E0277]: `dyn Iterator<Item = &'a mut u8>` is not an iterator
--> $DIR/dyn-iterator-deref-in-for-loop.rs:9:17
|
LL | for item in *things {
| ^^^^^^^ the trait `IntoIterator` is not implemented for `dyn Iterator<Item = &'a mut u8>`
| ^^^^^^^ the trait `Sized` is not implemented for `dyn Iterator<Item = &'a mut u8>`
|
= note: the trait bound `dyn Iterator<Item = &'a mut u8>: IntoIterator` is not satisfied
= note: the trait bound `Sized` is not satisfied
= note: required for `dyn Iterator<Item = &'a mut u8>` to implement `IntoIterator`
help: consider mutably borrowing here
|

View file

@ -2,9 +2,9 @@ error[E0277]: `dyn Iterator<Item = &'a mut u8>` is not an iterator
--> $DIR/dyn-iterator-deref-in-for-loop.rs:9:17
|
LL | for item in *things {
| ^^^^^^^ the trait `IntoIterator` is not implemented for `dyn Iterator<Item = &'a mut u8>`
| ^^^^^^^ the trait `Sized` is not implemented for `dyn Iterator<Item = &'a mut u8>`
|
= note: the trait bound `dyn Iterator<Item = &'a mut u8>: IntoIterator` is not satisfied
= note: the trait bound `Sized` is not satisfied
= note: required for `dyn Iterator<Item = &'a mut u8>` to implement `IntoIterator`
help: consider mutably borrowing here
|

View file

@ -11,7 +11,7 @@ note: required for `{integer}` to implement `Set<&[_]>`
LL | impl<'a, T, S> Set<&'a [T]> for S where
| - ^^^^^^^^^^^^ ^
| |
| unsatisfied trait bound introduced here
| unsatisfied trait bound implicitly introduced here
= note: 128 redundant requirements hidden
= note: required for `{integer}` to implement `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>`