Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simpler diagnostic when passing arg to closure and missing borrow #76362

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Initial approach
krupitskas committed Sep 8, 2020
commit 1a68ed498e91ec3be3f60cf9e3097373335fe653
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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<Span>,
expected_ref: ty::PolyTraitRef<'tcx>,
found: ty::PolyTraitRef<'tcx>,
found_node: Option<Node<'tcx>>,
) -> 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<Span>,
expected_ref: ty::PolyTraitRef<'tcx>,
found: ty::PolyTraitRef<'tcx>,
found_node: Option<Node<'tcx>>,
) -> 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
}