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
::{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}
;
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 if let Some(ref error
) = self.error
{
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
)) =
31 (&sup_origin
, &sub_origin
)
34 ValuePairs
::Types(sub_expected_found
),
35 ValuePairs
::Types(sup_expected_found
),
36 CompareImplMethodObligation { trait_item_def_id, .. }
,
37 ) = (&sub_trace
.values
, &sup_trace
.values
, &sub_trace
.cause
.code
)
39 if sup_expected_found
== sub_expected_found
{
42 sub_expected_found
.expected
,
43 sub_expected_found
.found
,
46 return Some(ErrorReported
);
55 fn emit_err(&self, sp
: Span
, expected
: Ty
<'tcx
>, found
: Ty
<'tcx
>, trait_def_id
: DefId
) {
56 let trait_sp
= self.tcx().def_span(trait_def_id
);
60 .struct_span_err(sp
, "`impl` item signature doesn't match `trait` item signature");
61 err
.span_label(sp
, &format
!("found `{}`", found
));
62 err
.span_label(trait_sp
, &format
!("expected `{}`", expected
));
64 // Get the span of all the used type parameters in the method.
65 let assoc_item
= self.tcx().associated_item(trait_def_id
);
66 let mut visitor
= TypeParamSpanVisitor { tcx: self.tcx(), types: vec![] }
;
67 match assoc_item
.kind
{
68 ty
::AssocKind
::Fn
=> {
69 let hir
= self.tcx().hir();
71 assoc_item
.def_id
.as_local().map(|id
| hir
.local_def_id_to_hir_id(id
))
73 if let Some(decl
) = hir
.fn_decl_by_hir_id(hir_id
) {
74 visitor
.visit_fn_decl(decl
);
80 let mut type_param_span
: MultiSpan
= visitor
.types
.to_vec().into();
81 for &span
in &visitor
.types
{
82 type_param_span
.push_span_label(
84 "consider borrowing this type parameter in the trait".to_string(),
88 if let Some((expected
, found
)) =
89 self.infcx
.expected_found_str_ty(&ExpectedFound { expected, found }
)
91 // Highlighted the differences when showing the "expected/found" note.
92 err
.note_expected_found(&"", expected
, &"", found
);
94 // This fallback shouldn't be necessary, but let's keep it in just in case.
95 err
.note(&format
!("expected `{}`\n found `{}`", expected
, found
));
99 "the lifetime requirements from the `impl` do not correspond to the requirements in \
102 if visitor
.types
.is_empty() {
104 "verify the lifetime relationships in the `trait` and `impl` between the `self` \
105 argument, the other inputs and its output",
112 struct TypeParamSpanVisitor
<'tcx
> {
117 impl Visitor
<'tcx
> for TypeParamSpanVisitor
<'tcx
> {
118 type Map
= rustc_middle
::hir
::map
::Map
<'tcx
>;
120 fn nested_visit_map(&mut self) -> hir
::intravisit
::NestedVisitorMap
<Self::Map
> {
121 hir
::intravisit
::NestedVisitorMap
::OnlyBodies(self.tcx
.hir())
124 fn visit_ty(&mut self, arg
: &'tcx hir
::Ty
<'tcx
>) {
126 hir
::TyKind
::Rptr(_
, ref mut_ty
) => {
127 // We don't want to suggest looking into borrowing `&T` or `&Self`.
128 hir
::intravisit
::walk_ty(self, mut_ty
.ty
);
131 hir
::TyKind
::Path(hir
::QPath
::Resolved(None
, path
)) => match &path
.segments
{
135 .map(|res
| match res
{
136 Res
::SelfTy(_
, _
) | Res
::Def(hir
::def
::DefKind
::TyParam
, _
) => true,
141 self.types
.push(path
.span
);
147 hir
::intravisit
::walk_ty(self, arg
);