Skip to content

Commit

Permalink
Account for ?Sized type parameter bounds
Browse files Browse the repository at this point in the history
  • Loading branch information
estebank committed Feb 2, 2020
1 parent d216b73 commit 342db71
Show file tree
Hide file tree
Showing 18 changed files with 76 additions and 72 deletions.
12 changes: 11 additions & 1 deletion src/librustc/traits/error_reporting/suggestions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,12 +145,14 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
let param_name = self_ty.to_string();
let constraint = trait_ref.print_only_trait_path().to_string();
if suggest_constraining_type_param(
self.tcx,
generics,
&mut err,
&param_name,
&constraint,
self.tcx.sess.source_map(),
*span,
Some(trait_ref.def_id()),
) {
return;
}
Expand Down Expand Up @@ -1652,18 +1654,26 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {

/// Suggest restricting a type param with a new bound.
pub fn suggest_constraining_type_param(
tcx: TyCtxt<'_>,
generics: &hir::Generics<'_>,
err: &mut DiagnosticBuilder<'_>,
param_name: &str,
constraint: &str,
source_map: &SourceMap,
span: Span,
def_id: Option<DefId>,
) -> bool {
let restrict_msg = "consider further restricting this bound";
if let Some(param) =
generics.params.iter().filter(|p| p.name.ident().as_str() == param_name).next()
{
if param_name.starts_with("impl ") {
if def_id == tcx.lang_items().sized_trait() {
// Type parameters are already `Sized` by default.
err.span_label(
param.span,
&format!("this type parameter needs to be `{}`", constraint),
);
} else if param_name.starts_with("impl ") {
// `impl Trait` in argument:
// `fn foo(x: impl Trait) {}` → `fn foo(t: impl Trait + Trait2) {}`
err.span_suggestion(
Expand Down
2 changes: 2 additions & 0 deletions src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -217,12 +217,14 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
tcx.hir().get_generics(tcx.closure_base_def_id(self.mir_def_id))
{
suggest_constraining_type_param(
tcx,
generics,
&mut err,
&param.name.as_str(),
"Copy",
tcx.sess.source_map(),
span,
None,
);
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/test/ui/consts/too_generic_eval_ice.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ LL | pub struct Foo<A, B>(A, B);
| --------------------------- required by `Foo`
LL |
LL | impl<A, B> Foo<A, B> {
| - help: consider restricting this bound: `A: std::marker::Sized`
| - this type parameter needs to be `std::marker::Sized`
...
LL | [5; Self::HOST_SIZE] == [6; 0]
| ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
Expand All @@ -33,7 +33,7 @@ LL | pub struct Foo<A, B>(A, B);
| --------------------------- required by `Foo`
LL |
LL | impl<A, B> Foo<A, B> {
| - help: consider restricting this bound: `B: std::marker::Sized`
| - this type parameter needs to be `std::marker::Sized`
...
LL | [5; Self::HOST_SIZE] == [6; 0]
| ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
Expand Down
4 changes: 2 additions & 2 deletions src/test/ui/dst/dst-object-from-unsized-type.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ error[E0277]: the size for values of type `T` cannot be known at compilation tim
--> $DIR/dst-object-from-unsized-type.rs:8:23
|
LL | fn test1<T: ?Sized + Foo>(t: &T) {
| -- help: consider further restricting this bound: `T: std::marker::Sized +`
| - this type parameter needs to be `std::marker::Sized`
LL | let u: &dyn Foo = t;
| ^ doesn't have a size known at compile-time
|
Expand All @@ -14,7 +14,7 @@ error[E0277]: the size for values of type `T` cannot be known at compilation tim
--> $DIR/dst-object-from-unsized-type.rs:13:23
|
LL | fn test2<T: ?Sized + Foo>(t: &T) {
| -- help: consider further restricting this bound: `T: std::marker::Sized +`
| - this type parameter needs to be `std::marker::Sized`
LL | let v: &dyn Foo = t as &dyn Foo;
| ^ doesn't have a size known at compile-time
|
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/issues/issue-27060-2.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ error[E0277]: the size for values of type `T` cannot be known at compilation tim
--> $DIR/issue-27060-2.rs:3:5
|
LL | pub struct Bad<T: ?Sized> {
| -- help: consider further restricting this bound: `T: std::marker::Sized +`
| - this type parameter needs to be `std::marker::Sized`
LL | data: T,
| ^^^^^^^ doesn't have a size known at compile-time
|
Expand Down
4 changes: 2 additions & 2 deletions src/test/ui/traits/trait-suggest-where-clause.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ error[E0277]: the size for values of type `U` cannot be known at compilation tim
--> $DIR/trait-suggest-where-clause.rs:11:20
|
LL | fn check<T: Iterator, U: ?Sized>() {
| -- help: consider further restricting this bound: `U: std::marker::Sized +`
| - this type parameter needs to be `std::marker::Sized`
LL | // suggest a where-clause, if needed
LL | mem::size_of::<U>();
| ^ doesn't have a size known at compile-time
Expand All @@ -19,7 +19,7 @@ error[E0277]: the size for values of type `U` cannot be known at compilation tim
--> $DIR/trait-suggest-where-clause.rs:14:5
|
LL | fn check<T: Iterator, U: ?Sized>() {
| -- help: consider further restricting this bound: `U: std::marker::Sized +`
| - this type parameter needs to be `std::marker::Sized`
...
LL | mem::size_of::<Misc<U>>();
| ^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
Expand Down
6 changes: 3 additions & 3 deletions src/test/ui/union/union-sized-field.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ error[E0277]: the size for values of type `T` cannot be known at compilation tim
--> $DIR/union-sized-field.rs:4:5
|
LL | union Foo<T: ?Sized> {
| -- help: consider further restricting this bound: `T: std::marker::Sized +`
| - this type parameter needs to be `std::marker::Sized`
LL | value: T,
| ^^^^^^^^ doesn't have a size known at compile-time
|
Expand All @@ -14,7 +14,7 @@ error[E0277]: the size for values of type `T` cannot be known at compilation tim
--> $DIR/union-sized-field.rs:9:5
|
LL | struct Foo2<T: ?Sized> {
| -- help: consider further restricting this bound: `T: std::marker::Sized +`
| - this type parameter needs to be `std::marker::Sized`
LL | value: T,
| ^^^^^^^^ doesn't have a size known at compile-time
|
Expand All @@ -26,7 +26,7 @@ error[E0277]: the size for values of type `T` cannot be known at compilation tim
--> $DIR/union-sized-field.rs:15:11
|
LL | enum Foo3<T: ?Sized> {
| -- help: consider further restricting this bound: `T: std::marker::Sized +`
| - this type parameter needs to be `std::marker::Sized`
LL | Value(T),
| ^ doesn't have a size known at compile-time
|
Expand Down
4 changes: 2 additions & 2 deletions src/test/ui/unsized/unsized-bare-typaram.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ error[E0277]: the size for values of type `T` cannot be known at compilation tim
LL | fn bar<T: Sized>() { }
| --- - required by this bound in `bar`
LL | fn foo<T: ?Sized>() { bar::<T>() }
| -- ^ doesn't have a size known at compile-time
| - ^ doesn't have a size known at compile-time
| |
| help: consider further restricting this bound: `T: std::marker::Sized +`
| this type parameter needs to be `std::marker::Sized`
|
= help: the trait `std::marker::Sized` is not implemented for `T`
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
Expand Down
4 changes: 2 additions & 2 deletions src/test/ui/unsized/unsized-enum.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ LL | enum Foo<U> { FooSome(U), FooNone }
| ----------- required by `Foo`
LL | fn foo1<T>() { not_sized::<Foo<T>>() } // Hunky dory.
LL | fn foo2<T: ?Sized>() { not_sized::<Foo<T>>() }
| -- ^^^^^^ doesn't have a size known at compile-time
| - ^^^^^^ doesn't have a size known at compile-time
| |
| help: consider further restricting this bound: `T: std::marker::Sized +`
| this type parameter needs to be `std::marker::Sized`
|
= help: the trait `std::marker::Sized` is not implemented for `T`
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
Expand Down
8 changes: 4 additions & 4 deletions src/test/ui/unsized/unsized-enum2.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ error[E0277]: the size for values of type `W` cannot be known at compilation tim
--> $DIR/unsized-enum2.rs:23:8
|
LL | enum E<W: ?Sized, X: ?Sized, Y: ?Sized, Z: ?Sized> {
| -- help: consider further restricting this bound: `W: std::marker::Sized +`
| - this type parameter needs to be `std::marker::Sized`
LL | // parameter
LL | VA(W),
| ^ doesn't have a size known at compile-time
Expand All @@ -15,7 +15,7 @@ error[E0277]: the size for values of type `X` cannot be known at compilation tim
--> $DIR/unsized-enum2.rs:25:8
|
LL | enum E<W: ?Sized, X: ?Sized, Y: ?Sized, Z: ?Sized> {
| -- help: consider further restricting this bound: `X: std::marker::Sized +`
| - this type parameter needs to be `std::marker::Sized`
...
LL | VB{x: X},
| ^^^^ doesn't have a size known at compile-time
Expand All @@ -28,7 +28,7 @@ error[E0277]: the size for values of type `Y` cannot be known at compilation tim
--> $DIR/unsized-enum2.rs:27:15
|
LL | enum E<W: ?Sized, X: ?Sized, Y: ?Sized, Z: ?Sized> {
| -- help: consider further restricting this bound: `Y: std::marker::Sized +`
| - this type parameter needs to be `std::marker::Sized`
...
LL | VC(isize, Y),
| ^ doesn't have a size known at compile-time
Expand All @@ -41,7 +41,7 @@ error[E0277]: the size for values of type `Z` cannot be known at compilation tim
--> $DIR/unsized-enum2.rs:29:18
|
LL | enum E<W: ?Sized, X: ?Sized, Y: ?Sized, Z: ?Sized> {
| -- help: consider further restricting this bound: `Z: std::marker::Sized +`
| - this type parameter needs to be `std::marker::Sized`
...
LL | VD{u: isize, x: Z},
| ^^^^ doesn't have a size known at compile-time
Expand Down
4 changes: 2 additions & 2 deletions src/test/ui/unsized/unsized-inherent-impl-self-type.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ LL | struct S5<Y>(Y);
| ---------------- required by `S5`
LL |
LL | impl<X: ?Sized> S5<X> {
| -- ^^^^^ doesn't have a size known at compile-time
| - ^^^^^ doesn't have a size known at compile-time
| |
| help: consider further restricting this bound: `X: std::marker::Sized +`
| this type parameter needs to be `std::marker::Sized`
|
= help: the trait `std::marker::Sized` is not implemented for `X`
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
Expand Down
8 changes: 4 additions & 4 deletions src/test/ui/unsized/unsized-struct.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ LL | struct Foo<T> { data: T }
| ------------- required by `Foo`
LL | fn foo1<T>() { not_sized::<Foo<T>>() } // Hunky dory.
LL | fn foo2<T: ?Sized>() { not_sized::<Foo<T>>() }
| -- ^^^^^^ doesn't have a size known at compile-time
| - ^^^^^^ doesn't have a size known at compile-time
| |
| help: consider further restricting this bound: `T: std::marker::Sized +`
| this type parameter needs to be `std::marker::Sized`
|
= help: the trait `std::marker::Sized` is not implemented for `T`
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
Expand All @@ -19,9 +19,9 @@ LL | fn is_sized<T:Sized>() { }
| -------- - required by this bound in `is_sized`
...
LL | fn bar2<T: ?Sized>() { is_sized::<Bar<T>>() }
| -- ^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
| - ^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
| |
| help: consider further restricting this bound: `T: std::marker::Sized +`
| this type parameter needs to be `std::marker::Sized`
|
= help: within `Bar<T>`, the trait `std::marker::Sized` is not implemented for `T`
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
Expand Down
4 changes: 2 additions & 2 deletions src/test/ui/unsized/unsized-trait-impl-self-type.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ LL | struct S5<Y>(Y);
| ---------------- required by `S5`
LL |
LL | impl<X: ?Sized> T3<X> for S5<X> {
| -- ^^^^^ doesn't have a size known at compile-time
| - ^^^^^ doesn't have a size known at compile-time
| |
| help: consider further restricting this bound: `X: std::marker::Sized +`
| this type parameter needs to be `std::marker::Sized`
|
= help: the trait `std::marker::Sized` is not implemented for `X`
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
Expand Down
4 changes: 2 additions & 2 deletions src/test/ui/unsized/unsized-trait-impl-trait-arg.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ error[E0277]: the size for values of type `X` cannot be known at compilation tim
--> $DIR/unsized-trait-impl-trait-arg.rs:8:17
|
LL | impl<X: ?Sized> T2<X> for S4<X> {
| -- ^^^^^ doesn't have a size known at compile-time
| - ^^^^^ doesn't have a size known at compile-time
| |
| help: consider further restricting this bound: `X: std::marker::Sized +`
| this type parameter needs to be `std::marker::Sized`
|
= help: the trait `std::marker::Sized` is not implemented for `X`
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
Expand Down
36 changes: 14 additions & 22 deletions src/test/ui/unsized3.stderr
Original file line number Diff line number Diff line change
@@ -1,42 +1,34 @@
error[E0277]: the size for values of type `X` cannot be known at compilation time
--> $DIR/unsized3.rs:7:13
|
LL | fn f1<X: ?Sized>(x: &X) {
| - this type parameter needs to be `std::marker::Sized`
LL | f2::<X>(x);
| ^ doesn't have a size known at compile-time
...
LL | fn f2<X>(x: &X) {
| -- - required by this bound in `f2`
| -- -- help: consider relaxing the implicit `Sized` restriction: `: ?Sized`
| |
| required by this bound in `f2`
|
= help: the trait `std::marker::Sized` is not implemented for `X`
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
help: consider further restricting this bound
|
LL | fn f1<X: std::marker::Sized + ?Sized>(x: &X) {
| ^^^^^^^^^^^^^^^^^^^^^^^
help: consider relaxing the implicit `Sized` restriction
|
LL | fn f2<X: ?Sized>(x: &X) {
| ^^^^^^^^

error[E0277]: the size for values of type `X` cannot be known at compilation time
--> $DIR/unsized3.rs:18:13
|
LL | fn f3<X: ?Sized + T>(x: &X) {
| - this type parameter needs to be `std::marker::Sized`
LL | f4::<X>(x);
| ^ doesn't have a size known at compile-time
...
LL | fn f4<X: T>(x: &X) {
| -- - required by this bound in `f4`
| -- - - help: consider relaxing the implicit `Sized` restriction: `+ ?Sized`
| |
| required by this bound in `f4`
|
= help: the trait `std::marker::Sized` is not implemented for `X`
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
help: consider further restricting this bound
|
LL | fn f3<X: std::marker::Sized + ?Sized + T>(x: &X) {
| ^^^^^^^^^^^^^^^^^^^^^^^
help: consider relaxing the implicit `Sized` restriction
|
LL | fn f4<X: T + ?Sized>(x: &X) {
| ^^^^^^^^^

error[E0277]: the size for values of type `X` cannot be known at compilation time
--> $DIR/unsized3.rs:33:8
Expand All @@ -45,7 +37,7 @@ LL | fn f5<Y>(x: &Y) {}
| -- - required by this bound in `f5`
...
LL | fn f8<X: ?Sized>(x1: &S<X>, x2: &S<X>) {
| -- help: consider further restricting this bound: `X: std::marker::Sized +`
| - this type parameter needs to be `std::marker::Sized`
LL | f5(x1);
| ^^ doesn't have a size known at compile-time
|
Expand All @@ -57,7 +49,7 @@ error[E0277]: the size for values of type `X` cannot be known at compilation tim
--> $DIR/unsized3.rs:40:8
|
LL | fn f9<X: ?Sized>(x1: Box<S<X>>) {
| -- help: consider further restricting this bound: `X: std::marker::Sized +`
| - this type parameter needs to be `std::marker::Sized`
LL | f5(&(*x1, 34));
| ^^^^^^^^^^ doesn't have a size known at compile-time
|
Expand All @@ -70,7 +62,7 @@ error[E0277]: the size for values of type `X` cannot be known at compilation tim
--> $DIR/unsized3.rs:45:9
|
LL | fn f10<X: ?Sized>(x1: Box<S<X>>) {
| -- help: consider further restricting this bound: `X: std::marker::Sized +`
| - this type parameter needs to be `std::marker::Sized`
LL | f5(&(32, *x1));
| ^^^^^^^^^ doesn't have a size known at compile-time
|
Expand All @@ -87,7 +79,7 @@ LL | fn f5<Y>(x: &Y) {}
| -- - required by this bound in `f5`
...
LL | fn f10<X: ?Sized>(x1: Box<S<X>>) {
| -- help: consider further restricting this bound: `X: std::marker::Sized +`
| - this type parameter needs to be `std::marker::Sized`
LL | f5(&(32, *x1));
| ^^^^^^^^^^ doesn't have a size known at compile-time
|
Expand Down
8 changes: 4 additions & 4 deletions src/test/ui/unsized5.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ error[E0277]: the size for values of type `X` cannot be known at compilation tim
--> $DIR/unsized5.rs:4:5
|
LL | struct S1<X: ?Sized> {
| -- help: consider further restricting this bound: `X: std::marker::Sized +`
| - this type parameter needs to be `std::marker::Sized`
LL | f1: X,
| ^^^^^ doesn't have a size known at compile-time
|
Expand All @@ -14,7 +14,7 @@ error[E0277]: the size for values of type `X` cannot be known at compilation tim
--> $DIR/unsized5.rs:10:5
|
LL | struct S2<X: ?Sized> {
| -- help: consider further restricting this bound: `X: std::marker::Sized +`
| - this type parameter needs to be `std::marker::Sized`
LL | f: isize,
LL | g: X,
| ^^^^ doesn't have a size known at compile-time
Expand Down Expand Up @@ -47,7 +47,7 @@ error[E0277]: the size for values of type `X` cannot be known at compilation tim
--> $DIR/unsized5.rs:25:8
|
LL | enum E<X: ?Sized> {
| -- help: consider further restricting this bound: `X: std::marker::Sized +`
| - this type parameter needs to be `std::marker::Sized`
LL | V1(X, isize),
| ^ doesn't have a size known at compile-time
|
Expand All @@ -59,7 +59,7 @@ error[E0277]: the size for values of type `X` cannot be known at compilation tim
--> $DIR/unsized5.rs:29:8
|
LL | enum F<X: ?Sized> {
| -- help: consider further restricting this bound: `X: std::marker::Sized +`
| - this type parameter needs to be `std::marker::Sized`
LL | V2{f1: X, f: isize},
| ^^^^^ doesn't have a size known at compile-time
|
Expand Down
Loading

0 comments on commit 342db71

Please sign in to comment.