diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs index 62edfc6495c..55602305090 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs @@ -866,6 +866,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } } + self.report_ambiguous_type_parameter(&mut err, arg); err.span_label( span, arg_data.cannot_infer_msg(use_diag.filter(|d| d.applies_to(span))), @@ -933,6 +934,27 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } } + fn report_ambiguous_type_parameter(&self, err: &mut Diagnostic, arg: GenericArg<'tcx>) { + if let GenericArgKind::Type(ty) = arg.unpack() + && let ty::Infer(ty::TyVar(ty_vid)) = *ty.kind() + { + let mut inner = self.inner.borrow_mut(); + let ty_vars = &inner.type_variables(); + let var_origin = ty_vars.var_origin(ty_vid); + if let TypeVariableOriginKind::TypeParameterDefinition(name, Some(def_id)) = + var_origin.kind + && let Some(parent_def_id) = self.tcx.parent(def_id).as_local() + && let Some(hir::Node::Item(item)) = self.tcx.hir().find_by_def_id(parent_def_id) + && let hir::ItemKind::Impl(impl_item) = item.kind + && let Some(trait_ref) = &impl_item.of_trait + && let Some(did) = trait_ref.trait_def_id() + && self.tcx.generics_of(did).params.iter().any(|param| param.name == name) + { + err.span_help(self.tcx.def_span(def_id), "type parameter declared here"); + } + } + } + pub fn need_type_info_err_in_generator( &self, kind: hir::GeneratorKind, diff --git a/src/test/ui/inference/ambiguous_type_parameter.rs b/src/test/ui/inference/ambiguous_type_parameter.rs new file mode 100644 index 00000000000..dc70ed661d2 --- /dev/null +++ b/src/test/ui/inference/ambiguous_type_parameter.rs @@ -0,0 +1,17 @@ +use std::collections::HashMap; + +trait Store { + fn get_raw(&self, key: &K) -> Option<()>; +} + +struct InMemoryStore; + +impl Store> for InMemoryStore { + fn get_raw(&self, key: &String) -> Option<()> { + None + } +} + +fn main() { + InMemoryStore.get_raw(&String::default()); //~ ERROR type annotations needed +} diff --git a/src/test/ui/inference/ambiguous_type_parameter.stderr b/src/test/ui/inference/ambiguous_type_parameter.stderr new file mode 100644 index 00000000000..47ef1948aee --- /dev/null +++ b/src/test/ui/inference/ambiguous_type_parameter.stderr @@ -0,0 +1,15 @@ +error[E0282]: type annotations needed + --> $DIR/ambiguous_type_parameter.rs:16:19 + | +LL | InMemoryStore.get_raw(&String::default()); + | ^^^^^^^ cannot infer type for type parameter `K` + | +help: type parameter declared here + --> $DIR/ambiguous_type_parameter.rs:9:6 + | +LL | impl Store> for InMemoryStore { + | ^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/traits/not-suggest-non-existing-fully-qualified-path.stderr b/src/test/ui/traits/not-suggest-non-existing-fully-qualified-path.stderr index 65f2d99417f..3c8d7450f96 100644 --- a/src/test/ui/traits/not-suggest-non-existing-fully-qualified-path.stderr +++ b/src/test/ui/traits/not-suggest-non-existing-fully-qualified-path.stderr @@ -16,6 +16,11 @@ LL | a.method(); | | cannot infer type for type parameter `U` | this method call resolves to `U` | +help: type parameter declared here + --> $DIR/not-suggest-non-existing-fully-qualified-path.rs:12:9 + | +LL | impl V for A + | ^ note: multiple `impl`s satisfying `B: I<_>` found --> $DIR/not-suggest-non-existing-fully-qualified-path.rs:5:1 |