Skip to content

Don't suggest unnameable generic arguments #99580

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

Merged
merged 1 commit into from
Jul 23, 2022
Merged
Show file tree
Hide file tree
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
41 changes: 35 additions & 6 deletions compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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,
);
Expand Down
18 changes: 13 additions & 5 deletions compiler/rustc_middle/src/ty/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};

Expand Down Expand Up @@ -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()
}
}

Expand All @@ -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;
}

Expand Down Expand Up @@ -419,13 +422,16 @@ 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> {
type BreakTy = ();

fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
match t.kind() {
Infer(InferTy::TyVar(_)) if self.infer_suggestable => {}

FnDef(..)
| Closure(..)
| Infer(..)
Expand Down Expand Up @@ -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(..)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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`.
Expand Down Expand Up @@ -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;
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_typeck/src/astconv/generics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_typeck/src/astconv/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
7 changes: 6 additions & 1 deletion compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -507,7 +507,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
Expand Down
9 changes: 7 additions & 2 deletions compiler/rustc_typeck/src/collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -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",
Expand Down
7 changes: 7 additions & 0 deletions src/test/ui/closures/issue-99565.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#![crate_type = "lib"]

fn foo<T, U>(_: U) {}

fn bar() {
foo(|| {}); //~ ERROR type annotations needed
}
14 changes: 14 additions & 0 deletions src/test/ui/closures/issue-99565.stderr
Original file line number Diff line number Diff line change
@@ -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`.
2 changes: 1 addition & 1 deletion src/test/ui/issues/issue-23041.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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(_) -> _>();
| ~~~~~~~~~~~~~~
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/issues/issue-24013.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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))};
| ~~~~~~~~~~
Expand Down