Skip to content
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

Explain origin of implicit Sized obligations and provide suggestions when possible #85947

Closed
wants to merge 11 commits into from
Prev Previous commit
Next Next commit
Move label for Sized obligation introduced by type param or assoc t…
…ype to its own note
  • Loading branch information
estebank committed Jun 11, 2021
commit 2c58ef5a5a77c7f7cfeab23a9e91b2e2e1306da2
19 changes: 12 additions & 7 deletions compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
Original file line number Diff line number Diff line change
@@ -202,6 +202,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
&obligation.cause.code,
&mut vec![],
&mut Default::default(),
None,
);

err.emit();
@@ -232,6 +233,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
) {
let tcx = self.tcx;
let span = obligation.cause.span;
let mut obligation_note = None;

let mut err = match *error {
SelectionError::Unimplemented => {
@@ -321,7 +323,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
ident,
..
})) => {
err.note(
obligation_note = Some(
"associated types introduce an implicit `Sized` \
obligation",
);
@@ -349,7 +351,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
kind: hir::ImplItemKind::TyAlias(_),
..
})) => {
err.note(
obligation_note = Some(
"associated types on `impl` blocks for types, have an \
implicit mandatory `Sized` obligation; associated \
types from `trait`s can be relaxed to `?Sized`",
@@ -358,7 +360,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
_ => {
// This is (likely?) a type parameter. The suggestion is handled
// in `rustc_middle/src/ty/diagnostics.rs`.
err.note(
obligation_note = Some(
"type parameters introduce an implicit `Sized` \
obligation",
);
@@ -423,7 +425,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
points_at_arg,
have_alt_message,
) {
self.note_obligation_cause(&mut err, obligation);
self.note_obligation_cause(&mut err, obligation, obligation_note);
err.emit();
return;
}
@@ -852,7 +854,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
}
};

self.note_obligation_cause(&mut err, obligation);
self.note_obligation_cause(&mut err, obligation, obligation_note);
self.point_at_returns_when_relevant(&mut err, &obligation);

err.emit();
@@ -1135,6 +1137,7 @@ trait InferCtxtPrivExt<'tcx> {
&self,
err: &mut DiagnosticBuilder<'tcx>,
obligation: &PredicateObligation<'tcx>,
note: Option<&str>,
);

fn suggest_unsized_bound_if_applicable(
@@ -1355,7 +1358,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
_ => None,
};
self.note_type_err(&mut diag, &obligation.cause, secondary_span, values, err, true);
self.note_obligation_cause(&mut diag, obligation);
self.note_obligation_cause(&mut diag, obligation, None);
diag.emit();
}
});
@@ -1764,7 +1767,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
err
}
};
self.note_obligation_cause(&mut err, obligation);
self.note_obligation_cause(&mut err, obligation, None);
err.emit();
}

@@ -1828,6 +1831,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
&self,
err: &mut DiagnosticBuilder<'tcx>,
obligation: &PredicateObligation<'tcx>,
note: Option<&str>,
) {
// First, attempt to add note to this error with an async-await-specific
// message, and fall back to regular note otherwise.
@@ -1838,6 +1842,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
&obligation.cause.code,
&mut vec![],
&mut Default::default(),
note,
);
self.suggest_unsized_bound_if_applicable(err, obligation);
}
Original file line number Diff line number Diff line change
@@ -162,6 +162,7 @@ pub trait InferCtxtExt<'tcx> {
cause_code: &ObligationCauseCode<'tcx>,
obligated_types: &mut Vec<&ty::TyS<'tcx>>,
seen_requirements: &mut FxHashSet<DefId>,
note: Option<&str>,
) where
T: fmt::Display;

@@ -1872,6 +1873,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
next_code.unwrap(),
&mut Vec::new(),
&mut Default::default(),
None,
);
}

@@ -1882,6 +1884,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
cause_code: &ObligationCauseCode<'tcx>,
obligated_types: &mut Vec<&ty::TyS<'tcx>>,
seen_requirements: &mut FxHashSet<DefId>,
note: Option<&str>,
) where
T: fmt::Display,
{
@@ -1946,7 +1949,13 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
}
}
if span != DUMMY_SP {
err.span_label(span, &msg);
if let Some(note) = note {
let mut sp: MultiSpan = span.into();
sp.push_span_label(span, msg);
err.span_note(sp, note);
} else {
err.span_label(span, &msg);
}
} else {
err.note(&msg);
}
@@ -2148,6 +2157,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
&data.parent_code,
obligated_types,
seen_requirements,
note,
)
});
}
@@ -2218,6 +2228,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
&data.parent_code,
obligated_types,
seen_requirements,
note,
)
});
}
@@ -2232,6 +2243,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
&data.parent_code,
obligated_types,
seen_requirements,
note,
)
});
}
11 changes: 5 additions & 6 deletions src/test/ui/associated-types/defaults-wf.stderr
Original file line number Diff line number Diff line change
@@ -3,14 +3,13 @@ error[E0277]: the size for values of type `[u8]` cannot be known at compilation
|
LL | type Ty = Vec<[u8]>;
| ^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
::: $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
|
LL | pub struct Vec<T, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global> {
| - required by this bound in `Vec`
|
= note: type parameters introduce an implicit `Sized` obligation
= help: the trait `Sized` is not implemented for `[u8]`
note: type parameters introduce an implicit `Sized` obligation
--> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
|
LL | pub struct Vec<T, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global> {
| ^ required by this bound in `Vec`

error: aborting due to previous error

Original file line number Diff line number Diff line change
@@ -3,13 +3,12 @@ error[E0277]: the size for values of type `Self` cannot be known at compilation
|
LL | trait ArithmeticOps: Add<Output=Self> + Sub<Output=Self> + Mul<Output=Self> + Div<Output=Self> {}
| ^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
::: $SRC_DIR/core/src/ops/arith.rs:LL:COL
|
LL | pub trait Add<Rhs = Self> {
| --- required by this bound in `Add`
note: type parameters introduce an implicit `Sized` obligation
--> $SRC_DIR/core/src/ops/arith.rs:LL:COL
|
= note: type parameters introduce an implicit `Sized` obligation
LL | pub trait Add<Rhs = Self> {
| ^^^ required by this bound in `Add`
help: consider further restricting `Self`
|
LL | trait ArithmeticOps: Add<Output=Self> + Sub<Output=Self> + Mul<Output=Self> + Div<Output=Self> + Sized {}
9 changes: 5 additions & 4 deletions src/test/ui/dst/dst-sized-trait-param.stderr
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
error[E0277]: the size for values of type `[isize]` cannot be known at compilation time
--> $DIR/dst-sized-trait-param.rs:7:6
|
LL | trait Foo<T> : Sized { fn take(self, x: &T) { } } // Note: T is sized
| - required by this bound in `Foo`
LL |
LL | impl Foo<[isize]> for usize { }
| ^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= note: type parameters introduce an implicit `Sized` obligation
= help: the trait `Sized` is not implemented for `[isize]`
note: type parameters introduce an implicit `Sized` obligation
--> $DIR/dst-sized-trait-param.rs:5:11
|
LL | trait Foo<T> : Sized { fn take(self, x: &T) { } } // Note: T is sized
| ^ required by this bound in `Foo`
help: consider relaxing the implicit `Sized` restriction
|
LL | trait Foo<T: ?Sized> : Sized { fn take(self, x: &T) { } } // Note: T is sized
36 changes: 20 additions & 16 deletions src/test/ui/extern/extern-types-unsized.stderr
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
error[E0277]: the size for values of type `A` cannot be known at compilation time
--> $DIR/extern-types-unsized.rs:22:20
|
LL | fn assert_sized<T>() {}
| - required by this bound in `assert_sized`
...
LL | assert_sized::<A>();
| ^ doesn't have a size known at compile-time
|
= note: type parameters introduce an implicit `Sized` obligation
= help: the trait `Sized` is not implemented for `A`
note: type parameters introduce an implicit `Sized` obligation
--> $DIR/extern-types-unsized.rs:19:17
|
LL | fn assert_sized<T>() {}
| ^ required by this bound in `assert_sized`
help: consider relaxing the implicit `Sized` restriction
|
LL | fn assert_sized<T: ?Sized>() {}
@@ -17,19 +18,20 @@ LL | fn assert_sized<T: ?Sized>() {}
error[E0277]: the size for values of type `A` cannot be known at compilation time
--> $DIR/extern-types-unsized.rs:25:5
|
LL | fn assert_sized<T>() {}
| - required by this bound in `assert_sized`
...
LL | assert_sized::<Foo>();
| ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= note: type parameters introduce an implicit `Sized` obligation
= help: within `Foo`, the trait `Sized` is not implemented for `A`
note: required because it appears within the type `Foo`
--> $DIR/extern-types-unsized.rs:9:8
|
LL | struct Foo {
| ^^^
note: type parameters introduce an implicit `Sized` obligation
--> $DIR/extern-types-unsized.rs:19:17
|
LL | fn assert_sized<T>() {}
| ^ required by this bound in `assert_sized`
help: consider relaxing the implicit `Sized` restriction
|
LL | fn assert_sized<T: ?Sized>() {}
@@ -38,19 +40,20 @@ LL | fn assert_sized<T: ?Sized>() {}
error[E0277]: the size for values of type `A` cannot be known at compilation time
--> $DIR/extern-types-unsized.rs:28:5
|
LL | fn assert_sized<T>() {}
| - required by this bound in `assert_sized`
...
LL | assert_sized::<Bar<A>>();
| ^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= note: type parameters introduce an implicit `Sized` obligation
= help: within `Bar<A>`, the trait `Sized` is not implemented for `A`
note: required because it appears within the type `Bar<A>`
--> $DIR/extern-types-unsized.rs:14:8
|
LL | struct Bar<T: ?Sized> {
| ^^^
note: type parameters introduce an implicit `Sized` obligation
--> $DIR/extern-types-unsized.rs:19:17
|
LL | fn assert_sized<T>() {}
| ^ required by this bound in `assert_sized`
help: consider relaxing the implicit `Sized` restriction
|
LL | fn assert_sized<T: ?Sized>() {}
@@ -59,13 +62,9 @@ LL | fn assert_sized<T: ?Sized>() {}
error[E0277]: the size for values of type `A` cannot be known at compilation time
--> $DIR/extern-types-unsized.rs:31:5
|
LL | fn assert_sized<T>() {}
| - required by this bound in `assert_sized`
...
LL | assert_sized::<Bar<Bar<A>>>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= note: type parameters introduce an implicit `Sized` obligation
= help: within `Bar<Bar<A>>`, the trait `Sized` is not implemented for `A`
note: required because it appears within the type `Bar<A>`
--> $DIR/extern-types-unsized.rs:14:8
@@ -77,6 +76,11 @@ note: required because it appears within the type `Bar<Bar<A>>`
|
LL | struct Bar<T: ?Sized> {
| ^^^
note: type parameters introduce an implicit `Sized` obligation
--> $DIR/extern-types-unsized.rs:19:17
|
LL | fn assert_sized<T>() {}
| ^ required by this bound in `assert_sized`
help: consider relaxing the implicit `Sized` restriction
|
LL | fn assert_sized<T: ?Sized>() {}
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
error[E0277]: the size for values of type `[()]` cannot be known at compilation time
--> $DIR/issue-61631-default-type-param-can-reference-self-in-trait.rs:19:6
|
LL | trait Tsized<P: Sized = [Self]> {}
| - required by this bound in `Tsized`
LL |
LL | impl Tsized for () {}
| ^^^^^^ doesn't have a size known at compile-time
|
= note: type parameters introduce an implicit `Sized` obligation
= help: the trait `Sized` is not implemented for `[()]`
note: type parameters introduce an implicit `Sized` obligation
--> $DIR/issue-61631-default-type-param-can-reference-self-in-trait.rs:17:14
|
LL | trait Tsized<P: Sized = [Self]> {}
| ^ required by this bound in `Tsized`

error: aborting due to previous error

9 changes: 5 additions & 4 deletions src/test/ui/issues/issue-10412.stderr
Original file line number Diff line number Diff line change
@@ -49,14 +49,15 @@ LL | impl<'self> Serializable<str> for &'self str {
error[E0277]: the size for values of type `str` cannot be known at compilation time
--> $DIR/issue-10412.rs:6:13
|
LL | trait Serializable<'self, T> {
| - required by this bound in `Serializable`
...
LL | impl<'self> Serializable<str> for &'self str {
| ^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= note: type parameters introduce an implicit `Sized` obligation
= help: the trait `Sized` is not implemented for `str`
note: type parameters introduce an implicit `Sized` obligation
--> $DIR/issue-10412.rs:1:27
|
LL | trait Serializable<'self, T> {
| ^ required by this bound in `Serializable`
help: consider relaxing the implicit `Sized` restriction
|
LL | trait Serializable<'self, T: ?Sized> {
9 changes: 5 additions & 4 deletions src/test/ui/issues/issue-18919.stderr
Original file line number Diff line number Diff line change
@@ -3,12 +3,13 @@ error[E0277]: the size for values of type `dyn for<'r> Fn(&'r isize) -> isize` c
|
LL | fn ho_func(f: Option<FuncType>) {
| ^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
...
LL | enum Option<T> {
| - required by this bound in `Option`
|
= note: type parameters introduce an implicit `Sized` obligation
= help: the trait `Sized` is not implemented for `dyn for<'r> Fn(&'r isize) -> isize`
note: type parameters introduce an implicit `Sized` obligation
--> $DIR/issue-18919.rs:7:13
|
LL | enum Option<T> {
| ^ required by this bound in `Option`
help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box<T>`
--> $DIR/issue-18919.rs:7:13
|
11 changes: 5 additions & 6 deletions src/test/ui/issues/issue-20433.stderr
Original file line number Diff line number Diff line change
@@ -3,14 +3,13 @@ error[E0277]: the size for values of type `[i32]` cannot be known at compilation
|
LL | fn iceman(c: Vec<[i32]>) {}
| ^^^^^^^^^^ doesn't have a size known at compile-time
|
::: $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
|
LL | pub struct Vec<T, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global> {
| - required by this bound in `Vec`
|
= note: type parameters introduce an implicit `Sized` obligation
= help: the trait `Sized` is not implemented for `[i32]`
note: type parameters introduce an implicit `Sized` obligation
--> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
|
LL | pub struct Vec<T, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global> {
| ^ required by this bound in `Vec`

error: aborting due to previous error

Loading