mirror of
https://github.com/rust-lang/rust
synced 2024-10-01 06:14:33 +00:00
Provide help
when T: ?Sized
can't be suggested
This commit is contained in:
parent
d2b8e6090c
commit
aa84b0fa37
|
@ -26,7 +26,7 @@
|
|||
TypeFoldable, WithConstness,
|
||||
};
|
||||
use rustc_session::DiagnosticMessageId;
|
||||
use rustc_span::{ExpnKind, Span, DUMMY_SP};
|
||||
use rustc_span::{ExpnKind, MultiSpan, Span, DUMMY_SP};
|
||||
use std::fmt;
|
||||
|
||||
use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
|
||||
|
@ -1740,10 +1740,36 @@ fn suggest_unsized_bound_if_applicable(
|
|||
// Suggesting `T: ?Sized` is only valid in an ADT if `T` is only used in a
|
||||
// borrow. `struct S<'a, T: ?Sized>(&'a T);` is valid, `struct S<T: ?Sized>(T);`
|
||||
// is not.
|
||||
let mut visitor = FindTypeParam { param: param.name.ident().name, valid: true };
|
||||
let mut visitor = FindTypeParam {
|
||||
param: param.name.ident().name,
|
||||
invalid_spans: vec![],
|
||||
nested: false,
|
||||
};
|
||||
visitor.visit_item(item);
|
||||
if !visitor.valid {
|
||||
continue;
|
||||
if !visitor.invalid_spans.is_empty() {
|
||||
let mut multispan: MultiSpan = param.span.into();
|
||||
multispan.push_span_label(
|
||||
param.span,
|
||||
format!("this could be changed to `{}: ?Sized`...", param.name.ident()),
|
||||
);
|
||||
for sp in visitor.invalid_spans {
|
||||
multispan.push_span_label(
|
||||
sp,
|
||||
format!(
|
||||
"...if indirection was used here: `Box<{}>`",
|
||||
param.name.ident(),
|
||||
),
|
||||
);
|
||||
}
|
||||
err.span_help(
|
||||
multispan,
|
||||
&format!(
|
||||
"you could relax the implicit `Sized` bound on `{T}` if it were \
|
||||
used through indirection like `&{T}` or `Box<{T}>`",
|
||||
T = param.name.ident(),
|
||||
),
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
|
@ -1782,7 +1808,8 @@ fn is_recursive_obligation(
|
|||
/// `param: ?Sized` would be a valid constraint.
|
||||
struct FindTypeParam {
|
||||
param: rustc_span::Symbol,
|
||||
valid: bool,
|
||||
invalid_spans: Vec<Span>,
|
||||
nested: bool,
|
||||
}
|
||||
|
||||
impl<'v> Visitor<'v> for FindTypeParam {
|
||||
|
@ -1794,15 +1821,24 @@ fn nested_visit_map(&mut self) -> hir::intravisit::NestedVisitorMap<Self::Map> {
|
|||
|
||||
fn visit_ty(&mut self, ty: &hir::Ty<'_>) {
|
||||
match ty.kind {
|
||||
hir::TyKind::Ptr(_) | hir::TyKind::Rptr(..) | hir::TyKind::TraitObject(..) => return,
|
||||
hir::TyKind::Ptr(_) | hir::TyKind::Rptr(..) | hir::TyKind::TraitObject(..) => {}
|
||||
hir::TyKind::Path(hir::QPath::Resolved(None, path))
|
||||
if path.segments.len() == 1 && path.segments[0].ident.name == self.param =>
|
||||
{
|
||||
self.valid = false;
|
||||
if !self.nested {
|
||||
self.invalid_spans.push(ty.span);
|
||||
}
|
||||
}
|
||||
hir::TyKind::Path(_) => {
|
||||
let prev = self.nested;
|
||||
self.nested = true;
|
||||
hir::intravisit::walk_ty(self, ty);
|
||||
self.nested = prev;
|
||||
}
|
||||
_ => {
|
||||
hir::intravisit::walk_ty(self, ty);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
hir::intravisit::walk_ty(self, ty);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,13 @@ LL | enum Option<T> {
|
|||
|
|
||||
= help: the trait `std::marker::Sized` is not implemented for `dyn for<'r> std::ops::Fn(&'r isize) -> isize`
|
||||
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
|
||||
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
|
||||
|
|
||||
LL | enum Option<T> {
|
||||
| ^ this could be changed to `T: ?Sized`...
|
||||
LL | Some(T),
|
||||
| - ...if indirection was used here: `Box<T>`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
@ -9,6 +9,13 @@ LL | struct Vec<T> {
|
|||
|
|
||||
= help: the trait `std::marker::Sized` is not implemented for `(dyn std::ops::Fn() + 'static)`
|
||||
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
|
||||
help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box<T>`
|
||||
--> $DIR/issue-23281.rs:8:12
|
||||
|
|
||||
LL | struct Vec<T> {
|
||||
| ^ this could be changed to `T: ?Sized`...
|
||||
LL | t: T,
|
||||
| - ...if indirection was used here: `Box<T>`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ trait Trait {
|
|||
fn func1() -> Struct1<Self>; //~ ERROR E0277
|
||||
fn func2<'a>() -> Struct2<'a, Self>; //~ ERROR E0277
|
||||
fn func3() -> Struct3<Self>; //~ ERROR E0277
|
||||
fn func4() -> Struct4<Self>; //~ ERROR E0277
|
||||
}
|
||||
|
||||
struct Struct1<T>{
|
||||
|
@ -14,4 +15,14 @@ struct Struct3<T>{
|
|||
_t: T,
|
||||
}
|
||||
|
||||
struct X<T>(T);
|
||||
|
||||
struct Struct4<T>{
|
||||
_t: X<T>,
|
||||
}
|
||||
|
||||
struct Struct5<T: ?Sized>{
|
||||
_t: X<T>, //~ ERROR E0277
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
@ -1,3 +1,24 @@
|
|||
error[E0277]: the size for values of type `T` cannot be known at compilation time
|
||||
--> $DIR/adt-param-with-implicit-sized-bound.rs:25:5
|
||||
|
|
||||
LL | struct X<T>(T);
|
||||
| - required by this bound in `X`
|
||||
...
|
||||
LL | struct Struct5<T: ?Sized>{
|
||||
| - this type parameter needs to be `std::marker::Sized`
|
||||
LL | _t: X<T>,
|
||||
| ^^^^^^^^ doesn't have a size known at compile-time
|
||||
|
|
||||
= 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>
|
||||
help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box<T>`
|
||||
--> $DIR/adt-param-with-implicit-sized-bound.rs:18:10
|
||||
|
|
||||
LL | struct X<T>(T);
|
||||
| ^ - ...if indirection was used here: `Box<T>`
|
||||
| |
|
||||
| this could be changed to `T: ?Sized`...
|
||||
|
||||
error[E0277]: the size for values of type `Self` cannot be known at compilation time
|
||||
--> $DIR/adt-param-with-implicit-sized-bound.rs:2:19
|
||||
|
|
||||
|
@ -49,11 +70,38 @@ LL | struct Struct3<T>{
|
|||
|
|
||||
= help: the trait `std::marker::Sized` is not implemented for `Self`
|
||||
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
|
||||
help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box<T>`
|
||||
--> $DIR/adt-param-with-implicit-sized-bound.rs:14:16
|
||||
|
|
||||
LL | struct Struct3<T>{
|
||||
| ^ this could be changed to `T: ?Sized`...
|
||||
LL | _t: T,
|
||||
| - ...if indirection was used here: `Box<T>`
|
||||
help: consider further restricting `Self`
|
||||
|
|
||||
LL | fn func3() -> Struct3<Self> where Self: std::marker::Sized;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
error[E0277]: the size for values of type `Self` cannot be known at compilation time
|
||||
--> $DIR/adt-param-with-implicit-sized-bound.rs:5:19
|
||||
|
|
||||
LL | fn func4() -> Struct4<Self>;
|
||||
| ^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
||||
...
|
||||
LL | struct Struct4<T>{
|
||||
| - required by this bound in `Struct4`
|
||||
|
|
||||
= help: the trait `std::marker::Sized` is not implemented for `Self`
|
||||
= 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 `Self`
|
||||
|
|
||||
LL | fn func4() -> Struct4<Self> where Self: std::marker::Sized;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
help: consider relaxing the implicit `Sized` restriction
|
||||
|
|
||||
LL | struct Struct4<T: ?Sized>{
|
||||
| ^^^^^^^^
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
|
|
|
@ -11,6 +11,13 @@ LL | fn foo2<T: ?Sized>() { not_sized::<Foo<T>>() }
|
|||
|
|
||||
= 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>
|
||||
help: you could relax the implicit `Sized` bound on `U` if it were used through indirection like `&U` or `Box<U>`
|
||||
--> $DIR/unsized-enum.rs:4:10
|
||||
|
|
||||
LL | enum Foo<U> { FooSome(U), FooNone }
|
||||
| ^ - ...if indirection was used here: `Box<U>`
|
||||
| |
|
||||
| this could be changed to `U: ?Sized`...
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
@ -11,6 +11,13 @@ LL | impl<X: ?Sized> S5<X> {
|
|||
|
|
||||
= 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: you could relax the implicit `Sized` bound on `Y` if it were used through indirection like `&Y` or `Box<Y>`
|
||||
--> $DIR/unsized-inherent-impl-self-type.rs:5:11
|
||||
|
|
||||
LL | struct S5<Y>(Y);
|
||||
| ^ - ...if indirection was used here: `Box<Y>`
|
||||
| |
|
||||
| this could be changed to `Y: ?Sized`...
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
@ -11,6 +11,13 @@ LL | fn foo2<T: ?Sized>() { not_sized::<Foo<T>>() }
|
|||
|
|
||||
= 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>
|
||||
help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box<T>`
|
||||
--> $DIR/unsized-struct.rs:4:12
|
||||
|
|
||||
LL | struct Foo<T> { data: T }
|
||||
| ^ - ...if indirection was used here: `Box<T>`
|
||||
| |
|
||||
| this could be changed to `T: ?Sized`...
|
||||
|
||||
error[E0277]: the size for values of type `T` cannot be known at compilation time
|
||||
--> $DIR/unsized-struct.rs:13:24
|
||||
|
|
|
@ -11,6 +11,13 @@ LL | impl<X: ?Sized> T3<X> for S5<X> {
|
|||
|
|
||||
= 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: you could relax the implicit `Sized` bound on `Y` if it were used through indirection like `&Y` or `Box<Y>`
|
||||
--> $DIR/unsized-trait-impl-self-type.rs:8:11
|
||||
|
|
||||
LL | struct S5<Y>(Y);
|
||||
| ^ - ...if indirection was used here: `Box<Y>`
|
||||
| |
|
||||
| this could be changed to `Y: ?Sized`...
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
@ -23,6 +23,13 @@ LL | struct Vec<T> {
|
|||
|
|
||||
= help: the trait `std::marker::Sized` is not implemented for `(dyn std::marker::Copy + 'static)`
|
||||
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
|
||||
help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box<T>`
|
||||
--> $DIR/wf-fn-where-clause.rs:16:12
|
||||
|
|
||||
LL | struct Vec<T> {
|
||||
| ^ this could be changed to `T: ?Sized`...
|
||||
LL | t: T,
|
||||
| - ...if indirection was used here: `Box<T>`
|
||||
|
||||
error[E0038]: the trait `std::marker::Copy` cannot be made into an object
|
||||
--> $DIR/wf-fn-where-clause.rs:12:16
|
||||
|
|
Loading…
Reference in a new issue