about summary refs log tree commit diff
diff options
context:
space:
mode:
authorDylan DPC <99973273+Dylan-DPC@users.noreply.github.com>2022-07-05 10:42:54 +0530
committerGitHub <noreply@github.com>2022-07-05 10:42:54 +0530
commit6a9db39f6ccf25e97d0017a6921d95c3534bd714 (patch)
tree90cbaa160b0cbc580e126a7490b06c14316b7baa
parentd26ccf7067ef5e18154db6e16f6285e2f62371dc (diff)
parentf475e880a4c6b2359ebaef88c844daede9c88fc9 (diff)
downloadrust-6a9db39f6ccf25e97d0017a6921d95c3534bd714.tar.gz
rust-6a9db39f6ccf25e97d0017a6921d95c3534bd714.zip
Rollup merge of #98761 - lcnr:need_type_info-cont, r=estebank
more `need_type_info` improvements

this now deals with macros in suggestions and the source cost computation does what I want for `channel` :tada:

r? ``@estebank``
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs107
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs27
-rw-r--r--compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs11
-rw-r--r--compiler/rustc_typeck/src/check/writeback.rs2
-rw-r--r--src/test/ui/inference/ambiguous_type_parameter.stderr7
-rw-r--r--src/test/ui/inference/cannot-infer-partial-try-return.rs2
-rw-r--r--src/test/ui/inference/cannot-infer-partial-try-return.stderr15
-rw-r--r--src/test/ui/inference/need_type_info/channel.rs19
-rw-r--r--src/test/ui/inference/need_type_info/channel.stderr25
-rw-r--r--src/test/ui/issues/issue-23041.stderr9
-rw-r--r--src/test/ui/issues/issue-24013.stderr9
-rw-r--r--src/test/ui/issues/issue-25368.rs4
-rw-r--r--src/test/ui/issues/issue-25368.stderr14
-rw-r--r--src/test/ui/methods/method-ambig-one-trait-unknown-int-type.stderr6
14 files changed, 167 insertions, 90 deletions
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 07dcf3876c8..4d29fc46946 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
@@ -315,8 +315,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         body_id: Option<hir::BodyId>,
         failure_span: Span,
         arg: GenericArg<'tcx>,
-        // FIXME(#94483): Either use this or remove it.
-        _impl_candidates: Vec<ty::TraitRef<'tcx>>,
         error_code: TypeAnnotationNeeded,
         should_label_span: bool,
     ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
@@ -534,6 +532,23 @@ enum InferSourceKind<'tcx> {
     },
 }
 
+impl<'tcx> InferSource<'tcx> {
+    fn from_expansion(&self) -> bool {
+        let source_from_expansion = match self.kind {
+            InferSourceKind::LetBinding { insert_span, .. }
+            | InferSourceKind::ClosureArg { insert_span, .. }
+            | InferSourceKind::GenericArg { insert_span, .. } => insert_span.from_expansion(),
+            InferSourceKind::FullyQualifiedMethodCall { receiver, .. } => {
+                receiver.span.from_expansion()
+            }
+            InferSourceKind::ClosureReturn { data, should_wrap_expr, .. } => {
+                data.span().from_expansion() || should_wrap_expr.map_or(false, Span::from_expansion)
+            }
+        };
+        source_from_expansion || self.span.from_expansion()
+    }
+}
+
 impl<'tcx> InferSourceKind<'tcx> {
     fn ty_msg(&self, infcx: &InferCtxt<'_, 'tcx>) -> String {
         match *self {
@@ -604,43 +619,65 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
     /// Sources with a small cost are prefer and should result
     /// in a clearer and idiomatic suggestion.
     fn source_cost(&self, source: &InferSource<'tcx>) -> usize {
-        let tcx = self.infcx.tcx;
-
-        fn arg_cost<'tcx>(arg: GenericArg<'tcx>) -> usize {
-            match arg.unpack() {
-                GenericArgKind::Lifetime(_) => 0, // erased
-                GenericArgKind::Type(ty) => ty_cost(ty),
-                GenericArgKind::Const(_) => 3, // some non-zero value
-            }
+        #[derive(Clone, Copy)]
+        struct CostCtxt<'tcx> {
+            tcx: TyCtxt<'tcx>,
         }
-        fn ty_cost<'tcx>(ty: Ty<'tcx>) -> usize {
-            match ty.kind() {
-                ty::Closure(..) => 100,
-                ty::FnDef(..) => 20,
-                ty::FnPtr(..) => 10,
-                ty::Infer(..) => 0,
-                _ => 1,
+        impl<'tcx> CostCtxt<'tcx> {
+            fn arg_cost(self, arg: GenericArg<'tcx>) -> usize {
+                match arg.unpack() {
+                    GenericArgKind::Lifetime(_) => 0, // erased
+                    GenericArgKind::Type(ty) => self.ty_cost(ty),
+                    GenericArgKind::Const(_) => 3, // some non-zero value
+                }
+            }
+            fn ty_cost(self, ty: Ty<'tcx>) -> usize {
+                match *ty.kind() {
+                    ty::Closure(..) => 1000,
+                    ty::FnDef(..) => 150,
+                    ty::FnPtr(..) => 30,
+                    ty::Adt(def, substs) => {
+                        5 + self
+                            .tcx
+                            .generics_of(def.did())
+                            .own_substs_no_defaults(self.tcx, substs)
+                            .iter()
+                            .map(|&arg| self.arg_cost(arg))
+                            .sum::<usize>()
+                    }
+                    ty::Tuple(args) => 5 + args.iter().map(|arg| self.ty_cost(arg)).sum::<usize>(),
+                    ty::Ref(_, ty, _) => 2 + self.ty_cost(ty),
+                    ty::Infer(..) => 0,
+                    _ => 1,
+                }
             }
         }
 
         // The sources are listed in order of preference here.
-        match source.kind {
-            InferSourceKind::LetBinding { ty, .. } => ty_cost(ty),
-            InferSourceKind::ClosureArg { ty, .. } => 5 + ty_cost(ty),
+        let tcx = self.infcx.tcx;
+        let ctx = CostCtxt { tcx };
+        let base_cost = match source.kind {
+            InferSourceKind::LetBinding { ty, .. } => ctx.ty_cost(ty),
+            InferSourceKind::ClosureArg { ty, .. } => ctx.ty_cost(ty),
             InferSourceKind::GenericArg { def_id, generic_args, .. } => {
                 let variant_cost = match tcx.def_kind(def_id) {
-                    DefKind::Variant | DefKind::Ctor(CtorOf::Variant, _) => 15, // `None::<u32>` and friends are ugly.
-                    _ => 12,
+                    // `None::<u32>` and friends are ugly.
+                    DefKind::Variant | DefKind::Ctor(CtorOf::Variant, _) => 15,
+                    _ => 10,
                 };
-                variant_cost + generic_args.iter().map(|&arg| arg_cost(arg)).sum::<usize>()
+                variant_cost + generic_args.iter().map(|&arg| ctx.arg_cost(arg)).sum::<usize>()
             }
             InferSourceKind::FullyQualifiedMethodCall { substs, .. } => {
-                20 + substs.iter().map(|arg| arg_cost(arg)).sum::<usize>()
+                20 + substs.iter().map(|arg| ctx.arg_cost(arg)).sum::<usize>()
             }
             InferSourceKind::ClosureReturn { ty, should_wrap_expr, .. } => {
-                30 + ty_cost(ty) + if should_wrap_expr.is_some() { 10 } else { 0 }
+                30 + ctx.ty_cost(ty) + if should_wrap_expr.is_some() { 10 } else { 0 }
             }
-        }
+        };
+
+        let suggestion_may_apply = if source.from_expansion() { 10000 } else { 0 };
+
+        base_cost + suggestion_may_apply
     }
 
     /// Uses `fn source_cost` to determine whether this inference source is preferable to
@@ -648,6 +685,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
     #[instrument(level = "debug", skip(self))]
     fn update_infer_source(&mut self, new_source: InferSource<'tcx>) {
         let cost = self.source_cost(&new_source) + self.attempt;
+        debug!(?cost);
         self.attempt += 1;
         if cost < self.infer_source_cost {
             self.infer_source_cost = cost;
@@ -655,6 +693,11 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
         }
     }
 
+    fn node_substs_opt(&self, hir_id: HirId) -> Option<SubstsRef<'tcx>> {
+        let substs = self.typeck_results.node_substs_opt(hir_id);
+        self.infcx.resolve_vars_if_possible(substs)
+    }
+
     fn opt_node_type(&self, hir_id: HirId) -> Option<Ty<'tcx>> {
         let ty = self.typeck_results.node_type_opt(hir_id);
         self.infcx.resolve_vars_if_possible(ty)
@@ -737,7 +780,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
         let tcx = self.infcx.tcx;
         match expr.kind {
             hir::ExprKind::Path(ref path) => {
-                if let Some(substs) = self.typeck_results.node_substs_opt(expr.hir_id) {
+                if let Some(substs) = self.node_substs_opt(expr.hir_id) {
                     return self.path_inferred_subst_iter(expr.hir_id, substs, path);
                 }
             }
@@ -765,7 +808,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
                         if generics.has_impl_trait() {
                             None?
                         }
-                        let substs = self.typeck_results.node_substs_opt(expr.hir_id)?;
+                        let substs = self.node_substs_opt(expr.hir_id)?;
                         let span = tcx.hir().span(segment.hir_id?);
                         let insert_span = segment.ident.span.shrink_to_hi().with_hi(span.hi());
                         InsertableGenericArgs {
@@ -980,8 +1023,10 @@ impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> {
             debug!(?args);
             let InsertableGenericArgs { insert_span, substs, generics_def_id, def_id } = args;
             let generics = tcx.generics_of(generics_def_id);
-            if let Some(argument_index) =
-                generics.own_substs(substs).iter().position(|&arg| self.generic_arg_is_target(arg))
+            if let Some(argument_index) = generics
+                .own_substs(substs)
+                .iter()
+                .position(|&arg| self.generic_arg_contains_target(arg))
             {
                 let substs = self.infcx.resolve_vars_if_possible(substs);
                 let generic_args = &generics.own_substs_no_defaults(tcx, substs)
@@ -1037,7 +1082,7 @@ impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> {
             .any(|generics| generics.has_impl_trait())
         };
         if let ExprKind::MethodCall(path, args, span) = expr.kind
-            && let Some(substs) = self.typeck_results.node_substs_opt(expr.hir_id)
+            && let Some(substs) = self.node_substs_opt(expr.hir_id)
             && substs.iter().any(|arg| self.generic_arg_contains_target(arg))
             && let Some(def_id) = self.typeck_results.type_dependent_def_id(expr.hir_id)
             && self.infcx.tcx.trait_of_item(def_id).is_some()
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
index fa56219b409..88b09f4de0a 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -1980,7 +1980,6 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
                             body_id,
                             span,
                             trait_ref.self_ty().skip_binder().into(),
-                            vec![],
                             ErrorCode::E0282,
                             false,
                         )
@@ -2005,19 +2004,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
                 let subst = data.trait_ref.substs.iter().find(|s| s.has_infer_types_or_consts());
 
                 let mut err = if let Some(subst) = subst {
-                    let impl_candidates = self
-                        .find_similar_impl_candidates(trait_ref)
-                        .into_iter()
-                        .map(|candidate| candidate.trait_ref)
-                        .collect();
-                    self.emit_inference_failure_err(
-                        body_id,
-                        span,
-                        subst,
-                        impl_candidates,
-                        ErrorCode::E0283,
-                        true,
-                    )
+                    self.emit_inference_failure_err(body_id, span, subst, ErrorCode::E0283, true)
                 } else {
                     struct_span_err!(
                         self.tcx.sess,
@@ -2117,7 +2104,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
                     return;
                 }
 
-                self.emit_inference_failure_err(body_id, span, arg, vec![], ErrorCode::E0282, false)
+                self.emit_inference_failure_err(body_id, span, arg, ErrorCode::E0282, false)
             }
 
             ty::PredicateKind::Subtype(data) => {
@@ -2131,14 +2118,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
                 let SubtypePredicate { a_is_expected: _, a, b } = data;
                 // both must be type variables, or the other would've been instantiated
                 assert!(a.is_ty_var() && b.is_ty_var());
-                self.emit_inference_failure_err(
-                    body_id,
-                    span,
-                    a.into(),
-                    vec![],
-                    ErrorCode::E0282,
-                    true,
-                )
+                self.emit_inference_failure_err(body_id, span, a.into(), ErrorCode::E0282, true)
             }
             ty::PredicateKind::Projection(data) => {
                 if predicate.references_error() || self.is_tainted_by_errors() {
@@ -2155,7 +2135,6 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
                         body_id,
                         span,
                         subst,
-                        vec![],
                         ErrorCode::E0284,
                         true,
                     );
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
index bce2e85de84..5297c48b4c3 100644
--- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
+++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
@@ -1538,15 +1538,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             ty
         } else {
             if !self.is_tainted_by_errors() {
-                self.emit_inference_failure_err(
-                    (**self).body_id,
-                    sp,
-                    ty.into(),
-                    vec![],
-                    E0282,
-                    true,
-                )
-                .emit();
+                self.emit_inference_failure_err((**self).body_id, sp, ty.into(), E0282, true)
+                    .emit();
             }
             let err = self.tcx.ty_error();
             self.demand_suptype(sp, err, ty);
diff --git a/compiler/rustc_typeck/src/check/writeback.rs b/compiler/rustc_typeck/src/check/writeback.rs
index 67160b98b9d..16e5639096c 100644
--- a/compiler/rustc_typeck/src/check/writeback.rs
+++ b/compiler/rustc_typeck/src/check/writeback.rs
@@ -692,7 +692,6 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> {
                     Some(self.body.id()),
                     self.span.to_span(self.tcx),
                     t.into(),
-                    vec![],
                     E0282,
                     false,
                 )
@@ -707,7 +706,6 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> {
                     Some(self.body.id()),
                     self.span.to_span(self.tcx),
                     c.into(),
-                    vec![],
                     E0282,
                     false,
                 )
diff --git a/src/test/ui/inference/ambiguous_type_parameter.stderr b/src/test/ui/inference/ambiguous_type_parameter.stderr
index a08342371b3..9cbe221de13 100644
--- a/src/test/ui/inference/ambiguous_type_parameter.stderr
+++ b/src/test/ui/inference/ambiguous_type_parameter.stderr
@@ -2,7 +2,12 @@ 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: try using a fully qualified path to specify the expected types
+   |
+LL |     <InMemoryStore as Store<String, HashMap<K, String>>>::get_raw(&InMemoryStore, &String::default());
+   |     +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++             ~
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/inference/cannot-infer-partial-try-return.rs b/src/test/ui/inference/cannot-infer-partial-try-return.rs
index 976827a4478..b555697dc34 100644
--- a/src/test/ui/inference/cannot-infer-partial-try-return.rs
+++ b/src/test/ui/inference/cannot-infer-partial-try-return.rs
@@ -16,8 +16,8 @@ fn infallible() -> Result<(), std::convert::Infallible> {
 
 fn main() {
     let x = || -> Result<_, QualifiedError<_>> {
-        //~^ ERROR type annotations needed for `Result<(), QualifiedError<_>>`
         infallible()?;
         Ok(())
+        //~^ ERROR type annotations needed
     };
 }
diff --git a/src/test/ui/inference/cannot-infer-partial-try-return.stderr b/src/test/ui/inference/cannot-infer-partial-try-return.stderr
index c1e43f0b721..2a56aaa44fe 100644
--- a/src/test/ui/inference/cannot-infer-partial-try-return.stderr
+++ b/src/test/ui/inference/cannot-infer-partial-try-return.stderr
@@ -1,16 +1,15 @@
-error[E0282]: type annotations needed for `Result<(), QualifiedError<_>>`
-  --> $DIR/cannot-infer-partial-try-return.rs:18:13
+error[E0282]: type annotations needed
+  --> $DIR/cannot-infer-partial-try-return.rs:20:9
    |
-LL |     let x = || -> Result<_, QualifiedError<_>> {
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-LL |
 LL |         infallible()?;
    |         ------------- type must be known at this point
+LL |         Ok(())
+   |         ^^ cannot infer type of the type parameter `E` declared on the enum `Result`
    |
-help: try giving this closure an explicit return type
+help: consider specifying the generic arguments
    |
-LL |     let x = || -> Result<(), QualifiedError<_>> {
-   |                   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+LL |         Ok::<(), QualifiedError<_>>(())
+   |           +++++++++++++++++++++++++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/inference/need_type_info/channel.rs b/src/test/ui/inference/need_type_info/channel.rs
new file mode 100644
index 00000000000..e2ba5a94171
--- /dev/null
+++ b/src/test/ui/inference/need_type_info/channel.rs
@@ -0,0 +1,19 @@
+// Test that we suggest specifying the generic argument of `channel`
+// instead of the return type of that function, which is a lot more
+// complex.
+use std::sync::mpsc::channel;
+
+fn no_tuple() {
+    let _data =
+        channel(); //~ ERROR type annotations needed
+}
+
+fn tuple() {
+    let (_sender, _receiver) =
+        channel(); //~ ERROR type annotations needed
+}
+
+fn main() {
+    no_tuple();
+    tuple();
+}
diff --git a/src/test/ui/inference/need_type_info/channel.stderr b/src/test/ui/inference/need_type_info/channel.stderr
new file mode 100644
index 00000000000..e33ace0338d
--- /dev/null
+++ b/src/test/ui/inference/need_type_info/channel.stderr
@@ -0,0 +1,25 @@
+error[E0282]: type annotations needed
+  --> $DIR/channel.rs:8:9
+   |
+LL |         channel();
+   |         ^^^^^^^ cannot infer type of the type parameter `T` declared on the function `channel`
+   |
+help: consider specifying the generic argument
+   |
+LL |         channel::<T>();
+   |                +++++
+
+error[E0282]: type annotations needed
+  --> $DIR/channel.rs:13:9
+   |
+LL |         channel();
+   |         ^^^^^^^ cannot infer type of the type parameter `T` declared on the function `channel`
+   |
+help: consider specifying the generic argument
+   |
+LL |         channel::<T>();
+   |                +++++
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/issues/issue-23041.stderr b/src/test/ui/issues/issue-23041.stderr
index 401086b2044..7b9a1634a0d 100644
--- a/src/test/ui/issues/issue-23041.stderr
+++ b/src/test/ui/issues/issue-23041.stderr
@@ -1,8 +1,13 @@
 error[E0282]: type annotations needed
-  --> $DIR/issue-23041.rs:6:22
+  --> $DIR/issue-23041.rs:6:7
    |
 LL |     b.downcast_ref::<fn(_)->_>();
-   |                      ^^^^^^^^ cannot infer type
+   |       ^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the associated function `downcast_ref`
+   |
+help: consider specifying the generic arguments
+   |
+LL |     b.downcast_ref::<fn(_) -> _>();
+   |                   ~~~~~~~~~~~~~~
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-24013.stderr b/src/test/ui/issues/issue-24013.stderr
index 4e3cb88297d..863993f4509 100644
--- a/src/test/ui/issues/issue-24013.stderr
+++ b/src/test/ui/issues/issue-24013.stderr
@@ -1,8 +1,13 @@
 error[E0282]: type annotations needed
-  --> $DIR/issue-24013.rs:5:20
+  --> $DIR/issue-24013.rs:5:13
    |
 LL |     unsafe {swap::<&mut _>(transmute(&a), transmute(&b))};
-   |                    ^^^^^^ cannot infer type
+   |             ^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `swap`
+   |
+help: consider specifying the generic arguments
+   |
+LL |     unsafe {swap::<&mut _>(transmute(&a), transmute(&b))};
+   |                 ~~~~~~~~~~
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-25368.rs b/src/test/ui/issues/issue-25368.rs
index b7f0f613e80..4be83457f7a 100644
--- a/src/test/ui/issues/issue-25368.rs
+++ b/src/test/ui/issues/issue-25368.rs
@@ -5,10 +5,10 @@ use std::marker::PhantomData;
 struct Foo<T> {foo: PhantomData<T>}
 
 fn main() {
-    let (tx, rx) = //~ ERROR type annotations needed
+    let (tx, rx) =
         channel();
-    // FIXME(#89862): Suggest adding a generic argument to `channel` instead
     spawn(move || {
         tx.send(Foo{ foo: PhantomData });
+        //~^ ERROR type annotations needed
     });
 }
diff --git a/src/test/ui/issues/issue-25368.stderr b/src/test/ui/issues/issue-25368.stderr
index ffcb7384952..e6ed3aac710 100644
--- a/src/test/ui/issues/issue-25368.stderr
+++ b/src/test/ui/issues/issue-25368.stderr
@@ -1,13 +1,13 @@
-error[E0282]: type annotations needed for `(Sender<Foo<T>>, std::sync::mpsc::Receiver<Foo<T>>)`
-  --> $DIR/issue-25368.rs:8:9
+error[E0282]: type annotations needed
+  --> $DIR/issue-25368.rs:11:27
    |
-LL |     let (tx, rx) =
-   |         ^^^^^^^^
+LL |         tx.send(Foo{ foo: PhantomData });
+   |                           ^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the struct `PhantomData`
    |
-help: consider giving this pattern a type, where the type for type parameter `T` is specified
+help: consider specifying the generic argument
    |
-LL |     let (tx, rx): (Sender<Foo<T>>, std::sync::mpsc::Receiver<Foo<T>>) =
-   |                 +++++++++++++++++++++++++++++++++++++++++++++++++++++
+LL |         tx.send(Foo{ foo: PhantomData::<T> });
+   |                                      +++++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/methods/method-ambig-one-trait-unknown-int-type.stderr b/src/test/ui/methods/method-ambig-one-trait-unknown-int-type.stderr
index 66e7ada3ac5..e0f8a5447b0 100644
--- a/src/test/ui/methods/method-ambig-one-trait-unknown-int-type.stderr
+++ b/src/test/ui/methods/method-ambig-one-trait-unknown-int-type.stderr
@@ -13,7 +13,7 @@ error[E0283]: type annotations needed
   --> $DIR/method-ambig-one-trait-unknown-int-type.rs:26:7
    |
 LL |     x.foo();
-   |       ^^^ cannot infer type for struct `Vec<_>`
+   |       ^^^
    |
 note: multiple `impl`s satisfying `Vec<_>: Foo` found
   --> $DIR/method-ambig-one-trait-unknown-int-type.rs:9:1
@@ -23,6 +23,10 @@ LL | impl Foo for Vec<usize> {
 ...
 LL | impl Foo for Vec<isize> {
    | ^^^^^^^^^^^^^^^^^^^^^^^
+help: try using a fully qualified path to specify the expected types
+   |
+LL |     <Vec<T> as Foo>::foo(&x);
+   |     ++++++++++++++++++++++ ~
 
 error[E0308]: mismatched types
   --> $DIR/method-ambig-one-trait-unknown-int-type.rs:33:20