]> git.lizzy.rs Git - rust.git/blobdiff - compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
drive-by: Fix path spans
[rust.git] / compiler / rustc_infer / src / infer / error_reporting / need_type_info.rs
index 4f9e069c1763d08789c78175be6c926fe3e3d8fa..a4c36b4c9cd59db580517b60f8d887ca2bcd40eb 100644 (file)
@@ -20,7 +20,7 @@
 use rustc_middle::ty::{self, DefIdTree, InferConst};
 use rustc_middle::ty::{GenericArg, GenericArgKind, SubstsRef};
 use rustc_middle::ty::{IsSuggestable, Ty, TyCtxt, TypeckResults};
-use rustc_span::symbol::{kw, Ident};
+use rustc_span::symbol::{kw, sym, Ident};
 use rustc_span::{BytePos, Span};
 use std::borrow::Cow;
 use std::iter;
@@ -79,7 +79,7 @@ fn can_add_more_info(&self) -> bool {
 
     fn where_x_is_kind(&self, in_type: Ty<'_>) -> &'static str {
         if in_type.is_ty_infer() {
-            "empty"
+            ""
         } else if self.name == "_" {
             // FIXME: Consider specializing this message if there is a single `_`
             // in the type.
@@ -183,13 +183,24 @@ fn fmt_printer<'a, 'tcx>(infcx: &'a InferCtxt<'tcx>, ns: Namespace) -> FmtPrinte
     printer
 }
 
-fn ty_to_string<'tcx>(infcx: &InferCtxt<'tcx>, ty: Ty<'tcx>) -> String {
+fn ty_to_string<'tcx>(
+    infcx: &InferCtxt<'tcx>,
+    ty: Ty<'tcx>,
+    called_method_def_id: Option<DefId>,
+) -> String {
     let printer = fmt_printer(infcx, Namespace::TypeNS);
     let ty = infcx.resolve_vars_if_possible(ty);
-    match ty.kind() {
+    match (ty.kind(), called_method_def_id) {
         // We don't want the regular output for `fn`s because it includes its path in
         // invalid pseudo-syntax, we want the `fn`-pointer output instead.
-        ty::FnDef(..) => ty.fn_sig(infcx.tcx).print(printer).unwrap().into_buffer(),
+        (ty::FnDef(..), _) => ty.fn_sig(infcx.tcx).print(printer).unwrap().into_buffer(),
+        (_, Some(def_id))
+            if ty.is_ty_infer()
+                && infcx.tcx.get_diagnostic_item(sym::iterator_collect_fn) == Some(def_id) =>
+        {
+            "Vec<_>".to_string()
+        }
+        _ if ty.is_ty_infer() => "/* Type */".to_string(),
         // FIXME: The same thing for closures, but this only works when the closure
         // does not capture anything.
         //
@@ -213,7 +224,7 @@ fn closure_as_fn_str<'tcx>(infcx: &InferCtxt<'tcx>, ty: Ty<'tcx>) -> String {
         .map(|args| {
             args.tuple_fields()
                 .iter()
-                .map(|arg| ty_to_string(infcx, arg))
+                .map(|arg| ty_to_string(infcx, arg, None))
                 .collect::<Vec<_>>()
                 .join(", ")
         })
@@ -221,7 +232,7 @@ fn closure_as_fn_str<'tcx>(infcx: &InferCtxt<'tcx>, ty: Ty<'tcx>) -> String {
     let ret = if fn_sig.output().skip_binder().is_unit() {
         String::new()
     } else {
-        format!(" -> {}", ty_to_string(infcx, fn_sig.output().skip_binder()))
+        format!(" -> {}", ty_to_string(infcx, fn_sig.output().skip_binder(), None))
     };
     format!("fn({}){}", args, ret)
 }
@@ -368,6 +379,7 @@ fn bad_inference_failure_err(
 }
 
 impl<'tcx> TypeErrCtxt<'_, 'tcx> {
+    #[instrument(level = "debug", skip(self, error_code))]
     pub fn emit_inference_failure_err(
         &self,
         body_id: Option<hir::BodyId>,
@@ -406,7 +418,7 @@ pub fn emit_inference_failure_err(
         let mut infer_subdiags = Vec::new();
         let mut multi_suggestions = Vec::new();
         match kind {
-            InferSourceKind::LetBinding { insert_span, pattern_name, ty } => {
+            InferSourceKind::LetBinding { insert_span, pattern_name, ty, def_id } => {
                 infer_subdiags.push(SourceKindSubdiag::LetLike {
                     span: insert_span,
                     name: pattern_name.map(|name| name.to_string()).unwrap_or_else(String::new),
@@ -415,7 +427,7 @@ pub fn emit_inference_failure_err(
                     prefix: arg_data.kind.try_get_prefix().unwrap_or_default(),
                     arg_name: arg_data.name,
                     kind: if pattern_name.is_some() { "with_pattern" } else { "other" },
-                    type_name: ty_to_string(self, ty),
+                    type_name: ty_to_string(self, ty, def_id),
                 });
             }
             InferSourceKind::ClosureArg { insert_span, ty } => {
@@ -427,7 +439,7 @@ pub fn emit_inference_failure_err(
                     prefix: arg_data.kind.try_get_prefix().unwrap_or_default(),
                     arg_name: arg_data.name,
                     kind: "closure",
-                    type_name: ty_to_string(self, ty),
+                    type_name: ty_to_string(self, ty, None),
                 });
             }
             InferSourceKind::GenericArg {
@@ -456,33 +468,39 @@ pub fn emit_inference_failure_err(
                     parent_name,
                 });
 
-                let args = fmt_printer(self, Namespace::TypeNS)
-                    .comma_sep(generic_args.iter().copied().map(|arg| {
-                        if arg.is_suggestable(self.tcx, true) {
-                            return arg;
-                        }
+                let args = if self.infcx.tcx.get_diagnostic_item(sym::iterator_collect_fn)
+                    == Some(generics_def_id)
+                {
+                    "Vec<_>".to_string()
+                } else {
+                    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 {
+                            match arg.unpack() {
+                                GenericArgKind::Lifetime(_) => bug!("unexpected lifetime"),
+                                GenericArgKind::Type(_) => self
+                                    .next_ty_var(TypeVariableOrigin {
                                         span: rustc_span::DUMMY_SP,
-                                        kind: ConstVariableOriginKind::MiscVariable,
-                                    },
-                                )
-                                .into(),
-                        }
-                    }))
-                    .unwrap()
-                    .into_buffer();
+                                        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()
+                };
 
                 if !have_turbofish {
                     infer_subdiags.push(SourceKindSubdiag::GenericSuggestion {
@@ -520,7 +538,7 @@ pub fn emit_inference_failure_err(
                 ));
             }
             InferSourceKind::ClosureReturn { ty, data, should_wrap_expr } => {
-                let ty_info = ty_to_string(self, ty);
+                let ty_info = ty_to_string(self, ty, None);
                 multi_suggestions.push(SourceKindMultiSuggestion::new_closure_return(
                     ty_info,
                     data,
@@ -608,6 +626,7 @@ enum InferSourceKind<'tcx> {
         insert_span: Span,
         pattern_name: Option<Ident>,
         ty: Ty<'tcx>,
+        def_id: Option<DefId>,
     },
     ClosureArg {
         insert_span: Span,
@@ -662,7 +681,7 @@ fn ty_localized_msg(&self, infcx: &InferCtxt<'tcx>) -> (&'static str, String) {
                 if ty.is_closure() {
                     ("closure", closure_as_fn_str(infcx, ty))
                 } else if !ty.is_ty_infer() {
-                    ("normal", ty_to_string(infcx, ty))
+                    ("normal", ty_to_string(infcx, ty, None))
                 } else {
                     ("other", String::new())
                 }
@@ -788,10 +807,18 @@ fn ty_cost(self, ty: Ty<'tcx>) -> usize {
     /// Uses `fn source_cost` to determine whether this inference source is preferable to
     /// previous sources. We generally prefer earlier sources.
     #[instrument(level = "debug", skip(self))]
-    fn update_infer_source(&mut self, new_source: InferSource<'tcx>) {
+    fn update_infer_source(&mut self, mut new_source: InferSource<'tcx>) {
         let cost = self.source_cost(&new_source) + self.attempt;
         debug!(?cost);
         self.attempt += 1;
+        if let Some(InferSource { kind: InferSourceKind::GenericArg { def_id: did, ..}, .. }) = self.infer_source
+            && let InferSourceKind::LetBinding { ref ty, ref mut def_id, ..} = new_source.kind
+            && ty.is_ty_infer()
+        {
+            // Customize the output so we talk about `let x: Vec<_> = iter.collect();` instead of
+            // `let x: _ = iter.collect();`, as this is a very common case.
+            *def_id = Some(did);
+        }
         if cost < self.infer_source_cost {
             self.infer_source_cost = cost;
             self.infer_source = Some(new_source);
@@ -1092,6 +1119,7 @@ fn visit_local(&mut self, local: &'tcx Local<'tcx>) {
                                 insert_span: local.pat.span.shrink_to_hi(),
                                 pattern_name: local.pat.simple_ident(),
                                 ty,
+                                def_id: None,
                             },
                         })
                     }