From 1a68ed498e91ec3be3f60cf9e3097373335fe653 Mon Sep 17 00:00:00 2001 From: Nikita Krupitskas Date: Sat, 5 Sep 2020 09:33:44 +0300 Subject: [PATCH] Initial approach --- .../src/traits/error_reporting/mod.rs | 8 ++- .../src/traits/error_reporting/suggestions.rs | 58 ++++++++++++++++++- 2 files changed, 64 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index dcd8379803319..5b2550ed625e3 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -685,6 +685,11 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { _ => None, }; + let found_node = match found_did { + Some(found_did) => self.tcx.hir().get_if_local(found_did), + None => None, + }; + let found_span = found_did .and_then(|did| self.tcx.hir().span_if_local(did)) .map(|sp| self.tcx.sess.source_map().guess_head_span(sp)); // the sp could be an fn def @@ -694,7 +699,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { // but we want to complain about them only once. return; } - + self.reported_closure_mismatch.borrow_mut().insert((span, found_span)); let found = match found_trait_ref.skip_binder().substs.type_at(1).kind() { @@ -717,6 +722,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { found_span, found_trait_ref, expected_trait_ref, + found_node, ) } else { let (closure_span, found) = found_did diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 82e809d014dd0..695539cd30ba6 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -14,6 +14,8 @@ use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::Visitor; use rustc_hir::lang_items::LangItem; +use rustc_hir::ExprKind; +// use rustc_hir::TyKind; use rustc_hir::{AsyncGeneratorKind, GeneratorKind, Node}; use rustc_middle::ty::{ self, suggest_constraining_type_param, AdtKind, DefIdTree, Infer, InferTy, ToPredicate, Ty, @@ -121,6 +123,7 @@ pub trait InferCtxtExt<'tcx> { found_span: Option, expected_ref: ty::PolyTraitRef<'tcx>, found: ty::PolyTraitRef<'tcx>, + found_node: Option>, ) -> DiagnosticBuilder<'tcx>; fn suggest_fully_qualified_path( @@ -907,7 +910,11 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { _ => return None, }; - if let hir::FnRetTy::Return(ret_ty) = sig.decl.output { Some(ret_ty.span) } else { None } + if let hir::FnRetTy::Return(ret_ty) = sig.decl.output { + Some(ret_ty.span) + } else { + None + } } /// If all conditions are met to identify a returned `dyn Trait`, suggest using `impl Trait` if @@ -1145,6 +1152,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { found_span: Option, expected_ref: ty::PolyTraitRef<'tcx>, found: ty::PolyTraitRef<'tcx>, + found_node: Option>, ) -> DiagnosticBuilder<'tcx> { crate fn build_fn_sig_string<'tcx>( tcx: TyCtxt<'tcx>, @@ -1193,6 +1201,54 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { ); err.span_label(found_span, expected_str); + if let Some(node) = found_node { + match node { + Node::Expr(param) => match param.kind { + ExprKind::Closure(_, _fn_decl_input, _, _, _) => { + // Input are in closure with _fn_decl_input inputs itself + let expected = expected_ref.skip_binder().substs.type_at(1); // ? + + // let inputs = expected_ref.skip_binder().substs.type_at(1); + // let sig = if let ty::Tuple(inputs) = inputs.kind() { + // inputs.iter().map(|k| k.expect_ty()) + // } else { + // ::std::iter::once(inputs) + // }; + + match expected.kind() { + ty::Closure(_did, substs) => { + let msg = format!( + "closure -> & {:?}", + substs + ); + err.span_suggestion_verbose( + span.shrink_to_lo(), + "hint: add missing borrow here:", + msg, + Applicability::MaybeIncorrect, + ); + } + ty::Ref(_region, ty, _) => { + let msg = format!( + "ref -> & {:?}", + ty + ); + err.span_suggestion_verbose( + span.shrink_to_lo(), + "hint: add missing borrow here:", + msg, + Applicability::MaybeIncorrect, + ); + } + _ => {} + } + } + _ => {} + }, + _ => {} + } + }; + err }