Handle more cases involving `impl` and `trait`
This commit is contained in:
parent
5b7ffd9333
commit
dbd75c8c40
|
@ -969,90 +969,103 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
trait_ref: &ty::PolyTraitRef<'_>,
|
||||
body_id: hir::HirId,
|
||||
) {
|
||||
let node = self.tcx.hir()
|
||||
.find(self.tcx.hir().get_parent_item(body_id))
|
||||
.or_else(|| self.tcx.hir().find(body_id));
|
||||
debug!(
|
||||
"suggest_restricting_param_bound node={:?} - trait_ref={:?} ty={:?} ({:?})",
|
||||
node,
|
||||
"suggest_restricting_param_bound trait_ref={:?} ty={:?} ({:?})",
|
||||
trait_ref,
|
||||
trait_ref.self_ty(),
|
||||
trait_ref.self_ty().kind,
|
||||
);
|
||||
if let ty::Param(param_ty) = &trait_ref.self_ty().kind {
|
||||
let restrict_msg = "consider further restricting this bound";
|
||||
let param_name = param_ty.name.as_str();
|
||||
let param_ty = if let ty::Param(param_ty) = &trait_ref.self_ty().kind {
|
||||
param_ty
|
||||
} else {
|
||||
err.help(&format!("consider adding a `where {}` bound", trait_ref.to_predicate()));
|
||||
return;
|
||||
};
|
||||
|
||||
if let Some(hir::Node::Item(hir::Item {
|
||||
kind: hir::ItemKind::Struct(_, generics), span, ..
|
||||
})) |
|
||||
Some(hir::Node::Item(hir::Item {
|
||||
kind: hir::ItemKind::Enum(_, generics), span, ..
|
||||
})) |
|
||||
Some(hir::Node::Item(hir::Item {
|
||||
kind: hir::ItemKind::Union(_, generics), span, ..
|
||||
})) |
|
||||
Some(hir::Node::Item(hir::Item {
|
||||
kind: hir::ItemKind::Trait(_, _, generics, ..), span, ..
|
||||
})) |
|
||||
Some(hir::Node::Item(hir::Item {
|
||||
kind: hir::ItemKind::Impl(_, _, _, generics, ..), span, ..
|
||||
})) |
|
||||
Some(hir::Node::Item(hir::Item {
|
||||
kind: hir::ItemKind::Fn(_, _, generics, _), span, ..
|
||||
})) = &node {
|
||||
for param in &generics.params {
|
||||
if param_name == param.name.ident().as_str() {
|
||||
if param_name.starts_with("impl ") {
|
||||
err.span_suggestion(
|
||||
param.span,
|
||||
restrict_msg,
|
||||
// `impl CurrentTrait + MissingTrait`
|
||||
format!("{} + {}", param.name.ident(), trait_ref),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
} else {
|
||||
if generics.where_clause.predicates.is_empty() &&
|
||||
param.bounds.is_empty()
|
||||
{
|
||||
let mut hir_id = body_id;
|
||||
while let Some(node) = self.tcx.hir().find(hir_id) {
|
||||
debug!("suggest_restricting_param_bound node={:?}", node);
|
||||
match node {
|
||||
hir::Node::Item(hir::Item { kind: hir::ItemKind::Struct(_, generics), span, .. }) |
|
||||
hir::Node::Item(hir::Item { kind: hir::ItemKind::Enum(_, generics), span, .. }) |
|
||||
hir::Node::Item(hir::Item { kind: hir::ItemKind::Union(_, generics), span, .. }) |
|
||||
hir::Node::Item(hir::Item {
|
||||
kind: hir::ItemKind::Trait(_, _, generics, ..), span, ..
|
||||
}) |
|
||||
hir::Node::Item(hir::Item {
|
||||
kind: hir::ItemKind::Impl(_, _, _, generics, ..), span, ..
|
||||
}) |
|
||||
hir::Node::Item(hir::Item {
|
||||
kind: hir::ItemKind::Fn(_, _, generics, _), span, ..
|
||||
}) |
|
||||
hir::Node::Item(hir::Item {
|
||||
kind: hir::ItemKind::TyAlias(_, generics), span, ..
|
||||
}) |
|
||||
hir::Node::Item(hir::Item {
|
||||
kind: hir::ItemKind::OpaqueTy(hir::OpaqueTy { generics, .. }), span, ..
|
||||
}) |
|
||||
hir::Node::TraitItem(hir::TraitItem { generics, span, .. }) |
|
||||
hir::Node::ImplItem(hir::ImplItem { generics, span, .. }) => {
|
||||
let restrict_msg = "consider further restricting this bound";
|
||||
let param_name = param_ty.name.as_str();
|
||||
for param in &generics.params {
|
||||
if param_name == param.name.ident().as_str() {
|
||||
if param_name.starts_with("impl ") {
|
||||
err.span_suggestion(
|
||||
param.span,
|
||||
"consider restricting this bound",
|
||||
format!("{}", trait_ref.to_predicate()),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
} else if !generics.where_clause.predicates.is_empty() {
|
||||
err.span_suggestion(
|
||||
generics.where_clause.span().unwrap().shrink_to_hi(),
|
||||
&format!(
|
||||
"consider further restricting type parameter `{}`",
|
||||
param_ty,
|
||||
),
|
||||
format!(", {}", trait_ref.to_predicate()),
|
||||
restrict_msg,
|
||||
// `impl CurrentTrait + MissingTrait`
|
||||
format!("{} + {}", param.name.ident(), trait_ref),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
} else {
|
||||
let sp = param.span.with_hi(span.hi());
|
||||
let span = self.tcx.sess.source_map().span_through_char(sp, ':');
|
||||
if sp != param.span && sp != span {
|
||||
// Only suggest if we have high certainty that the span covers
|
||||
// the colon in `foo<T: Trait>`.
|
||||
err.span_suggestion(span, restrict_msg, format!(
|
||||
"{} + ",
|
||||
trait_ref.to_predicate(),
|
||||
), Applicability::MachineApplicable);
|
||||
if generics.where_clause.predicates.is_empty() &&
|
||||
param.bounds.is_empty()
|
||||
{
|
||||
err.span_suggestion(
|
||||
param.span,
|
||||
"consider restricting this bound",
|
||||
format!("{}", trait_ref.to_predicate()),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
} else if !generics.where_clause.predicates.is_empty() {
|
||||
err.span_suggestion(
|
||||
generics.where_clause.span().unwrap().shrink_to_hi(),
|
||||
&format!(
|
||||
"consider further restricting type parameter `{}`",
|
||||
param_ty,
|
||||
),
|
||||
format!(", {}", trait_ref.to_predicate()),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
} else {
|
||||
err.span_label(param.span, &format!(
|
||||
"consider adding a `where {}` bound",
|
||||
trait_ref.to_predicate(),
|
||||
));
|
||||
let sp = param.span.with_hi(span.hi());
|
||||
let span = self.tcx.sess.source_map()
|
||||
.span_through_char(sp, ':');
|
||||
if sp != param.span && sp != span {
|
||||
// Only suggest if we have high certainty that the span
|
||||
// covers the colon in `foo<T: Trait>`.
|
||||
err.span_suggestion(span, restrict_msg, format!(
|
||||
"{} + ",
|
||||
trait_ref.to_predicate(),
|
||||
), Applicability::MachineApplicable);
|
||||
} else {
|
||||
err.span_label(param.span, &format!(
|
||||
"consider adding a `where {}` bound",
|
||||
trait_ref.to_predicate(),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
hir::Node::Crate => return,
|
||||
_ => {}
|
||||
}
|
||||
|
||||
hir_id = self.tcx.hir().get_parent_item(hir_id);
|
||||
}
|
||||
// FIXME: Add special check for `?Sized` so we don't suggest `T: Sized + ?Sized`.
|
||||
|
||||
|
|
|
@ -2,9 +2,10 @@ error[E0277]: the trait bound `T: Get` is not satisfied
|
|||
--> $DIR/associated-types-no-suitable-bound.rs:11:5
|
||||
|
|
||||
LL | fn uhoh<T>(foo: <T as Get>::Value) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `T`
|
||||
|
|
||||
= help: consider adding a `where T: Get` bound
|
||||
| ^^^^^^^^-^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| | |
|
||||
| | help: consider restricting this bound: `T: Get`
|
||||
| the trait `Get` is not implemented for `T`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
@ -16,26 +16,30 @@ error[E0277]: the size for values of type `A` cannot be known at compilation tim
|
|||
|
|
||||
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`
|
||||
...
|
||||
LL | [5; Self::HOST_SIZE] == [6; 0]
|
||||
| ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
||||
|
|
||||
= help: the trait `std::marker::Sized` is not implemented for `A`
|
||||
= 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 adding a `where A: std::marker::Sized` bound
|
||||
|
||||
error[E0277]: the size for values of type `B` cannot be known at compilation time
|
||||
--> $DIR/too_generic_eval_ice.rs:7:13
|
||||
|
|
||||
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`
|
||||
...
|
||||
LL | [5; Self::HOST_SIZE] == [6; 0]
|
||||
| ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
||||
|
|
||||
= help: the trait `std::marker::Sized` is not implemented for `B`
|
||||
= 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 adding a `where B: std::marker::Sized` bound
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
error[E0277]: the trait bound `S: std::marker::Copy` is not satisfied in `(S, T)`
|
||||
--> $DIR/issue-55872-1.rs:12:5
|
||||
|
|
||||
LL | impl<S: Default> Bar for S {
|
||||
| -- help: consider further restricting this bound: `S: std::marker::Copy +`
|
||||
LL | type E = impl Copy;
|
||||
| ^^^^^^^^^^^^^^^^^^^ within `(S, T)`, the trait `std::marker::Copy` is not implemented for `S`
|
||||
|
|
||||
= help: consider adding a `where S: std::marker::Copy` bound
|
||||
= note: required because it appears within the type `(S, T)`
|
||||
= note: the return type of a function must have a statically known size
|
||||
|
||||
|
@ -13,8 +14,10 @@ error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied in `(S, T)
|
|||
|
|
||||
LL | type E = impl Copy;
|
||||
| ^^^^^^^^^^^^^^^^^^^ within `(S, T)`, the trait `std::marker::Copy` is not implemented for `T`
|
||||
...
|
||||
LL | fn foo<T: Default>() -> Self::E {
|
||||
| -- help: consider further restricting this bound: `T: std::marker::Copy +`
|
||||
|
|
||||
= help: consider adding a `where T: std::marker::Copy` bound
|
||||
= note: required because it appears within the type `(S, T)`
|
||||
= note: the return type of a function must have a statically known size
|
||||
|
||||
|
|
|
@ -4,10 +4,11 @@ error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
|
|||
LL | fn require_copy<T: Copy>(x: T) {}
|
||||
| ------------ ---- required by this bound in `require_copy`
|
||||
...
|
||||
LL | impl<T> Foo<T> {
|
||||
| - help: consider restricting this bound: `T: std::marker::Copy`
|
||||
...
|
||||
LL | require_copy(self.x);
|
||||
| ^^^^^^ the trait `std::marker::Copy` is not implemented for `T`
|
||||
|
|
||||
= help: consider adding a `where T: std::marker::Copy` bound
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
@ -4,10 +4,11 @@ error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
|
|||
LL | fn require_copy<T: Copy>(x: T) {}
|
||||
| ------------ ---- required by this bound in `require_copy`
|
||||
...
|
||||
LL | impl<T> Foo<T> for Bar<T> {
|
||||
| - help: consider restricting this bound: `T: std::marker::Copy`
|
||||
...
|
||||
LL | require_copy(self.x);
|
||||
| ^^^^^^ the trait `std::marker::Copy` is not implemented for `T`
|
||||
|
|
||||
= help: consider adding a `where T: std::marker::Copy` bound
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
Loading…
Reference in New Issue