1
Fork 0

Rollup merge of #99580 - fmease:fix-issue-99565, r=estebank

Don't suggest unnameable generic arguments

Fixes #99565.

`@rustbot` label T-compiler A-diagnostics
r? `@rust-lang/wg-diagnostics`
This commit is contained in:
Matthias Krüger 2022-07-23 12:08:11 +02:00 committed by GitHub
commit b6d6f100a1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 90 additions and 22 deletions

View file

@ -1,4 +1,4 @@
use crate::infer::type_variable::TypeVariableOriginKind;
use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use crate::infer::InferCtxt;
use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed};
use rustc_hir as hir;
@ -8,12 +8,12 @@ use rustc_hir::def_id::DefId;
use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::{Body, Closure, Expr, ExprKind, FnRetTy, HirId, Local, LocalSource};
use rustc_middle::hir::nested_filter;
use rustc_middle::infer::unify_key::ConstVariableOriginKind;
use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability};
use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter, Print, Printer};
use rustc_middle::ty::subst::{GenericArg, GenericArgKind, Subst, SubstsRef};
use rustc_middle::ty::{self, DefIdTree, InferConst};
use rustc_middle::ty::{Ty, TyCtxt, TypeckResults};
use rustc_middle::ty::{IsSuggestable, Ty, TyCtxt, TypeckResults};
use rustc_span::symbol::{kw, Ident};
use rustc_span::{BytePos, Span};
use std::borrow::Cow;
@ -407,11 +407,40 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
err.span_label(span, cannot_infer_msg);
let printer = fmt_printer(self, Namespace::TypeNS);
let args = printer.comma_sep(generic_args.iter().copied()).unwrap().into_buffer();
let args = fmt_printer(self, Namespace::TypeNS)
.comma_sep(generic_args.iter().copied().map(|arg| {
if arg.is_suggestable(self.tcx, true) {
return arg;
}
match arg.unpack() {
GenericArgKind::Lifetime(_) => bug!("unexpected lifetime"),
GenericArgKind::Type(_) => self
.next_ty_var(TypeVariableOrigin {
span: rustc_span::DUMMY_SP,
kind: TypeVariableOriginKind::MiscVariable,
})
.into(),
GenericArgKind::Const(arg) => self
.next_const_var(
arg.ty(),
ConstVariableOrigin {
span: rustc_span::DUMMY_SP,
kind: ConstVariableOriginKind::MiscVariable,
},
)
.into(),
}
}))
.unwrap()
.into_buffer();
err.span_suggestion_verbose(
insert_span,
&format!("consider specifying the generic argument{}", pluralize!(args.len()),),
&format!(
"consider specifying the generic argument{}",
pluralize!(generic_args.len()),
),
format!("::<{}>", args),
Applicability::HasPlaceholders,
);

View file

@ -3,7 +3,7 @@
use std::ops::ControlFlow;
use crate::ty::{
visit::TypeVisitable, Const, ConstKind, DefIdTree, ExistentialPredicate, InferTy,
visit::TypeVisitable, Const, ConstKind, DefIdTree, ExistentialPredicate, InferConst, InferTy,
PolyTraitPredicate, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor,
};
@ -82,15 +82,18 @@ pub trait IsSuggestable<'tcx> {
/// meaningful rendered suggestions when pretty-printed. We leave some
/// nonsense, such as region vars, since those render as `'_` and are
/// usually okay to reinterpret as elided lifetimes.
fn is_suggestable(self, tcx: TyCtxt<'tcx>) -> bool;
///
/// Only if `infer_suggestable` is true, we consider type and const
/// inference variables to be suggestable.
fn is_suggestable(self, tcx: TyCtxt<'tcx>, infer_suggestable: bool) -> bool;
}
impl<'tcx, T> IsSuggestable<'tcx> for T
where
T: TypeVisitable<'tcx>,
{
fn is_suggestable(self, tcx: TyCtxt<'tcx>) -> bool {
self.visit_with(&mut IsSuggestableVisitor { tcx }).is_continue()
fn is_suggestable(self, tcx: TyCtxt<'tcx>, infer_suggestable: bool) -> bool {
self.visit_with(&mut IsSuggestableVisitor { tcx, infer_suggestable }).is_continue()
}
}
@ -100,7 +103,7 @@ pub fn suggest_arbitrary_trait_bound<'tcx>(
err: &mut Diagnostic,
trait_pred: PolyTraitPredicate<'tcx>,
) -> bool {
if !trait_pred.is_suggestable(tcx) {
if !trait_pred.is_suggestable(tcx, false) {
return false;
}
@ -419,6 +422,7 @@ impl<'v> hir::intravisit::Visitor<'v> for StaticLifetimeVisitor<'v> {
pub struct IsSuggestableVisitor<'tcx> {
tcx: TyCtxt<'tcx>,
infer_suggestable: bool,
}
impl<'tcx> TypeVisitor<'tcx> for IsSuggestableVisitor<'tcx> {
@ -426,6 +430,8 @@ impl<'tcx> TypeVisitor<'tcx> for IsSuggestableVisitor<'tcx> {
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
match t.kind() {
Infer(InferTy::TyVar(_)) if self.infer_suggestable => {}
FnDef(..)
| Closure(..)
| Infer(..)
@ -479,6 +485,8 @@ impl<'tcx> TypeVisitor<'tcx> for IsSuggestableVisitor<'tcx> {
fn visit_const(&mut self, c: Const<'tcx>) -> ControlFlow<Self::BreakTy> {
match c.kind() {
ConstKind::Infer(InferConst::Var(_)) if self.infer_suggestable => {}
ConstKind::Infer(..)
| ConstKind::Bound(..)
| ConstKind::Placeholder(..)

View file

@ -378,7 +378,7 @@ fn suggest_restriction<'tcx>(
replace_ty: ty::ParamTy::new(generics.count() as u32, Symbol::intern(&type_param_name))
.to_ty(tcx),
});
if !trait_pred.is_suggestable(tcx) {
if !trait_pred.is_suggestable(tcx, false) {
return;
}
// We know we have an `impl Trait` that doesn't satisfy a required projection.
@ -417,7 +417,7 @@ fn suggest_restriction<'tcx>(
Applicability::MaybeIncorrect,
);
} else {
if !trait_pred.is_suggestable(tcx) {
if !trait_pred.is_suggestable(tcx, false) {
return;
}
// Trivial case: `T` needs an extra bound: `T: Bound`.
@ -586,7 +586,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
// else in the predicate.
if !trait_pred.skip_binder().trait_ref.substs[1..]
.iter()
.all(|g| g.is_suggestable(self.tcx))
.all(|g| g.is_suggestable(self.tcx, false))
{
return;
}

View file

@ -86,7 +86,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let param_type = tcx.infer_ctxt().enter(|infcx| {
infcx.resolve_numeric_literals_with_default(tcx.type_of(param.def_id))
});
if param_type.is_suggestable(tcx) {
if param_type.is_suggestable(tcx, false) {
err.span_suggestion(
tcx.def_span(src_def_id),
"consider changing this type parameter to be a `const` generic",

View file

@ -2676,7 +2676,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
span,
ty,
opt_sugg: Some((span, Applicability::MachineApplicable))
.filter(|_| ty.is_suggestable(tcx)),
.filter(|_| ty.is_suggestable(tcx, false)),
});
ty

View file

@ -1070,7 +1070,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let (_, expected_ty) = formal_and_expected_inputs[expected_idx];
if expected_ty.is_unit() {
"()".to_string()
} else if expected_ty.is_suggestable(tcx) {
} else if expected_ty.is_suggestable(tcx, false) {
format!("/* {} */", expected_ty)
} else {
"/* value */".to_string()

View file

@ -506,7 +506,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.resolve_numeric_literals_with_default(self.resolve_vars_if_possible(found));
// Only suggest changing the return type for methods that
// haven't set a return type at all (and aren't `fn main()` or an impl).
match (&fn_decl.output, found.is_suggestable(self.tcx), can_suggest, expected.is_unit()) {
match (
&fn_decl.output,
found.is_suggestable(self.tcx, false),
can_suggest,
expected.is_unit(),
) {
(&hir::FnRetTy::DefaultReturn(span), true, true, true) => {
err.subdiagnostic(AddReturnTypeSuggestion::Add { span, found });
true

View file

@ -1929,7 +1929,7 @@ fn infer_return_ty_for_fn_sig<'tcx>(
visitor.visit_ty(ty);
let mut diag = bad_placeholder(tcx, visitor.0, "return type");
let ret_ty = fn_sig.skip_binder().output();
if ret_ty.is_suggestable(tcx) {
if ret_ty.is_suggestable(tcx, false) {
diag.span_suggestion(
ty.span,
"replace with the correct return type",
@ -1938,7 +1938,12 @@ fn infer_return_ty_for_fn_sig<'tcx>(
);
} else if matches!(ret_ty.kind(), ty::FnDef(..)) {
let fn_sig = ret_ty.fn_sig(tcx);
if fn_sig.skip_binder().inputs_and_output.iter().all(|t| t.is_suggestable(tcx)) {
if fn_sig
.skip_binder()
.inputs_and_output
.iter()
.all(|t| t.is_suggestable(tcx, false))
{
diag.span_suggestion(
ty.span,
"replace with the correct return type",

View file

@ -0,0 +1,7 @@
#![crate_type = "lib"]
fn foo<T, U>(_: U) {}
fn bar() {
foo(|| {}); //~ ERROR type annotations needed
}

View file

@ -0,0 +1,14 @@
error[E0282]: type annotations needed
--> $DIR/issue-99565.rs:6:5
|
LL | foo(|| {});
| ^^^ cannot infer type of the type parameter `T` declared on the function `foo`
|
help: consider specifying the generic arguments
|
LL | foo::<T, _>(|| {});
| ++++++++
error: aborting due to previous error
For more information about this error, try `rustc --explain E0282`.

View file

@ -4,7 +4,7 @@ error[E0282]: type annotations needed
LL | b.downcast_ref::<fn(_)->_>();
| ^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the associated function `downcast_ref`
|
help: consider specifying the generic arguments
help: consider specifying the generic argument
|
LL | b.downcast_ref::<fn(_) -> _>();
| ~~~~~~~~~~~~~~

View file

@ -4,7 +4,7 @@ error[E0282]: type annotations needed
LL | unsafe {swap::<&mut _>(transmute(&a), transmute(&b))};
| ^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `swap`
|
help: consider specifying the generic arguments
help: consider specifying the generic argument
|
LL | unsafe {swap::<&mut _>(transmute(&a), transmute(&b))};
| ~~~~~~~~~~