]> git.lizzy.rs Git - rust.git/blobdiff - compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs
Rollup merge of #85766 - workingjubilee:file-options, r=yaahc
[rust.git] / compiler / rustc_infer / src / infer / error_reporting / nice_region_error / trait_impl_difference.rs
index ea9d0eae17e2c46b27a713da65513ef1351e6af9..cfa79213c805ce683e5f524bda74e7de27e14629 100644 (file)
@@ -9,10 +9,13 @@
 use rustc_hir::def::Res;
 use rustc_hir::def_id::DefId;
 use rustc_hir::intravisit::Visitor;
-use rustc_middle::ty::error::ExpectedFound;
-use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_middle::ty::print::RegionHighlightMode;
+use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeVisitor};
+
 use rustc_span::{MultiSpan, Span, Symbol};
 
+use std::ops::ControlFlow;
+
 impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
     /// Print the error message for lifetime errors when the `impl` doesn't conform to the `trait`.
     pub(super) fn try_report_impl_not_conforming_to_trait(&self) -> Option<ErrorReported> {
@@ -51,12 +54,16 @@ pub(super) fn try_report_impl_not_conforming_to_trait(&self) -> Option<ErrorRepo
         {
             if let SubregionOrigin::CompareImplTypeObligation {
                 span,
-                item_name,
                 impl_item_def_id,
                 trait_item_def_id,
             } = origin
             {
-                self.emit_associated_type_err(span, item_name, impl_item_def_id, trait_item_def_id);
+                self.emit_associated_type_err(
+                    span,
+                    self.infcx.tcx.item_name(impl_item_def_id),
+                    impl_item_def_id,
+                    trait_item_def_id,
+                );
                 return Some(ErrorReported);
             }
         }
@@ -69,6 +76,47 @@ fn emit_err(&self, sp: Span, expected: Ty<'tcx>, found: Ty<'tcx>, trait_def_id:
             .tcx()
             .sess
             .struct_span_err(sp, "`impl` item signature doesn't match `trait` item signature");
+
+        // Mark all unnamed regions in the type with a number.
+        // This diagnostic is called in response to lifetime errors, so be informative.
+        struct HighlightBuilder<'tcx> {
+            highlight: RegionHighlightMode,
+            tcx: TyCtxt<'tcx>,
+            counter: usize,
+        }
+
+        impl HighlightBuilder<'tcx> {
+            fn build(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> RegionHighlightMode {
+                let mut builder =
+                    HighlightBuilder { highlight: RegionHighlightMode::default(), counter: 1, tcx };
+                builder.visit_ty(ty);
+                builder.highlight
+            }
+        }
+
+        impl<'tcx> ty::fold::TypeVisitor<'tcx> for HighlightBuilder<'tcx> {
+            fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
+                Some(self.tcx)
+            }
+
+            fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
+                if !r.has_name() && self.counter <= 3 {
+                    self.highlight.highlighting_region(r, self.counter);
+                    self.counter += 1;
+                }
+                r.super_visit_with(self)
+            }
+        }
+
+        let expected_highlight = HighlightBuilder::build(self.tcx(), expected);
+        let expected = self
+            .infcx
+            .extract_inference_diagnostics_data(expected.into(), Some(expected_highlight))
+            .name;
+        let found_highlight = HighlightBuilder::build(self.tcx(), found);
+        let found =
+            self.infcx.extract_inference_diagnostics_data(found.into(), Some(found_highlight)).name;
+
         err.span_label(sp, &format!("found `{}`", found));
         err.span_label(trait_sp, &format!("expected `{}`", expected));
 
@@ -96,15 +144,8 @@ fn emit_err(&self, sp: Span, expected: Ty<'tcx>, found: Ty<'tcx>, trait_def_id:
             );
         }
 
-        if let Some((expected, found)) =
-            self.infcx.expected_found_str_ty(ExpectedFound { expected, found })
-        {
-            // Highlighted the differences when showing the "expected/found" note.
-            err.note_expected_found(&"", expected, &"", found);
-        } else {
-            // This fallback shouldn't be necessary, but let's keep it in just in case.
-            err.note(&format!("expected `{}`\n   found `{}`", expected, found));
-        }
+        err.note(&format!("expected `{}`\n   found `{}`", expected, found));
+
         err.span_help(
             type_param_span,
             "the lifetime requirements from the `impl` do not correspond to the requirements in \