]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs
New upstream version 1.71.1+dfsg1
[rustc.git] / compiler / rustc_infer / src / infer / error_reporting / nice_region_error / different_lifetimes.rs
CommitLineData
ff7c6d11
XL
1//! Error Reporting for Anonymous Region Lifetime Errors
2//! where both the regions are anonymous.
3
f2b60f7d
FG
4use crate::errors::AddLifetimeParamsSuggestion;
5use crate::errors::LifetimeMismatch;
6use crate::errors::LifetimeMismatchLabels;
6a06907d 7use crate::infer::error_reporting::nice_region_error::find_anon_type::find_anon_type;
e1599b0c 8use crate::infer::error_reporting::nice_region_error::util::AnonymousParamInfo;
dfeec247 9use crate::infer::error_reporting::nice_region_error::NiceRegionError;
ba9703b0
XL
10use crate::infer::lexical_region_resolve::RegionResolutionError;
11use crate::infer::SubregionOrigin;
04454e1e 12use crate::infer::TyCtxt;
ff7c6d11 13
2b03887a 14use rustc_errors::AddToDiagnostic;
f2b60f7d
FG
15use rustc_errors::{Diagnostic, ErrorGuaranteed};
16use rustc_hir::Ty;
3c0e092e 17use rustc_middle::ty::Region;
60c5eb7d 18
dc9dc135 19impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
ff7c6d11
XL
20 /// Print the error message for lifetime errors when both the concerned regions are anonymous.
21 ///
22 /// Consider a case where we have
23 ///
49aad941 24 /// ```compile_fail
ff7c6d11
XL
25 /// fn foo(x: &mut Vec<&u8>, y: &u8) {
26 /// x.push(y);
27 /// }
28 /// ```
29 ///
30 /// The example gives
31 ///
32 /// ```text
33 /// fn foo(x: &mut Vec<&u8>, y: &u8) {
34 /// --- --- these references are declared with different lifetimes...
35 /// x.push(y);
36 /// ^ ...but data from `y` flows into `x` here
37 /// ```
38 ///
39 /// It has been extended for the case of structs too.
40 ///
41 /// Consider the example
42 ///
43 /// ```no_run
44 /// struct Ref<'a> { x: &'a u32 }
45 /// ```
46 ///
47 /// ```text
48 /// fn foo(mut x: Vec<Ref>, y: Ref) {
49 /// --- --- these structs are declared with different lifetimes...
50 /// x.push(y);
51 /// ^ ...but data from `y` flows into `x` here
52 /// }
9fa01778 53 /// ```
ff7c6d11
XL
54 ///
55 /// It will later be extended to trait objects.
5e7ed085 56 pub(super) fn try_report_anon_anon_conflict(&self) -> Option<ErrorGuaranteed> {
74b04a01 57 let (span, sub, sup) = self.regions()?;
ff7c6d11 58
ba9703b0
XL
59 if let Some(RegionResolutionError::ConcreteFailure(
60 SubregionOrigin::ReferenceOutlivesReferent(..),
61 ..,
62 )) = self.error
63 {
64 // This error doesn't make much sense in this case.
65 return None;
66 }
67
ff7c6d11 68 // Determine whether the sub and sup consist of both anonymous (elided) regions.
9fa01778 69 let anon_reg_sup = self.tcx().is_suitable_region(sup)?;
ff7c6d11 70
9fa01778 71 let anon_reg_sub = self.tcx().is_suitable_region(sub)?;
ff7c6d11
XL
72 let scope_def_id_sup = anon_reg_sup.def_id;
73 let bregion_sup = anon_reg_sup.boundregion;
74 let scope_def_id_sub = anon_reg_sub.def_id;
75 let bregion_sub = anon_reg_sub.boundregion;
76
6a06907d 77 let ty_sup = find_anon_type(self.tcx(), sup, &bregion_sup)?;
ff7c6d11 78
6a06907d 79 let ty_sub = find_anon_type(self.tcx(), sub, &bregion_sub)?;
ff7c6d11
XL
80
81 debug!(
e1599b0c 82 "try_report_anon_anon_conflict: found_param1={:?} sup={:?} br1={:?}",
dfeec247 83 ty_sub, sup, bregion_sup
ff7c6d11
XL
84 );
85 debug!(
e1599b0c 86 "try_report_anon_anon_conflict: found_param2={:?} sub={:?} br2={:?}",
dfeec247 87 ty_sup, sub, bregion_sub
ff7c6d11
XL
88 );
89
90 let (ty_sup, ty_fndecl_sup) = ty_sup;
91 let (ty_sub, ty_fndecl_sub) = ty_sub;
92
dfeec247
XL
93 let AnonymousParamInfo { param: anon_param_sup, .. } =
94 self.find_param_with_region(sup, sup)?;
95 let AnonymousParamInfo { param: anon_param_sub, .. } =
96 self.find_param_with_region(sub, sub)?;
ff7c6d11
XL
97
98 let sup_is_ret_type =
99 self.is_return_type_anon(scope_def_id_sup, bregion_sup, ty_fndecl_sup);
100 let sub_is_ret_type =
101 self.is_return_type_anon(scope_def_id_sub, bregion_sub, ty_fndecl_sub);
102
5099ac24
FG
103 debug!(
104 "try_report_anon_anon_conflict: sub_is_ret_type={:?} sup_is_ret_type={:?}",
105 sub_is_ret_type, sup_is_ret_type
106 );
29967ef6 107
f2b60f7d 108 let labels = match (sup_is_ret_type, sub_is_ret_type) {
5099ac24
FG
109 (ret_capture @ Some(ret_span), _) | (_, ret_capture @ Some(ret_span)) => {
110 let param_span =
111 if sup_is_ret_type == ret_capture { ty_sub.span } else { ty_sup.span };
f2b60f7d 112 LifetimeMismatchLabels::InRet {
5099ac24 113 param_span,
f2b60f7d
FG
114 ret_span,
115 span,
116 label_var1: anon_param_sup.pat.simple_ident(),
5099ac24
FG
117 }
118 }
3c0e092e 119
f2b60f7d
FG
120 (None, None) => LifetimeMismatchLabels::Normal {
121 hir_equal: ty_sup.hir_id == ty_sub.hir_id,
122 ty_sup: ty_sup.span,
123 ty_sub: ty_sub.span,
124 span,
125 sup: anon_param_sup.pat.simple_ident(),
126 sub: anon_param_sub.pat.simple_ident(),
127 },
128 };
29967ef6 129
f2b60f7d
FG
130 let suggestion =
131 AddLifetimeParamsSuggestion { tcx: self.tcx(), sub, ty_sup, ty_sub, add_note: true };
132 let err = LifetimeMismatch { span, labels, suggestion };
133 let reported = self.tcx().sess.emit_err(err);
5e7ed085 134 Some(reported)
ff7c6d11 135 }
04454e1e 136}
3c0e092e 137
f2b60f7d
FG
138/// Currently only used in rustc_borrowck, probably should be
139/// removed in favour of public_errors::AddLifetimeParamsSuggestion
04454e1e
FG
140pub fn suggest_adding_lifetime_params<'tcx>(
141 tcx: TyCtxt<'tcx>,
142 sub: Region<'tcx>,
f2b60f7d
FG
143 ty_sup: &'tcx Ty<'_>,
144 ty_sub: &'tcx Ty<'_>,
04454e1e 145 err: &mut Diagnostic,
f2b60f7d
FG
146) {
147 let suggestion = AddLifetimeParamsSuggestion { tcx, sub, ty_sup, ty_sub, add_note: false };
148 suggestion.add_to_diagnostic(err);
ff7c6d11 149}