]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_infer/src/infer/error_reporting/nice_region_error/named_anon_conflict.rs
New upstream version 1.67.1+dfsg1
[rustc.git] / compiler / rustc_infer / src / infer / error_reporting / nice_region_error / named_anon_conflict.rs
CommitLineData
ff7c6d11
XL
1//! Error Reporting for Anonymous Region Lifetime Errors
2//! where one region is named and the other is anonymous.
6a06907d 3use crate::infer::error_reporting::nice_region_error::find_anon_type::find_anon_type;
9fa01778 4use crate::infer::error_reporting::nice_region_error::NiceRegionError;
5e7ed085 5use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed};
ba9703b0 6use rustc_middle::ty;
923072b8 7use rustc_span::symbol::kw;
60c5eb7d 8
dc9dc135 9impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
e1599b0c 10 /// When given a `ConcreteFailure` for a function with parameters containing a named region and
ff7c6d11 11 /// an anonymous region, emit an descriptive diagnostic error.
5e7ed085
FG
12 pub(super) fn try_report_named_anon_conflict(
13 &self,
14 ) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
74b04a01 15 let (span, sub, sup) = self.regions()?;
ff7c6d11
XL
16
17 debug!(
532ac7d7 18 "try_report_named_anon_conflict(sub={:?}, sup={:?}, error={:?})",
dfeec247 19 sub, sup, self.error,
ff7c6d11
XL
20 );
21
22 // Determine whether the sub and sup consist of one named region ('a)
23 // and one anonymous (elided) region. If so, find the parameter arg
24 // where the anonymous region appears (there must always be one; we
25 // only introduced anonymous regions in parameters) as well as a
26 // version new_ty of its type where the anonymous region is replaced
f9f354fc
XL
27 // with the named one.
28 let (named, anon, anon_param_info, region_info) = if sub.has_name()
9fa01778 29 && self.tcx().is_suitable_region(sup).is_some()
e1599b0c 30 && self.find_param_with_region(sup, sub).is_some()
ff7c6d11
XL
31 {
32 (
33 sub,
34 sup,
e1599b0c 35 self.find_param_with_region(sup, sub).unwrap(),
9fa01778 36 self.tcx().is_suitable_region(sup).unwrap(),
ff7c6d11 37 )
f9f354fc 38 } else if sup.has_name()
dfeec247 39 && self.tcx().is_suitable_region(sub).is_some()
e1599b0c 40 && self.find_param_with_region(sub, sup).is_some()
ff7c6d11
XL
41 {
42 (
43 sup,
44 sub,
e1599b0c 45 self.find_param_with_region(sub, sup).unwrap(),
9fa01778 46 self.tcx().is_suitable_region(sub).unwrap(),
ff7c6d11
XL
47 )
48 } else {
49 return None; // inapplicable
50 };
51
3c0e092e
XL
52 // Suggesting to add a `'static` lifetime to a parameter is nearly always incorrect,
53 // and can steer users down the wrong path.
5099ac24 54 if named.is_static() {
3c0e092e
XL
55 return None;
56 }
57
ff7c6d11 58 debug!("try_report_named_anon_conflict: named = {:?}", named);
dfeec247
XL
59 debug!("try_report_named_anon_conflict: anon_param_info = {:?}", anon_param_info);
60 debug!("try_report_named_anon_conflict: region_info = {:?}", region_info);
ff7c6d11 61
3c0e092e
XL
62 let param = anon_param_info.param;
63 let new_ty = anon_param_info.param_ty;
64 let new_ty_span = anon_param_info.param_ty_span;
65 let br = anon_param_info.bound_region;
66 let is_first = anon_param_info.is_first;
67 let scope_def_id = region_info.def_id;
68 let is_impl_item = region_info.is_impl_item;
69
ff7c6d11 70 match br {
487cf647 71 ty::BrNamed(_, kw::UnderscoreLifetime) | ty::BrAnon(..) => {}
ff7c6d11
XL
72 _ => {
73 /* not an anonymous region */
74 debug!("try_report_named_anon_conflict: not an anonymous region");
75 return None;
76 }
77 }
78
79 if is_impl_item {
80 debug!("try_report_named_anon_conflict: impl item, bail out");
81 return None;
82 }
83
3c0e092e
XL
84 if find_anon_type(self.tcx(), anon, &br).is_some()
85 && self.is_self_anon(is_first, scope_def_id)
86 {
87 return None;
ff7c6d11
XL
88 }
89
e1599b0c 90 let (error_var, span_label_var) = match param.pat.simple_ident() {
48663c56 91 Some(simple_ident) => (
8faf50e0
XL
92 format!("the type of `{}`", simple_ident),
93 format!("the type of `{}`", simple_ident),
48663c56
XL
94 ),
95 None => ("parameter type".to_owned(), "type".to_owned()),
ff7c6d11
XL
96 };
97
9fa01778
XL
98 let mut diag = struct_span_err!(
99 self.tcx().sess,
ff7c6d11
XL
100 span,
101 E0621,
102 "explicit lifetime required in {}",
103 error_var
9fa01778
XL
104 );
105
532ac7d7 106 diag.span_label(span, format!("lifetime `{}` required", named));
3c0e092e
XL
107 diag.span_suggestion(
108 new_ty_span,
109 &format!("add explicit lifetime `{}` to {}", named, span_label_var),
923072b8 110 new_ty,
3c0e092e
XL
111 Applicability::Unspecified,
112 );
9fa01778
XL
113
114 Some(diag)
ff7c6d11
XL
115 }
116}