Skip to content

Commit cb6dfea

Browse files
committed
Suggest ?Sized on type parameters
1 parent 542130b commit cb6dfea

File tree

4 files changed

+60
-6
lines changed

4 files changed

+60
-6
lines changed

src/librustc/traits/error_reporting/mod.rs

+38
Original file line numberDiff line numberDiff line change
@@ -1340,6 +1340,44 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
13401340
&obligation.cause.code,
13411341
&mut vec![],
13421342
);
1343+
self.suggest_unsized_bound_if_applicable(err, obligation);
1344+
}
1345+
}
1346+
1347+
fn suggest_unsized_bound_if_applicable(
1348+
&self,
1349+
err: &mut DiagnosticBuilder<'_>,
1350+
obligation: &PredicateObligation<'tcx>,
1351+
) {
1352+
if let (
1353+
ty::Predicate::Trait(pred, _),
1354+
ObligationCauseCode::BindingObligation(item_def_id, span),
1355+
) = (&obligation.predicate, &obligation.cause.code)
1356+
{
1357+
if let (Some(generics), true) = (
1358+
self.tcx.hir().get_if_local(*item_def_id).as_ref().and_then(|n| n.generics()),
1359+
Some(pred.def_id()) == self.tcx.lang_items().sized_trait(),
1360+
) {
1361+
for param in generics.params {
1362+
if param.span == *span
1363+
&& !param.bounds.iter().any(|bound| {
1364+
bound.trait_def_id() == self.tcx.lang_items().sized_trait()
1365+
})
1366+
{
1367+
let (span, separator) = match param.bounds {
1368+
[] => (span.shrink_to_hi(), ":"),
1369+
[.., bound] => (bound.span().shrink_to_hi(), " + "),
1370+
};
1371+
err.span_suggestion(
1372+
span,
1373+
"consider relaxing the implicit `Sized` restriction",
1374+
format!("{} ?Sized", separator),
1375+
Applicability::MachineApplicable,
1376+
);
1377+
return;
1378+
}
1379+
}
1380+
}
13431381
}
13441382
}
13451383

src/test/ui/extern/extern-types-unsized.stderr

+3-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ error[E0277]: the size for values of type `A` cannot be known at compilation tim
22
--> $DIR/extern-types-unsized.rs:22:20
33
|
44
LL | fn assert_sized<T>() { }
5-
| ------------ - required by this bound in `assert_sized`
5+
| ------------ -- help: consider relaxing the implicit `Sized` restriction: `: ?Sized`
6+
| |
7+
| required by this bound in `assert_sized`
68
...
79
LL | assert_sized::<A>();
810
| ^ doesn't have a size known at compile-time

src/test/ui/str/str-mut-idx.stderr

+3-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ error[E0277]: the size for values of type `str` cannot be known at compilation t
22
--> $DIR/str-mut-idx.rs:4:15
33
|
44
LL | fn bot<T>() -> T { loop {} }
5-
| --- - required by this bound in `bot`
5+
| --- -- help: consider relaxing the implicit `Sized` restriction: `: ?Sized`
6+
| |
7+
| required by this bound in `bot`
68
...
79
LL | s[1..2] = bot();
810
| ^^^ doesn't have a size known at compile-time

src/test/ui/unsized3.stderr

+16-4
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
error[E0277]: the size for values of type `X` cannot be known at compilation time
22
--> $DIR/unsized3.rs:7:13
33
|
4-
LL | fn f1<X: ?Sized>(x: &X) {
5-
| -- help: consider further restricting this bound: `X: std::marker::Sized +`
64
LL | f2::<X>(x);
75
| ^ doesn't have a size known at compile-time
86
...
@@ -11,12 +9,18 @@ LL | fn f2<X>(x: &X) {
119
|
1210
= help: the trait `std::marker::Sized` is not implemented for `X`
1311
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
12+
help: consider further restricting this bound
13+
|
14+
LL | fn f1<X: std::marker::Sized + ?Sized>(x: &X) {
15+
| ^^^^^^^^^^^^^^^^^^^^^^^
16+
help: consider relaxing the implicit `Sized` restriction
17+
|
18+
LL | fn f2<X: ?Sized>(x: &X) {
19+
| ^^^^^^^^
1420

1521
error[E0277]: the size for values of type `X` cannot be known at compilation time
1622
--> $DIR/unsized3.rs:18:13
1723
|
18-
LL | fn f3<X: ?Sized + T>(x: &X) {
19-
| -- help: consider further restricting this bound: `X: std::marker::Sized +`
2024
LL | f4::<X>(x);
2125
| ^ doesn't have a size known at compile-time
2226
...
@@ -25,6 +29,14 @@ LL | fn f4<X: T>(x: &X) {
2529
|
2630
= help: the trait `std::marker::Sized` is not implemented for `X`
2731
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
32+
help: consider further restricting this bound
33+
|
34+
LL | fn f3<X: std::marker::Sized + ?Sized + T>(x: &X) {
35+
| ^^^^^^^^^^^^^^^^^^^^^^^
36+
help: consider relaxing the implicit `Sized` restriction
37+
|
38+
LL | fn f4<X: T + ?Sized>(x: &X) {
39+
| ^^^^^^^^^
2840

2941
error[E0277]: the size for values of type `X` cannot be known at compilation time
3042
--> $DIR/unsized3.rs:33:8

0 commit comments

Comments
 (0)