]>
Commit | Line | Data |
---|---|---|
ff7c6d11 XL |
1 | //! Error Reporting for Anonymous Region Lifetime Errors |
2 | //! where both the regions are anonymous. | |
3 | ||
f2b60f7d FG |
4 | use crate::errors::AddLifetimeParamsSuggestion; |
5 | use crate::errors::LifetimeMismatch; | |
6 | use crate::errors::LifetimeMismatchLabels; | |
6a06907d | 7 | use crate::infer::error_reporting::nice_region_error::find_anon_type::find_anon_type; |
e1599b0c | 8 | use crate::infer::error_reporting::nice_region_error::util::AnonymousParamInfo; |
dfeec247 | 9 | use crate::infer::error_reporting::nice_region_error::NiceRegionError; |
ba9703b0 XL |
10 | use crate::infer::lexical_region_resolve::RegionResolutionError; |
11 | use crate::infer::SubregionOrigin; | |
04454e1e | 12 | use crate::infer::TyCtxt; |
ff7c6d11 | 13 | |
2b03887a | 14 | use rustc_errors::AddToDiagnostic; |
f2b60f7d FG |
15 | use rustc_errors::{Diagnostic, ErrorGuaranteed}; |
16 | use rustc_hir::Ty; | |
3c0e092e | 17 | use rustc_middle::ty::Region; |
60c5eb7d | 18 | |
dc9dc135 | 19 | impl<'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 |
140 | pub 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 | } |