1 //! Error Reporting for `impl` items that do not match the obligations from their `trait`.
3 use crate::infer::error_reporting::nice_region_error::NiceRegionError;
4 use crate::infer::lexical_region_resolve::RegionResolutionError;
5 use crate::infer::{SubregionOrigin, Subtype, ValuePairs};
6 use crate::traits::ObligationCauseCode::CompareImplMethodObligation;
7 use rustc_errors::ErrorReported;
9 use rustc_hir::def::Res;
10 use rustc_hir::def_id::DefId;
11 use rustc_hir::intravisit::Visitor;
12 use rustc_middle::ty::error::ExpectedFound;
13 use rustc_middle::ty::{self, Ty, TyCtxt};
14 use rustc_span::{MultiSpan, Span, Symbol};
16 impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
17 /// Print the error message for lifetime errors when the `impl` doesn't conform to the `trait`.
18 pub(super) fn try_report_impl_not_conforming_to_trait(&self) -> Option<ErrorReported> {
19 let error = self.error.as_ref()?;
20 debug!("try_report_impl_not_conforming_to_trait {:?}", error);
21 if let RegionResolutionError::SubSupConflict(
30 if let (&Subtype(ref sup_trace), &Subtype(ref sub_trace)) = (&sup_origin, &sub_origin) {
32 ValuePairs::Types(sub_expected_found),
33 ValuePairs::Types(sup_expected_found),
34 CompareImplMethodObligation { trait_item_def_id, .. },
35 ) = (&sub_trace.values, &sup_trace.values, &sub_trace.cause.code)
37 if sup_expected_found == sub_expected_found {
40 sub_expected_found.expected,
41 sub_expected_found.found,
44 return Some(ErrorReported);
49 if let RegionResolutionError::ConcreteFailure(origin, _, _) = error.clone() {
50 if let SubregionOrigin::CompareImplTypeObligation {
57 self.emit_associated_type_err(span, item_name, impl_item_def_id, trait_item_def_id);
58 return Some(ErrorReported);
64 fn emit_err(&self, sp: Span, expected: Ty<'tcx>, found: Ty<'tcx>, trait_def_id: DefId) {
65 let trait_sp = self.tcx().def_span(trait_def_id);
69 .struct_span_err(sp, "`impl` item signature doesn't match `trait` item signature");
70 err.span_label(sp, &format!("found `{}`", found));
71 err.span_label(trait_sp, &format!("expected `{}`", expected));
73 // Get the span of all the used type parameters in the method.
74 let assoc_item = self.tcx().associated_item(trait_def_id);
75 let mut visitor = TypeParamSpanVisitor { tcx: self.tcx(), types: vec![] };
76 match assoc_item.kind {
77 ty::AssocKind::Fn => {
78 let hir = self.tcx().hir();
80 assoc_item.def_id.as_local().map(|id| hir.local_def_id_to_hir_id(id))
82 if let Some(decl) = hir.fn_decl_by_hir_id(hir_id) {
83 visitor.visit_fn_decl(decl);
89 let mut type_param_span: MultiSpan = visitor.types.to_vec().into();
90 for &span in &visitor.types {
91 type_param_span.push_span_label(
93 "consider borrowing this type parameter in the trait".to_string(),
97 if let Some((expected, found)) =
98 self.infcx.expected_found_str_ty(ExpectedFound { expected, found })
100 // Highlighted the differences when showing the "expected/found" note.
101 err.note_expected_found(&"", expected, &"", found);
103 // This fallback shouldn't be necessary, but let's keep it in just in case.
104 err.note(&format!("expected `{}`\n found `{}`", expected, found));
108 "the lifetime requirements from the `impl` do not correspond to the requirements in \
111 if visitor.types.is_empty() {
113 "verify the lifetime relationships in the `trait` and `impl` between the `self` \
114 argument, the other inputs and its output",
120 fn emit_associated_type_err(
124 impl_item_def_id: DefId,
125 trait_item_def_id: DefId,
127 let impl_sp = self.tcx().def_span(impl_item_def_id);
128 let trait_sp = self.tcx().def_span(trait_item_def_id);
132 .struct_span_err(span, &format!("`impl` associated type signature for `{}` doesn't match `trait` associated type signature", item_name));
133 err.span_label(impl_sp, &format!("found"));
134 err.span_label(trait_sp, &format!("expected"));
140 struct TypeParamSpanVisitor<'tcx> {
145 impl Visitor<'tcx> for TypeParamSpanVisitor<'tcx> {
146 type Map = rustc_middle::hir::map::Map<'tcx>;
148 fn nested_visit_map(&mut self) -> hir::intravisit::NestedVisitorMap<Self::Map> {
149 hir::intravisit::NestedVisitorMap::OnlyBodies(self.tcx.hir())
152 fn visit_ty(&mut self, arg: &'tcx hir::Ty<'tcx>) {
154 hir::TyKind::Rptr(_, ref mut_ty) => {
155 // We don't want to suggest looking into borrowing `&T` or `&Self`.
156 hir::intravisit::walk_ty(self, mut_ty.ty);
159 hir::TyKind::Path(hir::QPath::Resolved(None, path)) => match &path.segments {
166 Res::SelfTy(_, _) | Res::Def(hir::def::DefKind::TyParam, _)
171 self.types.push(path.span);
177 hir::intravisit::walk_ty(self, arg);