]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs
New upstream version 1.68.2+dfsg1
[rustc.git] / compiler / rustc_infer / src / infer / error_reporting / nice_region_error / trait_impl_difference.rs
CommitLineData
e74abb32
XL
1//! Error Reporting for `impl` items that do not match the obligations from their `trait`.
2
9c376795 3use crate::errors::{ConsiderBorrowingParamHelp, RelationshipHelp, TraitImplDiff};
e74abb32
XL
4use crate::infer::error_reporting::nice_region_error::NiceRegionError;
5use crate::infer::lexical_region_resolve::RegionResolutionError;
9c376795 6use crate::infer::{Subtype, ValuePairs};
064997fb 7use crate::traits::ObligationCauseCode::CompareImplItemObligation;
9c376795 8use rustc_errors::ErrorGuaranteed;
f9f354fc
XL
9use rustc_hir as hir;
10use rustc_hir::def::Res;
064997fb 11use rustc_hir::def_id::DefId;
f9f354fc 12use rustc_hir::intravisit::Visitor;
5099ac24 13use rustc_middle::hir::nested_filter;
9c376795 14use rustc_middle::ty::error::ExpectedFound;
3c0e092e 15use rustc_middle::ty::print::RegionHighlightMode;
064997fb
FG
16use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor};
17use rustc_span::Span;
e74abb32 18
3c0e092e
XL
19use std::ops::ControlFlow;
20
e74abb32
XL
21impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
22 /// Print the error message for lifetime errors when the `impl` doesn't conform to the `trait`.
5e7ed085 23 pub(super) fn try_report_impl_not_conforming_to_trait(&self) -> Option<ErrorGuaranteed> {
c295e0f8
XL
24 let error = self.error.as_ref()?;
25 debug!("try_report_impl_not_conforming_to_trait {:?}", error);
26 if let RegionResolutionError::SubSupConflict(
9c376795
FG
27 _,
28 var_origin,
29 sub_origin,
30 _sub,
31 sup_origin,
32 _sup,
33 _,
34 ) = error.clone()
064997fb 35 && let (Subtype(sup_trace), Subtype(sub_trace)) = (&sup_origin, &sub_origin)
064997fb 36 && let CompareImplItemObligation { trait_item_def_id, .. } = sub_trace.cause.code()
9c376795
FG
37 && sub_trace.values == sup_trace.values
38 && let ValuePairs::Sigs(ExpectedFound { expected, found }) = sub_trace.values
c295e0f8 39 {
9c376795
FG
40 // FIXME(compiler-errors): Don't like that this needs `Ty`s, but
41 // all of the region highlighting machinery only deals with those.
42 let guar = self.emit_err(
43 var_origin.span(),
44 self.cx.tcx.mk_fn_ptr(ty::Binder::dummy(expected)),
45 self.cx.tcx.mk_fn_ptr(ty::Binder::dummy(found)),
46 *trait_item_def_id,
47 );
5e7ed085 48 return Some(guar);
c295e0f8 49 }
e74abb32
XL
50 None
51 }
52
5e7ed085
FG
53 fn emit_err(
54 &self,
55 sp: Span,
56 expected: Ty<'tcx>,
57 found: Ty<'tcx>,
58 trait_def_id: DefId,
59 ) -> ErrorGuaranteed {
f9f354fc 60 let trait_sp = self.tcx().def_span(trait_def_id);
3c0e092e
XL
61
62 // Mark all unnamed regions in the type with a number.
63 // This diagnostic is called in response to lifetime errors, so be informative.
64 struct HighlightBuilder<'tcx> {
5099ac24 65 highlight: RegionHighlightMode<'tcx>,
3c0e092e
XL
66 counter: usize,
67 }
68
a2a8927a 69 impl<'tcx> HighlightBuilder<'tcx> {
5099ac24 70 fn build(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> RegionHighlightMode<'tcx> {
3c0e092e 71 let mut builder =
5099ac24 72 HighlightBuilder { highlight: RegionHighlightMode::new(tcx), counter: 1 };
3c0e092e
XL
73 builder.visit_ty(ty);
74 builder.highlight
75 }
76 }
77
064997fb 78 impl<'tcx> ty::visit::TypeVisitor<'tcx> for HighlightBuilder<'tcx> {
3c0e092e
XL
79 fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
80 if !r.has_name() && self.counter <= 3 {
81 self.highlight.highlighting_region(r, self.counter);
82 self.counter += 1;
83 }
84 r.super_visit_with(self)
85 }
86 }
87
88 let expected_highlight = HighlightBuilder::build(self.tcx(), expected);
89 let expected = self
2b03887a 90 .cx
3c0e092e
XL
91 .extract_inference_diagnostics_data(expected.into(), Some(expected_highlight))
92 .name;
93 let found_highlight = HighlightBuilder::build(self.tcx(), found);
94 let found =
2b03887a 95 self.cx.extract_inference_diagnostics_data(found.into(), Some(found_highlight)).name;
3c0e092e 96
f9f354fc
XL
97 // Get the span of all the used type parameters in the method.
98 let assoc_item = self.tcx().associated_item(trait_def_id);
99 let mut visitor = TypeParamSpanVisitor { tcx: self.tcx(), types: vec![] };
100 match assoc_item.kind {
101 ty::AssocKind::Fn => {
102 let hir = self.tcx().hir();
3dfed10e
XL
103 if let Some(hir_id) =
104 assoc_item.def_id.as_local().map(|id| hir.local_def_id_to_hir_id(id))
f9f354fc
XL
105 {
106 if let Some(decl) = hir.fn_decl_by_hir_id(hir_id) {
107 visitor.visit_fn_decl(decl);
108 }
109 }
110 }
111 _ => {}
112 }
f9f354fc 113
9c376795
FG
114 let diag = TraitImplDiff {
115 sp,
116 trait_sp,
117 note: (),
118 param_help: ConsiderBorrowingParamHelp { spans: visitor.types.to_vec() },
119 rel_help: visitor.types.is_empty().then_some(RelationshipHelp),
120 expected,
121 found,
122 };
123
124 self.tcx().sess.emit_err(diag)
e74abb32
XL
125 }
126}
f9f354fc
XL
127
128struct TypeParamSpanVisitor<'tcx> {
129 tcx: TyCtxt<'tcx>,
130 types: Vec<Span>,
131}
132
a2a8927a 133impl<'tcx> Visitor<'tcx> for TypeParamSpanVisitor<'tcx> {
5099ac24 134 type NestedFilter = nested_filter::OnlyBodies;
f9f354fc 135
5099ac24
FG
136 fn nested_visit_map(&mut self) -> Self::Map {
137 self.tcx.hir()
f9f354fc
XL
138 }
139
140 fn visit_ty(&mut self, arg: &'tcx hir::Ty<'tcx>) {
141 match arg.kind {
9c376795 142 hir::TyKind::Ref(_, ref mut_ty) => {
f9f354fc
XL
143 // We don't want to suggest looking into borrowing `&T` or `&Self`.
144 hir::intravisit::walk_ty(self, mut_ty.ty);
145 return;
146 }
147 hir::TyKind::Path(hir::QPath::Resolved(None, path)) => match &path.segments {
148 [segment]
f2b60f7d
FG
149 if matches!(
150 segment.res,
2b03887a
FG
151 Res::SelfTyParam { .. }
152 | Res::SelfTyAlias { .. }
f2b60f7d
FG
153 | Res::Def(hir::def::DefKind::TyParam, _)
154 ) =>
f9f354fc
XL
155 {
156 self.types.push(path.span);
157 }
158 _ => {}
159 },
160 _ => {}
161 }
162 hir::intravisit::walk_ty(self, arg);
163 }
164}