]> git.proxmox.com Git - rustc.git/blame - src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs
New upstream version 1.33.0+dfsg1
[rustc.git] / src / librustc / 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.
3use infer::error_reporting::nice_region_error::NiceRegionError;
4use ty;
5use util::common::ErrorReported;
0bf4aa26 6use errors::Applicability;
ff7c6d11
XL
7
8impl<'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}