Skip to content

Commit

Permalink
review comments and rebase fix
Browse files Browse the repository at this point in the history
  • Loading branch information
estebank committed May 4, 2020
1 parent d8d02f8 commit c93c660
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 48 deletions.
106 changes: 61 additions & 45 deletions src/librustc_typeck/check/op.rs
Expand Up @@ -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;

Expand Down Expand Up @@ -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!(
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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);
}
}
12 changes: 9 additions & 3 deletions src/test/ui/issues/issue-20005.stderr
Expand Up @@ -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

Expand Down

0 comments on commit c93c660

Please sign in to comment.