1 // Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 //! Error Reporting for Anonymous Region Lifetime Errors
12 //! where one region is named and the other is anonymous.
13 use infer::error_reporting::nice_region_error::NiceRegionError;
15 use util::common::ErrorReported;
17 impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> {
18 /// When given a `ConcreteFailure` for a function with arguments containing a named region and
19 /// an anonymous region, emit an descriptive diagnostic error.
20 pub(super) fn try_report_named_anon_conflict(&self) -> Option<ErrorReported> {
21 let (span, sub, sup) = self.get_regions();
24 "try_report_named_anon_conflict(sub={:?}, sup={:?})",
29 // Determine whether the sub and sup consist of one named region ('a)
30 // and one anonymous (elided) region. If so, find the parameter arg
31 // where the anonymous region appears (there must always be one; we
32 // only introduced anonymous regions in parameters) as well as a
33 // version new_ty of its type where the anonymous region is replaced
34 // with the named one.//scope_def_id
35 let (named, anon, anon_arg_info, region_info) = if self.is_named_region(sub)
36 && self.is_suitable_region(sup).is_some()
37 && self.find_arg_with_region(sup, sub).is_some()
42 self.find_arg_with_region(sup, sub).unwrap(),
43 self.is_suitable_region(sup).unwrap(),
45 } else if self.is_named_region(sup) && self.is_suitable_region(sub).is_some()
46 && self.find_arg_with_region(sub, sup).is_some()
51 self.find_arg_with_region(sub, sup).unwrap(),
52 self.is_suitable_region(sub).unwrap(),
55 return None; // inapplicable
58 debug!("try_report_named_anon_conflict: named = {:?}", named);
60 "try_report_named_anon_conflict: anon_arg_info = {:?}",
64 "try_report_named_anon_conflict: region_info = {:?}",
68 let (arg, new_ty, br, is_first, scope_def_id, is_impl_item) = (
71 anon_arg_info.bound_region,
72 anon_arg_info.is_first,
74 region_info.is_impl_item,
79 /* not an anonymous region */
80 debug!("try_report_named_anon_conflict: not an anonymous region");
86 debug!("try_report_named_anon_conflict: impl item, bail out");
90 if let Some((_, fndecl)) = self.find_anon_type(anon, &br) {
91 if self.is_return_type_anon(scope_def_id, br, fndecl).is_some()
92 || self.is_self_anon(is_first, scope_def_id)
98 let (error_var, span_label_var) = if let Some(simple_name) = arg.pat.simple_name() {
100 format!("the type of `{}`", simple_name),
101 format!("the type of `{}`", simple_name),
104 ("parameter type".to_owned(), "type".to_owned())
111 "explicit lifetime required in {}",
115 format!("consider changing {} to `{}`", span_label_var, new_ty),
117 .span_label(span, format!("lifetime `{}` required", named))
119 return Some(ErrorReported);
122 // This method returns whether the given Region is Named
123 pub(super) fn is_named_region(&self, region: ty::Region<'tcx>) -> bool {
125 ty::ReStatic => true,
126 ty::ReFree(ref free_region) => match free_region.bound_region {
127 ty::BrNamed(..) => true,
130 ty::ReEarlyBound(_) => true,