review comments and rebase fix
This commit is contained in:
parent
d8d02f8f18
commit
c93c660b0d
2 changed files with 70 additions and 48 deletions
|
|
@ -10,7 +10,7 @@ use rustc_middle::ty::adjustment::{
|
|||
Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability,
|
||||
};
|
||||
use rustc_middle::ty::TyKind::{Adt, Array, Char, FnDef, Never, Ref, Str, Tuple, Uint};
|
||||
use rustc_middle::ty::{self, suggest_constraining_type_param, Ty, TypeFoldable};
|
||||
use rustc_middle::ty::{self, suggest_constraining_type_param, Ty, TyCtxt, TypeFoldable};
|
||||
use rustc_span::Span;
|
||||
use rustc_trait_selection::infer::InferCtxtExt;
|
||||
|
||||
|
|
@ -254,49 +254,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
if !lhs_ty.references_error() {
|
||||
let source_map = self.tcx.sess.source_map();
|
||||
|
||||
let suggest_constraining_param =
|
||||
|mut err: &mut DiagnosticBuilder<'_>,
|
||||
missing_trait: &str,
|
||||
p: ty::ParamTy,
|
||||
set_output: bool| {
|
||||
let hir = self.tcx.hir();
|
||||
let msg =
|
||||
&format!("`{}` might need a bound for `{}`", lhs_ty, missing_trait);
|
||||
if let Some(def_id) = hir
|
||||
.find(hir.get_parent_item(expr.hir_id))
|
||||
.and_then(|node| node.hir_id())
|
||||
.and_then(|hir_id| hir.opt_local_def_id(hir_id))
|
||||
{
|
||||
let generics = self.tcx.generics_of(def_id);
|
||||
let param_def_id = generics.type_param(&p, self.tcx).def_id;
|
||||
if let Some(generics) = hir
|
||||
.as_local_hir_id(param_def_id)
|
||||
.and_then(|id| hir.find(hir.get_parent_item(id)))
|
||||
.as_ref()
|
||||
.and_then(|node| node.generics())
|
||||
{
|
||||
let output = if set_output {
|
||||
format!("<Output = {}>", rhs_ty)
|
||||
} else {
|
||||
String::new()
|
||||
};
|
||||
suggest_constraining_type_param(
|
||||
self.tcx,
|
||||
generics,
|
||||
&mut err,
|
||||
&format!("{}", lhs_ty),
|
||||
&format!("{}{}", missing_trait, output),
|
||||
None,
|
||||
);
|
||||
} else {
|
||||
let span = self.tcx.def_span(param_def_id);
|
||||
err.span_label(span, msg);
|
||||
}
|
||||
} else {
|
||||
err.note(&msg);
|
||||
}
|
||||
};
|
||||
|
||||
match is_assign {
|
||||
IsAssign::Yes => {
|
||||
let mut err = struct_span_err!(
|
||||
|
|
@ -362,7 +319,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
// concatenation (e.g., "Hello " += "World!"). This means
|
||||
// we don't want the note in the else clause to be emitted
|
||||
} else if let ty::Param(p) = lhs_ty.kind {
|
||||
suggest_constraining_param(&mut err, missing_trait, p, false);
|
||||
suggest_constraining_param(
|
||||
self.tcx,
|
||||
&mut err,
|
||||
lhs_ty,
|
||||
rhs_ty,
|
||||
&expr,
|
||||
missing_trait,
|
||||
p,
|
||||
false,
|
||||
);
|
||||
} else if !suggested_deref {
|
||||
suggest_impl_missing(&mut err, lhs_ty, &missing_trait);
|
||||
}
|
||||
|
|
@ -514,7 +480,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
// we don't want the note in the else clause to be emitted
|
||||
} else if let ty::Param(p) = lhs_ty.kind {
|
||||
suggest_constraining_param(
|
||||
self.tcx,
|
||||
&mut err,
|
||||
lhs_ty,
|
||||
rhs_ty,
|
||||
&expr,
|
||||
missing_trait,
|
||||
p,
|
||||
use_output,
|
||||
|
|
@ -965,3 +935,49 @@ fn suggest_impl_missing(err: &mut DiagnosticBuilder<'_>, ty: Ty<'_>, missing_tra
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn suggest_constraining_param(
|
||||
tcx: TyCtxt<'_>,
|
||||
mut err: &mut DiagnosticBuilder<'_>,
|
||||
lhs_ty: Ty<'_>,
|
||||
rhs_ty: Ty<'_>,
|
||||
expr: &hir::Expr<'_>,
|
||||
missing_trait: &str,
|
||||
p: ty::ParamTy,
|
||||
set_output: bool,
|
||||
) {
|
||||
let hir = tcx.hir();
|
||||
let msg = &format!("`{}` might need a bound for `{}`", lhs_ty, missing_trait);
|
||||
// Try to find the def-id and details for the parameter p. We have only the index,
|
||||
// so we have to find the enclosing function's def-id, then look through its declared
|
||||
// generic parameters to get the declaration.
|
||||
if let Some(def_id) = hir
|
||||
.find(hir.get_parent_item(expr.hir_id))
|
||||
.and_then(|node| node.hir_id())
|
||||
.and_then(|hir_id| hir.opt_local_def_id(hir_id))
|
||||
{
|
||||
let generics = tcx.generics_of(def_id);
|
||||
let param_def_id = generics.type_param(&p, tcx).def_id;
|
||||
if let Some(generics) = hir
|
||||
.as_local_hir_id(param_def_id)
|
||||
.and_then(|id| hir.find(hir.get_parent_item(id)))
|
||||
.as_ref()
|
||||
.and_then(|node| node.generics())
|
||||
{
|
||||
let output = if set_output { format!("<Output = {}>", rhs_ty) } else { String::new() };
|
||||
suggest_constraining_type_param(
|
||||
tcx,
|
||||
generics,
|
||||
&mut err,
|
||||
&format!("{}", lhs_ty),
|
||||
&format!("{}{}", missing_trait, output),
|
||||
None,
|
||||
);
|
||||
} else {
|
||||
let span = tcx.def_span(param_def_id);
|
||||
err.span_label(span, msg);
|
||||
}
|
||||
} else {
|
||||
err.note(&msg);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,12 +5,18 @@ LL | trait From<Src> {
|
|||
| --- required by this bound in `From`
|
||||
...
|
||||
LL | ) -> <Dst as From<Self>>::Result where Dst: From<Self> {
|
||||
| ^^^^^^^^^^- help: consider further restricting `Self`: `, Self: std::marker::Sized`
|
||||
| |
|
||||
| doesn't have a size known at compile-time
|
||||
| ^^^^^^^^^^ doesn't have a size known at compile-time
|
||||
|
|
||||
= 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 | ) -> <Dst as From<Self>>::Result where Dst: From<Self>, Self: std::marker::Sized {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
help: consider relaxing the implicit `Sized` restriction
|
||||
|
|
||||
LL | trait From<Src: ?Sized> {
|
||||
| ^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue