]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs
New upstream version 1.57.0+dfsg1
[rustc.git] / compiler / rustc_infer / src / infer / error_reporting / nice_region_error / mismatched_static_lifetime.rs
CommitLineData
136023e0
XL
1//! Error Reporting for when the lifetime for a type doesn't match the `impl` selected for a predicate
2//! to hold.
3
4use crate::infer::error_reporting::nice_region_error::NiceRegionError;
5use crate::infer::error_reporting::note_and_explain_region;
6use crate::infer::lexical_region_resolve::RegionResolutionError;
7use crate::infer::{SubregionOrigin, TypeTrace};
8use crate::traits::ObligationCauseCode;
9use rustc_data_structures::stable_set::FxHashSet;
10use rustc_errors::{Applicability, ErrorReported};
11use rustc_hir as hir;
12use rustc_hir::intravisit::Visitor;
13use rustc_middle::ty::{self, TypeVisitor};
14use rustc_span::MultiSpan;
15
16impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
17 pub(super) fn try_report_mismatched_static_lifetime(&self) -> Option<ErrorReported> {
18 let error = self.error.as_ref()?;
19 debug!("try_report_mismatched_static_lifetime {:?}", error);
20
21 let (origin, sub, sup) = match error.clone() {
22 RegionResolutionError::ConcreteFailure(origin, sub, sup) => (origin, sub, sup),
23 _ => return None,
24 };
25 if *sub != ty::RegionKind::ReStatic {
26 return None;
27 }
28 let cause = match origin {
29 SubregionOrigin::Subtype(box TypeTrace { ref cause, .. }) => cause,
30 _ => return None,
31 };
c295e0f8
XL
32 // If we added a "points at argument expression" obligation, we remove it here, we care
33 // about the original obligation only.
34 let code = match &cause.code {
35 ObligationCauseCode::FunctionArgumentObligation { parent_code, .. } => &*parent_code,
36 _ => &cause.code,
37 };
38 let (parent, impl_def_id) = match code {
136023e0
XL
39 ObligationCauseCode::MatchImpl(parent, impl_def_id) => (parent, impl_def_id),
40 _ => return None,
41 };
c295e0f8 42 let binding_span = match parent.code {
136023e0
XL
43 ObligationCauseCode::BindingObligation(_def_id, binding_span) => binding_span,
44 _ => return None,
45 };
46 let mut err = self.tcx().sess.struct_span_err(cause.span, "incompatible lifetime on type");
47 // FIXME: we should point at the lifetime
48 let mut multi_span: MultiSpan = vec![binding_span].into();
49 multi_span
50 .push_span_label(binding_span, "introduces a `'static` lifetime requirement".into());
51 err.span_note(multi_span, "because this has an unmet lifetime requirement");
94222f64 52 note_and_explain_region(self.tcx(), &mut err, "", sup, "...", Some(binding_span));
136023e0
XL
53 if let Some(impl_node) = self.tcx().hir().get_if_local(*impl_def_id) {
54 // If an impl is local, then maybe this isn't what they want. Try to
55 // be as helpful as possible with implicit lifetimes.
56
57 // First, let's get the hir self type of the impl
58 let impl_self_ty = match impl_node {
59 hir::Node::Item(hir::Item {
60 kind: hir::ItemKind::Impl(hir::Impl { self_ty, .. }),
61 ..
62 }) => self_ty,
63 _ => bug!("Node not an impl."),
64 };
65
66 // Next, let's figure out the set of trait objects with implict static bounds
67 let ty = self.tcx().type_of(*impl_def_id);
68 let mut v = super::static_impl_trait::TraitObjectVisitor(FxHashSet::default());
69 v.visit_ty(ty);
70 let mut traits = vec![];
71 for matching_def_id in v.0 {
72 let mut hir_v =
73 super::static_impl_trait::HirTraitObjectVisitor(&mut traits, matching_def_id);
74 hir_v.visit_ty(&impl_self_ty);
75 }
76
77 if traits.is_empty() {
78 // If there are no trait object traits to point at, either because
79 // there aren't trait objects or because none are implicit, then just
80 // write a single note on the impl itself.
81
82 let impl_span = self.tcx().def_span(*impl_def_id);
83 err.span_note(impl_span, "...does not necessarily outlive the static lifetime introduced by the compatible `impl`");
84 } else {
85 // Otherwise, point at all implicit static lifetimes
86
87 err.note("...does not necessarily outlive the static lifetime introduced by the compatible `impl`");
88 for span in &traits {
89 err.span_note(*span, "this has an implicit `'static` lifetime requirement");
90 // It would be nice to put this immediately under the above note, but they get
91 // pushed to the end.
92 err.span_suggestion_verbose(
93 span.shrink_to_hi(),
94 "consider relaxing the implicit `'static` requirement",
95 " + '_".to_string(),
96 Applicability::MaybeIncorrect,
97 );
98 }
99 }
100 } else {
101 // Otherwise just point out the impl.
102
103 let impl_span = self.tcx().def_span(*impl_def_id);
104 err.span_note(impl_span, "...does not necessarily outlive the static lifetime introduced by the compatible `impl`");
105 }
106 err.emit();
107 Some(ErrorReported)
108 }
109}