]>
Commit | Line | Data |
---|---|---|
ff7c6d11 XL |
1 | //! Error Reporting for Anonymous Region Lifetime Errors |
2 | //! where one region is named and the other is anonymous. | |
3 | use infer::error_reporting::nice_region_error::NiceRegionError; | |
4 | use ty; | |
5 | use util::common::ErrorReported; | |
0bf4aa26 | 6 | use errors::Applicability; |
ff7c6d11 XL |
7 | |
8 | impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> { | |
9 | /// When given a `ConcreteFailure` for a function with arguments containing a named region and | |
10 | /// an anonymous region, emit an descriptive diagnostic error. | |
11 | pub(super) fn try_report_named_anon_conflict(&self) -> Option<ErrorReported> { | |
2c00a5a8 | 12 | let (span, sub, sup) = self.get_regions(); |
ff7c6d11 XL |
13 | |
14 | debug!( | |
15 | "try_report_named_anon_conflict(sub={:?}, sup={:?})", | |
16 | sub, | |
17 | sup | |
18 | ); | |
19 | ||
20 | // Determine whether the sub and sup consist of one named region ('a) | |
21 | // and one anonymous (elided) region. If so, find the parameter arg | |
22 | // where the anonymous region appears (there must always be one; we | |
23 | // only introduced anonymous regions in parameters) as well as a | |
24 | // version new_ty of its type where the anonymous region is replaced | |
25 | // with the named one.//scope_def_id | |
26 | let (named, anon, anon_arg_info, region_info) = if self.is_named_region(sub) | |
0bf4aa26 | 27 | && self.tcx.is_suitable_region(sup).is_some() |
ff7c6d11 XL |
28 | && self.find_arg_with_region(sup, sub).is_some() |
29 | { | |
30 | ( | |
31 | sub, | |
32 | sup, | |
33 | self.find_arg_with_region(sup, sub).unwrap(), | |
0bf4aa26 | 34 | self.tcx.is_suitable_region(sup).unwrap(), |
ff7c6d11 | 35 | ) |
0bf4aa26 | 36 | } else if self.is_named_region(sup) && self.tcx.is_suitable_region(sub).is_some() |
ff7c6d11 XL |
37 | && self.find_arg_with_region(sub, sup).is_some() |
38 | { | |
39 | ( | |
40 | sup, | |
41 | sub, | |
42 | self.find_arg_with_region(sub, sup).unwrap(), | |
0bf4aa26 | 43 | self.tcx.is_suitable_region(sub).unwrap(), |
ff7c6d11 XL |
44 | ) |
45 | } else { | |
46 | return None; // inapplicable | |
47 | }; | |
48 | ||
49 | debug!("try_report_named_anon_conflict: named = {:?}", named); | |
50 | debug!( | |
51 | "try_report_named_anon_conflict: anon_arg_info = {:?}", | |
52 | anon_arg_info | |
53 | ); | |
54 | debug!( | |
55 | "try_report_named_anon_conflict: region_info = {:?}", | |
56 | region_info | |
57 | ); | |
58 | ||
b7449926 | 59 | let (arg, new_ty, new_ty_span, br, is_first, scope_def_id, is_impl_item) = ( |
ff7c6d11 XL |
60 | anon_arg_info.arg, |
61 | anon_arg_info.arg_ty, | |
b7449926 | 62 | anon_arg_info.arg_ty_span, |
ff7c6d11 XL |
63 | anon_arg_info.bound_region, |
64 | anon_arg_info.is_first, | |
65 | region_info.def_id, | |
66 | region_info.is_impl_item, | |
67 | ); | |
68 | match br { | |
69 | ty::BrAnon(_) => {} | |
70 | _ => { | |
71 | /* not an anonymous region */ | |
72 | debug!("try_report_named_anon_conflict: not an anonymous region"); | |
73 | return None; | |
74 | } | |
75 | } | |
76 | ||
77 | if is_impl_item { | |
78 | debug!("try_report_named_anon_conflict: impl item, bail out"); | |
79 | return None; | |
80 | } | |
81 | ||
82 | if let Some((_, fndecl)) = self.find_anon_type(anon, &br) { | |
83 | if self.is_return_type_anon(scope_def_id, br, fndecl).is_some() | |
84 | || self.is_self_anon(is_first, scope_def_id) | |
85 | { | |
86 | return None; | |
87 | } | |
88 | } | |
89 | ||
8faf50e0 | 90 | let (error_var, span_label_var) = if let Some(simple_ident) = arg.pat.simple_ident() { |
ff7c6d11 | 91 | ( |
8faf50e0 XL |
92 | format!("the type of `{}`", simple_ident), |
93 | format!("the type of `{}`", simple_ident), | |
ff7c6d11 XL |
94 | ) |
95 | } else { | |
96 | ("parameter type".to_owned(), "type".to_owned()) | |
97 | }; | |
98 | ||
99 | struct_span_err!( | |
100 | self.tcx.sess, | |
101 | span, | |
102 | E0621, | |
103 | "explicit lifetime required in {}", | |
104 | error_var | |
0bf4aa26 | 105 | ).span_suggestion_with_applicability( |
b7449926 XL |
106 | new_ty_span, |
107 | &format!("add explicit lifetime `{}` to {}", named, span_label_var), | |
0bf4aa26 XL |
108 | new_ty.to_string(), |
109 | Applicability::Unspecified, | |
ff7c6d11 | 110 | ) |
0bf4aa26 XL |
111 | .span_label(span, format!("lifetime `{}` required", named)) |
112 | .emit(); | |
ff7c6d11 XL |
113 | return Some(ErrorReported); |
114 | } | |
2c00a5a8 XL |
115 | |
116 | // This method returns whether the given Region is Named | |
117 | pub(super) fn is_named_region(&self, region: ty::Region<'tcx>) -> bool { | |
118 | match *region { | |
119 | ty::ReStatic => true, | |
120 | ty::ReFree(ref free_region) => match free_region.bound_region { | |
121 | ty::BrNamed(..) => true, | |
122 | _ => false, | |
123 | }, | |
b7449926 | 124 | ty::ReEarlyBound(ebr) => ebr.has_name(), |
2c00a5a8 XL |
125 | _ => false, |
126 | } | |
127 | } | |
ff7c6d11 | 128 | } |