Skip to content

Commit 7ac2dea

Browse files
committed
On E0277 be clearer about implicit Sized bounds on type params and assoc types
``` error[E0277]: the size for values of type `[i32]` cannot be known at compilation time --> f100.rs:2:33 | 2 | let _ = std::mem::size_of::<[i32]>(); | ^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `[i32]` note: required by an implicit `Sized` bound in `std::mem::size_of` --> /home/gh-estebank/rust/library/core/src/mem/mod.rs:312:22 | 312 | pub const fn size_of<T>() -> usize { | ^ required by the implicit `Sized` requirement on this bound in `size_of` ``` Fix #120178.
1 parent e7bbe8c commit 7ac2dea

File tree

48 files changed

+232
-223
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+232
-223
lines changed

compiler/rustc_hir_analysis/src/astconv/bounds.rs

+11-3
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
2828
let tcx = self.tcx();
2929
let sized_def_id = tcx.lang_items().sized_trait();
3030
let mut seen_negative_sized_bound = false;
31+
let mut seen_positive_sized_bound = false;
3132

3233
// Try to find an unbound in bounds.
3334
let mut unbounds: SmallVec<[_; 1]> = SmallVec::new();
@@ -45,6 +46,13 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
4546
seen_negative_sized_bound = true;
4647
}
4748
}
49+
hir::TraitBoundModifier::None => {
50+
if let Some(sized_def_id) = sized_def_id
51+
&& ptr.trait_ref.path.res == Res::Def(DefKind::Trait, sized_def_id)
52+
{
53+
seen_positive_sized_bound = true;
54+
}
55+
}
4856
_ => {}
4957
}
5058
}
@@ -82,11 +90,11 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
8290
);
8391
}
8492

85-
if seen_sized_unbound || seen_negative_sized_bound {
86-
// There was in fact a `?Sized` or `!Sized` bound;
93+
if seen_sized_unbound || seen_negative_sized_bound || seen_positive_sized_bound {
94+
// There was in fact a `?Sized`, `!Sized` or explicit `Sized` bound;
8795
// we don't need to do anything.
8896
} else if sized_def_id.is_some() {
89-
// There was no `?Sized` or `!Sized` bound;
97+
// There was no `?Sized`, `!Sized` or explicit `Sized` bound;
9098
// add `Sized` if it's available.
9199
bounds.push_sized(tcx, self_ty, span);
92100
}

compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs

+90-69
Original file line numberDiff line numberDiff line change
@@ -3011,35 +3011,44 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
30113011
);
30123012
}
30133013
}
3014-
let descr = format!("required by a bound in `{item_name}`");
3015-
if span.is_visible(sm) {
3016-
let msg = format!("required by this bound in `{short_item_name}`");
3017-
multispan.push_span_label(span, msg);
3018-
err.span_note(multispan, descr);
3019-
if let ty::PredicateKind::Clause(clause) = predicate.kind().skip_binder()
3020-
&& let ty::ClauseKind::Trait(trait_pred) = clause
3021-
{
3022-
let def_id = trait_pred.def_id();
3023-
let visible_item = if let Some(local) = def_id.as_local() {
3024-
// Check for local traits being reachable.
3025-
let vis = &tcx.resolutions(()).effective_visibilities;
3026-
// Account for non-`pub` traits in the root of the local crate.
3027-
let is_locally_reachable = tcx.parent(def_id).is_crate_root();
3028-
vis.is_reachable(local) || is_locally_reachable
3029-
} else {
3030-
// Check for foreign traits being reachable.
3031-
tcx.visible_parent_map(()).get(&def_id).is_some()
3032-
};
3033-
if Some(def_id) == tcx.lang_items().sized_trait()
3034-
&& let Some(hir::Node::TraitItem(hir::TraitItem {
3035-
ident,
3036-
kind: hir::TraitItemKind::Type(bounds, None),
3037-
..
3038-
})) = tcx.hir().get_if_local(item_def_id)
3039-
// Do not suggest relaxing if there is an explicit `Sized` obligation.
3040-
&& !bounds.iter()
3041-
.filter_map(|bound| bound.trait_ref())
3042-
.any(|tr| tr.trait_def_id() == tcx.lang_items().sized_trait())
3014+
let mut a = "a";
3015+
let mut this = "this";
3016+
let mut note = None;
3017+
let mut help = None;
3018+
if let ty::PredicateKind::Clause(clause) = predicate.kind().skip_binder()
3019+
&& let ty::ClauseKind::Trait(trait_pred) = clause
3020+
{
3021+
let def_id = trait_pred.def_id();
3022+
let visible_item = if let Some(local) = def_id.as_local() {
3023+
// Check for local traits being reachable.
3024+
let vis = &tcx.resolutions(()).effective_visibilities;
3025+
// Account for non-`pub` traits in the root of the local crate.
3026+
let is_locally_reachable = tcx.parent(def_id).is_crate_root();
3027+
vis.is_reachable(local) || is_locally_reachable
3028+
} else {
3029+
// Check for foreign traits being reachable.
3030+
tcx.visible_parent_map(()).get(&def_id).is_some()
3031+
};
3032+
if Some(def_id) == tcx.lang_items().sized_trait() {
3033+
// Check if this is an implicit bound, even in foreign crates.
3034+
if tcx
3035+
.generics_of(item_def_id)
3036+
.params
3037+
.iter()
3038+
.any(|param| tcx.def_span(param.def_id) == span)
3039+
{
3040+
a = "an implicit `Sized`";
3041+
this = "the implicit `Sized` requirement on this";
3042+
}
3043+
if let Some(hir::Node::TraitItem(hir::TraitItem {
3044+
ident,
3045+
kind: hir::TraitItemKind::Type(bounds, None),
3046+
..
3047+
})) = tcx.hir().get_if_local(item_def_id)
3048+
// Do not suggest relaxing if there is an explicit `Sized` obligation.
3049+
&& !bounds.iter()
3050+
.filter_map(|bound| bound.trait_ref())
3051+
.any(|tr| tr.trait_def_id() == tcx.lang_items().sized_trait())
30433052
{
30443053
let (span, separator) = if let [.., last] = bounds {
30453054
(last.span().shrink_to_hi(), " +")
@@ -3053,52 +3062,64 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
30533062
Applicability::MachineApplicable,
30543063
);
30553064
}
3056-
if let DefKind::Trait = tcx.def_kind(item_def_id)
3057-
&& !visible_item
3058-
{
3059-
err.note(format!(
3060-
"`{short_item_name}` is a \"sealed trait\", because to implement \
3061-
it you also need to implement `{}`, which is not accessible; \
3062-
this is usually done to force you to use one of the provided \
3063-
types that already implement it",
3064-
with_no_trimmed_paths!(tcx.def_path_str(def_id)),
3065-
));
3066-
let impls_of = tcx.trait_impls_of(def_id);
3067-
let impls = impls_of
3068-
.non_blanket_impls()
3069-
.values()
3070-
.flatten()
3071-
.chain(impls_of.blanket_impls().iter())
3065+
}
3066+
if let DefKind::Trait = tcx.def_kind(item_def_id)
3067+
&& !visible_item
3068+
{
3069+
note = Some(format!(
3070+
"`{short_item_name}` is a \"sealed trait\", because to implement it \
3071+
you also need to implement `{}`, which is not accessible; this is \
3072+
usually done to force you to use one of the provided types that \
3073+
already implement it",
3074+
with_no_trimmed_paths!(tcx.def_path_str(def_id)),
3075+
));
3076+
let impls_of = tcx.trait_impls_of(def_id);
3077+
let impls = impls_of
3078+
.non_blanket_impls()
3079+
.values()
3080+
.flatten()
3081+
.chain(impls_of.blanket_impls().iter())
3082+
.collect::<Vec<_>>();
3083+
if !impls.is_empty() {
3084+
let len = impls.len();
3085+
let mut types = impls
3086+
.iter()
3087+
.map(|t| {
3088+
with_no_trimmed_paths!(format!(
3089+
" {}",
3090+
tcx.type_of(*t).instantiate_identity(),
3091+
))
3092+
})
30723093
.collect::<Vec<_>>();
3073-
if !impls.is_empty() {
3074-
let len = impls.len();
3075-
let mut types = impls
3076-
.iter()
3077-
.map(|t| {
3078-
with_no_trimmed_paths!(format!(
3079-
" {}",
3080-
tcx.type_of(*t).instantiate_identity(),
3081-
))
3082-
})
3083-
.collect::<Vec<_>>();
3084-
let post = if types.len() > 9 {
3085-
types.truncate(8);
3086-
format!("\nand {} others", len - 8)
3087-
} else {
3088-
String::new()
3089-
};
3090-
err.help(format!(
3091-
"the following type{} implement{} the trait:\n{}{post}",
3092-
pluralize!(len),
3093-
if len == 1 { "s" } else { "" },
3094-
types.join("\n"),
3095-
));
3096-
}
3094+
let post = if types.len() > 9 {
3095+
types.truncate(8);
3096+
format!("\nand {} others", len - 8)
3097+
} else {
3098+
String::new()
3099+
};
3100+
help = Some(format!(
3101+
"the following type{} implement{} the trait:\n{}{post}",
3102+
pluralize!(len),
3103+
if len == 1 { "s" } else { "" },
3104+
types.join("\n"),
3105+
));
30973106
}
30983107
}
3108+
};
3109+
let descr = format!("required by {a} bound in `{item_name}`");
3110+
if span.is_visible(sm) {
3111+
let msg = format!("required by {this} bound in `{short_item_name}`");
3112+
multispan.push_span_label(span, msg);
3113+
err.span_note(multispan, descr);
30993114
} else {
31003115
err.span_note(tcx.def_span(item_def_id), descr);
31013116
}
3117+
if let Some(note) = note {
3118+
err.note(note);
3119+
}
3120+
if let Some(help) = help {
3121+
err.help(help);
3122+
}
31023123
}
31033124
ObligationCauseCode::Coercion { source, target } => {
31043125
let mut file = None;

tests/ui/associated-types/defaults-wf.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ LL | type Ty = Vec<[u8]>;
55
| ^^^^^^^^^ doesn't have a size known at compile-time
66
|
77
= help: the trait `Sized` is not implemented for `[u8]`
8-
note: required by a bound in `Vec`
8+
note: required by an implicit `Sized` bound in `Vec`
99
--> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
1010

1111
error: aborting due to 1 previous error

tests/ui/associated-types/issue-20005.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@ error[E0277]: the size for values of type `Self` cannot be known at compilation
44
LL | ) -> <Dst as From<Self>>::Result where Dst: From<Self> {
55
| ^^^^^^^^^^ doesn't have a size known at compile-time
66
|
7-
note: required by a bound in `From`
7+
note: required by an implicit `Sized` bound in `From`
88
--> $DIR/issue-20005.rs:1:12
99
|
1010
LL | trait From<Src> {
11-
| ^^^ required by this bound in `From`
11+
| ^^^ required by the implicit `Sized` requirement on this bound in `From`
1212
help: consider further restricting `Self`
1313
|
1414
LL | ) -> <Dst as From<Self>>::Result where Dst: From<Self>, Self: Sized {

tests/ui/associated-types/trait-with-supertraits-needing-sized-self.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ error[E0277]: the size for values of type `Self` cannot be known at compilation
44
LL | trait ArithmeticOps: Add<Output=Self> + Sub<Output=Self> + Mul<Output=Self> + Div<Output=Self> {}
55
| ^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
66
|
7-
note: required by a bound in `Add`
7+
note: required by an implicit `Sized` bound in `Add`
88
--> $SRC_DIR/core/src/ops/arith.rs:LL:COL
99
help: consider further restricting `Self`
1010
|

tests/ui/closures/issue-111932.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ LL | println!("{:?}", foo);
1717
| required by a bound introduced by this call
1818
|
1919
= help: the trait `Sized` is not implemented for `dyn Foo`
20-
note: required by a bound in `core::fmt::rt::Argument::<'a>::new_debug`
20+
note: required by an implicit `Sized` bound in `core::fmt::rt::Argument::<'a>::new_debug`
2121
--> $SRC_DIR/core/src/fmt/rt.rs:LL:COL
2222
= note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
2323

tests/ui/coroutine/sized-yield.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ LL | Pin::new(&mut gen).resume(());
1818
| ^^^^^^ doesn't have a size known at compile-time
1919
|
2020
= help: the trait `Sized` is not implemented for `str`
21-
note: required by a bound in `CoroutineState`
21+
note: required by an implicit `Sized` bound in `CoroutineState`
2222
--> $SRC_DIR/core/src/ops/coroutine.rs:LL:COL
2323

2424
error: aborting due to 2 previous errors

tests/ui/dst/dst-sized-trait-param.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@ LL | impl Foo<[isize]> for usize { }
55
| ^^^^^^^^^^^^ doesn't have a size known at compile-time
66
|
77
= help: the trait `Sized` is not implemented for `[isize]`
8-
note: required by a bound in `Foo`
8+
note: required by an implicit `Sized` bound in `Foo`
99
--> $DIR/dst-sized-trait-param.rs:5:11
1010
|
1111
LL | trait Foo<T> : Sized { fn take(self, x: &T) { } } // Note: T is sized
12-
| ^ required by this bound in `Foo`
12+
| ^ required by the implicit `Sized` requirement on this bound in `Foo`
1313
help: consider relaxing the implicit `Sized` restriction
1414
|
1515
LL | trait Foo<T: ?Sized> : Sized { fn take(self, x: &T) { } } // Note: T is sized

tests/ui/extern/extern-types-unsized.stderr

+8-8
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@ LL | assert_sized::<A>();
55
| ^ doesn't have a size known at compile-time
66
|
77
= help: the trait `Sized` is not implemented for `A`
8-
note: required by a bound in `assert_sized`
8+
note: required by an implicit `Sized` bound in `assert_sized`
99
--> $DIR/extern-types-unsized.rs:19:17
1010
|
1111
LL | fn assert_sized<T>() {}
12-
| ^ required by this bound in `assert_sized`
12+
| ^ required by the implicit `Sized` requirement on this bound in `assert_sized`
1313
help: consider relaxing the implicit `Sized` restriction
1414
|
1515
LL | fn assert_sized<T: ?Sized>() {}
@@ -27,11 +27,11 @@ note: required because it appears within the type `Foo`
2727
|
2828
LL | struct Foo {
2929
| ^^^
30-
note: required by a bound in `assert_sized`
30+
note: required by an implicit `Sized` bound in `assert_sized`
3131
--> $DIR/extern-types-unsized.rs:19:17
3232
|
3333
LL | fn assert_sized<T>() {}
34-
| ^ required by this bound in `assert_sized`
34+
| ^ required by the implicit `Sized` requirement on this bound in `assert_sized`
3535
help: consider relaxing the implicit `Sized` restriction
3636
|
3737
LL | fn assert_sized<T: ?Sized>() {}
@@ -49,11 +49,11 @@ note: required because it appears within the type `Bar<A>`
4949
|
5050
LL | struct Bar<T: ?Sized> {
5151
| ^^^
52-
note: required by a bound in `assert_sized`
52+
note: required by an implicit `Sized` bound in `assert_sized`
5353
--> $DIR/extern-types-unsized.rs:19:17
5454
|
5555
LL | fn assert_sized<T>() {}
56-
| ^ required by this bound in `assert_sized`
56+
| ^ required by the implicit `Sized` requirement on this bound in `assert_sized`
5757
help: consider relaxing the implicit `Sized` restriction
5858
|
5959
LL | fn assert_sized<T: ?Sized>() {}
@@ -71,11 +71,11 @@ note: required because it appears within the type `Bar<A>`
7171
|
7272
LL | struct Bar<T: ?Sized> {
7373
| ^^^
74-
note: required by a bound in `assert_sized`
74+
note: required by an implicit `Sized` bound in `assert_sized`
7575
--> $DIR/extern-types-unsized.rs:19:17
7676
|
7777
LL | fn assert_sized<T>() {}
78-
| ^ required by this bound in `assert_sized`
78+
| ^ required by the implicit `Sized` requirement on this bound in `assert_sized`
7979
help: consider relaxing the implicit `Sized` restriction
8080
|
8181
LL | fn assert_sized<T: ?Sized>() {}

tests/ui/generic-associated-types/issue-88287.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,11 @@ LL | type SearchFutureTy<'f, A, B: 'f>
77
LL | async move { todo!() }
88
| ^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
99
|
10-
note: required by a bound in `<T as SearchableResourceExt<Criteria>>`
10+
note: required by an implicit `Sized` bound in `<T as SearchableResourceExt<Criteria>>`
1111
--> $DIR/issue-88287.rs:24:6
1212
|
1313
LL | impl<T, Criteria> SearchableResourceExt<Criteria> for T
14-
| ^ required by this bound in `<T as SearchableResourceExt<Criteria>>`
14+
| ^ required by the implicit `Sized` requirement on this bound in `<T as SearchableResourceExt<Criteria>>`
1515
help: consider removing the `?Sized` bound to make the type parameter `Sized`
1616
|
1717
LL - A: SearchableResource<B> + ?Sized + 'f,

tests/ui/generics/issue-61631-default-type-param-can-reference-self-in-trait.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@ LL | impl Tsized for () {}
66
|
77
= help: the trait `Sized` is not implemented for `[()]`
88
note: required by a bound in `Tsized`
9-
--> $DIR/issue-61631-default-type-param-can-reference-self-in-trait.rs:17:14
9+
--> $DIR/issue-61631-default-type-param-can-reference-self-in-trait.rs:17:17
1010
|
1111
LL | trait Tsized<P: Sized = [Self]> {}
12-
| ^^^^^^^^^^^^^^^^^ required by this bound in `Tsized`
12+
| ^^^^^ required by this bound in `Tsized`
1313

1414
error: aborting due to 1 previous error
1515

tests/ui/impl-trait/in-trait/wf-bounds.stderr

+4-4
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ LL | fn nya() -> impl Wf<Vec<[u8]>>;
55
| ^^^^^^^^^^^^^ doesn't have a size known at compile-time
66
|
77
= help: the trait `Sized` is not implemented for `[u8]`
8-
note: required by a bound in `Vec`
8+
note: required by an implicit `Sized` bound in `Vec`
99
--> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
1010

1111
error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
@@ -15,11 +15,11 @@ LL | fn nya2() -> impl Wf<[u8]>;
1515
| ^^^^^^^^ doesn't have a size known at compile-time
1616
|
1717
= help: the trait `Sized` is not implemented for `[u8]`
18-
note: required by a bound in `Wf`
18+
note: required by an implicit `Sized` bound in `Wf`
1919
--> $DIR/wf-bounds.rs:7:10
2020
|
2121
LL | trait Wf<T> {
22-
| ^ required by this bound in `Wf`
22+
| ^ required by the implicit `Sized` requirement on this bound in `Wf`
2323
help: consider relaxing the implicit `Sized` restriction
2424
|
2525
LL | trait Wf<T: ?Sized> {
@@ -32,7 +32,7 @@ LL | fn nya3() -> impl Wf<(), Output = impl Wf<Vec<[u8]>>>;
3232
| ^^^^^^^^^^^^^ doesn't have a size known at compile-time
3333
|
3434
= help: the trait `Sized` is not implemented for `[u8]`
35-
note: required by a bound in `Vec`
35+
note: required by an implicit `Sized` bound in `Vec`
3636
--> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
3737

3838
error[E0277]: `T` doesn't implement `std::fmt::Display`

0 commit comments

Comments
 (0)