|
1 | 1 | //! Error Reporting for `impl` items that do not match the obligations from their `trait`.
|
2 | 2 |
|
| 3 | +use crate::hir::def_id::DefId; |
3 | 4 | use crate::infer::error_reporting::nice_region_error::NiceRegionError;
|
4 | 5 | use crate::infer::lexical_region_resolve::RegionResolutionError;
|
5 | 6 | use crate::infer::{Subtype, ValuePairs};
|
6 | 7 | use crate::traits::ObligationCauseCode::CompareImplMethodObligation;
|
| 8 | +use rustc_data_structures::fx::FxHashSet; |
7 | 9 | use rustc_errors::ErrorReported;
|
8 |
| -use rustc_middle::ty::Ty; |
| 10 | +use rustc_middle::ty::error::ExpectedFound; |
| 11 | +use rustc_middle::ty::fold::TypeFoldable; |
| 12 | +use rustc_middle::ty::{self, Ty}; |
9 | 13 | use rustc_span::Span;
|
10 | 14 |
|
11 | 15 | impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
@@ -52,9 +56,52 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
52 | 56 | .tcx()
|
53 | 57 | .sess
|
54 | 58 | .struct_span_err(sp, "`impl` item signature doesn't match `trait` item signature");
|
55 |
| - err.note(&format!("expected `{:?}`\n found `{:?}`", expected, found)); |
56 | 59 | err.span_label(sp, &format!("found {:?}", found));
|
57 | 60 | err.span_label(impl_sp, &format!("expected {:?}", expected));
|
| 61 | + |
| 62 | + struct EarlyBoundRegionHighlighter(FxHashSet<DefId>); |
| 63 | + impl<'tcx> ty::fold::TypeVisitor<'tcx> for EarlyBoundRegionHighlighter { |
| 64 | + fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool { |
| 65 | + debug!("LateBoundRegionNameCollector visit_region {:?}", r); |
| 66 | + match *r { |
| 67 | + ty::ReFree(free) => { |
| 68 | + self.0.insert(free.scope); |
| 69 | + } |
| 70 | + |
| 71 | + ty::ReEarlyBound(bound) => { |
| 72 | + self.0.insert(bound.def_id); |
| 73 | + } |
| 74 | + _ => {} |
| 75 | + } |
| 76 | + r.super_visit_with(self) |
| 77 | + } |
| 78 | + } |
| 79 | + |
| 80 | + let mut visitor = EarlyBoundRegionHighlighter(FxHashSet::default()); |
| 81 | + expected.visit_with(&mut visitor); |
| 82 | + |
| 83 | + let note = !visitor.0.is_empty(); |
| 84 | + |
| 85 | + if let Some((expected, found)) = self |
| 86 | + .tcx() |
| 87 | + .infer_ctxt() |
| 88 | + .enter(|infcx| infcx.expected_found_str_ty(&ExpectedFound { expected, found })) |
| 89 | + { |
| 90 | + err.note_expected_found(&"", expected, &"", found); |
| 91 | + } else { |
| 92 | + // This fallback shouldn't be necessary, but let's keep it in just in case. |
| 93 | + err.note(&format!("expected `{:?}`\n found `{:?}`", expected, found)); |
| 94 | + } |
| 95 | + if note { |
| 96 | + err.note( |
| 97 | + "the lifetime requirements from the `trait` could not be fulfilled by the \ |
| 98 | + `impl`", |
| 99 | + ); |
| 100 | + err.help( |
| 101 | + "consider adding a named lifetime to the `trait` that constrains the item's \ |
| 102 | + `self` argument, its inputs and its output with it", |
| 103 | + ); |
| 104 | + } |
58 | 105 | err.emit();
|
59 | 106 | }
|
60 | 107 | }
|
0 commit comments