about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/mod.rs39
-rw-r--r--compiler/rustc_middle/src/ty/error.rs6
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs56
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs10
-rw-r--r--compiler/rustc_typeck/src/check/cast.rs6
-rw-r--r--compiler/rustc_typeck/src/check/check.rs8
-rw-r--r--compiler/rustc_typeck/src/check/compare_method.rs8
-rw-r--r--compiler/rustc_typeck/src/check/wfcheck.rs3
8 files changed, 117 insertions, 19 deletions
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index c3f2213229a..1e3f9f7464d 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -1430,6 +1430,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         }
     }
 
+    /// Extend a type error with extra labels pointing at "non-trivial" types, like closures and
+    /// the return type of `async fn`s.
+    ///
+    /// `secondary_span` gives the caller the opportunity to expand `diag` with a `span_label`.
+    ///
+    /// `swap_secondary_and_primary` is used to make projection errors in particular nicer by using
+    /// the message in `secondary_span` as the primary label, and apply the message that would
+    /// otherwise be used for the primary label on the `secondary_span` `Span`. This applies on
+    /// E0271, like `src/test/ui/issues/issue-39970.stderr`.
     pub fn note_type_err(
         &self,
         diag: &mut DiagnosticBuilder<'tcx>,
@@ -1437,6 +1446,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         secondary_span: Option<(Span, String)>,
         mut values: Option<ValuePairs<'tcx>>,
         terr: &TypeError<'tcx>,
+        swap_secondary_and_primary: bool,
     ) {
         let span = cause.span(self.tcx);
         debug!("note_type_err cause={:?} values={:?}, terr={:?}", cause, values, terr);
@@ -1613,9 +1623,32 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         match terr {
             TypeError::ObjectUnsafeCoercion(_) => {}
             _ => {
-                diag.span_label(span, terr.to_string());
+                let mut label_or_note = |span: Span, msg: &str| {
+                    if &[span] == diag.span.primary_spans() {
+                        diag.span_label(span, msg);
+                    } else {
+                        diag.span_note(span, msg);
+                    }
+                };
                 if let Some((sp, msg)) = secondary_span {
-                    diag.span_label(sp, msg);
+                    if swap_secondary_and_primary {
+                        let terr = if let Some(infer::ValuePairs::Types(infer::ExpectedFound {
+                            expected,
+                            ..
+                        })) = values
+                        {
+                            format!("expected this to be `{}`", expected)
+                        } else {
+                            terr.to_string()
+                        };
+                        label_or_note(sp, &terr);
+                        label_or_note(span, &msg);
+                    } else {
+                        label_or_note(span, &terr.to_string());
+                        label_or_note(sp, &msg);
+                    }
+                } else {
+                    label_or_note(span, &terr.to_string());
                 }
             }
         };
@@ -2049,7 +2082,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                 struct_span_err!(self.tcx.sess, span, E0644, "{}", failure_str)
             }
         };
-        self.note_type_err(&mut diag, &trace.cause, None, Some(trace.values), terr);
+        self.note_type_err(&mut diag, &trace.cause, None, Some(trace.values), terr, false);
         diag
     }
 
diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs
index bda40a9abb0..1b4566fd026 100644
--- a/compiler/rustc_middle/src/ty/error.rs
+++ b/compiler/rustc_middle/src/ty/error.rs
@@ -118,8 +118,7 @@ impl<'tcx> fmt::Display for TypeError<'tcx> {
             ArgumentMutability(_) | Mutability => write!(f, "types differ in mutability"),
             TupleSize(values) => write!(
                 f,
-                "expected a tuple with {} element{}, \
-                           found one with {} element{}",
+                "expected a tuple with {} element{}, found one with {} element{}",
                 values.expected,
                 pluralize!(values.expected),
                 values.found,
@@ -127,8 +126,7 @@ impl<'tcx> fmt::Display for TypeError<'tcx> {
             ),
             FixedArraySize(values) => write!(
                 f,
-                "expected an array with a fixed size of {} element{}, \
-                           found one with {} element{}",
+                "expected an array with a fixed size of {} element{}, found one with {} element{}",
                 values.expected,
                 pluralize!(values.expected),
                 values.found,
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 d9f86fbc23b..645295d4839 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -1338,7 +1338,46 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
                     "type mismatch resolving `{}`",
                     predicate
                 );
-                self.note_type_err(&mut diag, &obligation.cause, None, values, err);
+                let secondary_span = match predicate.kind().skip_binder() {
+                    ty::PredicateKind::Projection(proj) => self
+                        .tcx
+                        .opt_associated_item(proj.projection_ty.item_def_id)
+                        .and_then(|trait_assoc_item| {
+                            self.tcx
+                                .trait_of_item(proj.projection_ty.item_def_id)
+                                .map(|id| (trait_assoc_item, id))
+                        })
+                        .and_then(|(trait_assoc_item, id)| {
+                            self.tcx.find_map_relevant_impl(
+                                id,
+                                proj.projection_ty.self_ty(),
+                                |did| {
+                                    self.tcx
+                                        .associated_items(did)
+                                        .in_definition_order()
+                                        .filter(|assoc| assoc.ident == trait_assoc_item.ident)
+                                        .next()
+                                },
+                            )
+                        })
+                        .and_then(|item| match self.tcx.hir().get_if_local(item.def_id) {
+                            Some(
+                                hir::Node::TraitItem(hir::TraitItem {
+                                    kind: hir::TraitItemKind::Type(_, Some(ty)),
+                                    ..
+                                })
+                                | hir::Node::ImplItem(hir::ImplItem {
+                                    kind: hir::ImplItemKind::TyAlias(ty),
+                                    ..
+                                }),
+                            ) => {
+                                Some((ty.span, format!("type mismatch resolving `{}`", predicate)))
+                            }
+                            _ => None,
+                        }),
+                    _ => None,
+                };
+                self.note_type_err(&mut diag, &obligation.cause, secondary_span, values, err, true);
                 self.note_obligation_cause(&mut diag, obligation);
                 diag.emit();
             }
@@ -2095,10 +2134,21 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
     ) -> bool {
         if let ObligationCauseCode::BuiltinDerivedObligation(ref data) = cause_code {
             let parent_trait_ref = self.resolve_vars_if_possible(data.parent_trait_ref);
-
-            if obligated_types.iter().any(|ot| ot == &parent_trait_ref.skip_binder().self_ty()) {
+            let self_ty = parent_trait_ref.skip_binder().self_ty();
+            if obligated_types.iter().any(|ot| ot == &self_ty) {
                 return true;
             }
+            if let ty::Adt(def, substs) = self_ty.kind() {
+                if let [arg] = &substs[..] {
+                    if let ty::subst::GenericArgKind::Type(ty) = arg.unpack() {
+                        if let ty::Adt(inner_def, _) = ty.kind() {
+                            if inner_def == def {
+                                return true;
+                            }
+                        }
+                    }
+                }
+            }
         }
         false
     }
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
index d0b61b24308..db76ade296b 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -2186,6 +2186,16 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                             seen_requirements,
                         )
                     });
+                } else {
+                    ensure_sufficient_stack(|| {
+                        self.note_obligation_cause_code(
+                            err,
+                            &parent_predicate,
+                            &cause_code.peel_derives(),
+                            obligated_types,
+                            seen_requirements,
+                        )
+                    });
                 }
             }
             ObligationCauseCode::ImplDerivedObligation(ref data) => {
diff --git a/compiler/rustc_typeck/src/check/cast.rs b/compiler/rustc_typeck/src/check/cast.rs
index 511a2d7ddac..a397ee771af 100644
--- a/compiler/rustc_typeck/src/check/cast.rs
+++ b/compiler/rustc_typeck/src/check/cast.rs
@@ -638,7 +638,11 @@ impl<'a, 'tcx> CastCheck<'tcx> {
         self.expr_ty = fcx.structurally_resolved_type(self.expr.span, self.expr_ty);
         self.cast_ty = fcx.structurally_resolved_type(self.cast_span, self.cast_ty);
 
-        if !fcx.type_is_known_to_be_sized_modulo_regions(self.cast_ty, self.span) {
+        debug!("check_cast({}, {:?} as {:?})", self.expr.hir_id, self.expr_ty, self.cast_ty);
+
+        if !fcx.type_is_known_to_be_sized_modulo_regions(self.cast_ty, self.span)
+            && !self.cast_ty.has_infer_types()
+        {
             self.report_cast_to_unsized_type(fcx);
         } else if self.expr_ty.references_error() || self.cast_ty.references_error() {
             // No sense in giving duplicate error messages
diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs
index a6b16e7f0d4..4e06608be5d 100644
--- a/compiler/rustc_typeck/src/check/check.rs
+++ b/compiler/rustc_typeck/src/check/check.rs
@@ -730,7 +730,7 @@ pub fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, it: &'tcx hir::Item<'tcx>) {
                         let abi = sig.header.abi;
                         fn_maybe_err(tcx, item.ident.span, abi);
                     }
-                    hir::TraitItemKind::Type(.., Some(_default)) => {
+                    hir::TraitItemKind::Type(.., Some(default)) => {
                         let assoc_item = tcx.associated_item(item.def_id);
                         let trait_substs =
                             InternalSubsts::identity_for_item(tcx, it.def_id.to_def_id());
@@ -738,7 +738,7 @@ pub fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, it: &'tcx hir::Item<'tcx>) {
                             tcx,
                             assoc_item,
                             assoc_item,
-                            item.span,
+                            default.span,
                             ty::TraitRef { def_id: it.def_id.to_def_id(), substs: trait_substs },
                         );
                     }
@@ -987,12 +987,12 @@ pub(super) fn check_impl_items_against_trait<'tcx>(
                         opt_trait_span,
                     );
                 }
-                hir::ImplItemKind::TyAlias(_) => {
+                hir::ImplItemKind::TyAlias(impl_ty) => {
                     let opt_trait_span = tcx.hir().span_if_local(ty_trait_item.def_id);
                     compare_ty_impl(
                         tcx,
                         &ty_impl_item,
-                        impl_item.span,
+                        impl_ty.span,
                         &ty_trait_item,
                         impl_trait_ref,
                         opt_trait_span,
diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs
index 44fc81a889d..6af0312f313 100644
--- a/compiler/rustc_typeck/src/check/compare_method.rs
+++ b/compiler/rustc_typeck/src/check/compare_method.rs
@@ -379,6 +379,7 @@ fn compare_predicate_entailment<'tcx>(
                     found: impl_fty,
                 })),
                 &terr,
+                false,
             );
             diag.emit();
             return Err(ErrorReported);
@@ -734,8 +735,7 @@ fn compare_number_of_method_arguments<'tcx>(
             tcx.sess,
             impl_span,
             E0050,
-            "method `{}` has {} but the declaration in \
-                                        trait `{}` has {}",
+            "method `{}` has {} but the declaration in trait `{}` has {}",
             trait_m.ident,
             potentially_plural_count(impl_number_args, "parameter"),
             tcx.def_path_str(trait_m.def_id),
@@ -1069,6 +1069,7 @@ crate fn compare_const_impl<'tcx>(
                     found: impl_ty,
                 })),
                 &terr,
+                false,
             );
             diag.emit();
         }
@@ -1099,7 +1100,8 @@ crate fn compare_ty_impl<'tcx>(
     let _: Result<(), ErrorReported> = (|| {
         compare_number_of_generics(tcx, impl_ty, impl_ty_span, trait_ty, trait_item_span)?;
 
-        compare_type_predicate_entailment(tcx, impl_ty, impl_ty_span, trait_ty, impl_trait_ref)?;
+        let sp = tcx.def_span(impl_ty.def_id);
+        compare_type_predicate_entailment(tcx, impl_ty, sp, trait_ty, impl_trait_ref)?;
 
         check_type_bounds(tcx, trait_ty, impl_ty, impl_ty_span, impl_trait_ref)
     })();
diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs
index 1fc88829c77..17f07d0877e 100644
--- a/compiler/rustc_typeck/src/check/wfcheck.rs
+++ b/compiler/rustc_typeck/src/check/wfcheck.rs
@@ -683,7 +683,8 @@ pub fn check_impl_item(tcx: TyCtxt<'_>, def_id: LocalDefId) {
 
     let (method_sig, span) = match impl_item.kind {
         hir::ImplItemKind::Fn(ref sig, _) => (Some(sig), impl_item.span),
-        hir::ImplItemKind::TyAlias(ty) => (None, ty.span),
+        // Constrain binding and overflow error spans to `<Ty>` in `type foo = <Ty>`.
+        hir::ImplItemKind::TyAlias(ty) if ty.span != DUMMY_SP => (None, ty.span),
         _ => (None, impl_item.span),
     };