Suggest a FnPtr type if a FnDef type is found
This commit is contained in:
parent
f687d5c43a
commit
79dc9a76a6
3 changed files with 74 additions and 39 deletions
|
@ -9,7 +9,7 @@ use rustc_hir::{HirId, Node};
|
|||
use rustc_middle::hir::map::Map;
|
||||
use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts};
|
||||
use rustc_middle::ty::util::IntTypeExt;
|
||||
use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt, TypeFoldable};
|
||||
use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt, TypeFoldable, TypeFolder};
|
||||
use rustc_span::symbol::Ident;
|
||||
use rustc_span::{Span, DUMMY_SP};
|
||||
|
||||
|
@ -749,15 +749,38 @@ fn infer_placeholder_type(
|
|||
span: Span,
|
||||
item_ident: Ident,
|
||||
) -> Ty<'_> {
|
||||
fn contains_anonymous(ty: Ty<'_>) -> bool {
|
||||
for gen_arg in ty.walk() {
|
||||
if let ty::subst::GenericArgKind::Type(inner_ty) = gen_arg.unpack() {
|
||||
if let ty::FnDef(..) | ty::Closure(..) | ty::Generator(..) = inner_ty.kind() {
|
||||
return true;
|
||||
// Attempts to make the type nameable by turning FnDefs into FnPtrs.
|
||||
struct MakeNameable<'tcx> {
|
||||
success: bool,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
}
|
||||
|
||||
impl<'tcx> MakeNameable<'tcx> {
|
||||
fn new(tcx: TyCtxt<'tcx>) -> Self {
|
||||
MakeNameable { success: true, tcx }
|
||||
}
|
||||
}
|
||||
|
||||
impl TypeFolder<'tcx> for MakeNameable<'tcx> {
|
||||
fn tcx(&self) -> TyCtxt<'tcx> {
|
||||
self.tcx
|
||||
}
|
||||
|
||||
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
|
||||
if !self.success {
|
||||
return ty;
|
||||
}
|
||||
|
||||
match ty.kind() {
|
||||
ty::FnDef(def_id, _) => self.tcx.mk_fn_ptr(self.tcx.fn_sig(*def_id)),
|
||||
// FIXME: non-capturing closures should also suggest a function pointer
|
||||
ty::Closure(..) | ty::Generator(..) => {
|
||||
self.success = false;
|
||||
ty
|
||||
}
|
||||
_ => ty.super_fold_with(self),
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
let ty = tcx.diagnostic_only_typeck(def_id).node_type(body_id.hir_id);
|
||||
|
@ -773,11 +796,14 @@ fn infer_placeholder_type(
|
|||
err.suggestions.clear();
|
||||
|
||||
// Suggesting unnameable types won't help.
|
||||
if !contains_anonymous(ty) {
|
||||
let mut mk_nameable = MakeNameable::new(tcx);
|
||||
let ty = mk_nameable.fold_ty(ty);
|
||||
let sugg_ty = if mk_nameable.success { Some(ty) } else { None };
|
||||
if let Some(sugg_ty) = sugg_ty {
|
||||
err.span_suggestion(
|
||||
span,
|
||||
"provide a type for the item",
|
||||
format!("{}: {}", item_ident, ty),
|
||||
format!("{}: {}", item_ident, sugg_ty),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
} else {
|
||||
|
@ -793,11 +819,14 @@ fn infer_placeholder_type(
|
|||
let mut diag = bad_placeholder_type(tcx, vec![span]);
|
||||
|
||||
if !ty.references_error() {
|
||||
if !contains_anonymous(ty) {
|
||||
let mut mk_nameable = MakeNameable::new(tcx);
|
||||
let ty = mk_nameable.fold_ty(ty);
|
||||
let sugg_ty = if mk_nameable.success { Some(ty) } else { None };
|
||||
if let Some(sugg_ty) = sugg_ty {
|
||||
diag.span_suggestion(
|
||||
span,
|
||||
"replace with the correct type",
|
||||
ty.to_string(),
|
||||
sugg_ty.to_string(),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
} else {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue