]> git.lizzy.rs Git - rust.git/blob - src/librustc/infer/error_reporting/named_anon_conflict.rs
adding E0623 for LateBound regions
[rust.git] / src / librustc / infer / error_reporting / named_anon_conflict.rs
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.
4 //
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.
10
11 //! Error Reporting for Anonymous Region Lifetime Errors
12 //! where one region is named and the other is anonymous.
13 use infer::InferCtxt;
14 use infer::region_inference::RegionResolutionError::*;
15 use infer::region_inference::RegionResolutionError;
16 use ty;
17
18 impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
19     // This method generates the error message for the case when
20     // the function arguments consist of a named region and an anonymous
21     // region and corresponds to `ConcreteFailure(..)`
22     pub fn try_report_named_anon_conflict(&self, error: &RegionResolutionError<'tcx>) -> bool {
23         let (span, sub, sup) = match *error {
24             ConcreteFailure(ref origin, sub, sup) => (origin.span(), sub, sup),
25             _ => return false, // inapplicable
26         };
27
28         debug!("try_report_named_anon_conflict(sub={:?}, sup={:?})",
29                sub,
30                sup);
31
32         // Determine whether the sub and sup consist of one named region ('a)
33         // and one anonymous (elided) region. If so, find the parameter arg
34         // where the anonymous region appears (there must always be one; we
35         // only introduced anonymous regions in parameters) as well as a
36         // version new_ty of its type where the anonymous region is replaced
37         // with the named one.//scope_def_id
38         let (named, anon_arg_info, region_info) =
39             if self.is_named_region(sub) && self.is_suitable_region(sup).is_some() &&
40                self.find_arg_with_region(sup, sub).is_some() {
41                 (sub,
42                  self.find_arg_with_region(sup, sub).unwrap(),
43                  self.is_suitable_region(sup).unwrap())
44             } else if self.is_named_region(sup) && self.is_suitable_region(sub).is_some() &&
45                       self.find_arg_with_region(sub, sup).is_some() {
46                 (sup,
47                  self.find_arg_with_region(sub, sup).unwrap(),
48                  self.is_suitable_region(sub).unwrap())
49             } else {
50                 return false; // inapplicable
51             };
52
53         debug!("try_report_named_anon_conflict: named = {:?}", named);
54         debug!("try_report_named_anon_conflict: anon_arg_info = {:?}",
55                anon_arg_info);
56         debug!("try_report_named_anon_conflict: region_info = {:?}",
57                region_info);
58
59         let (arg, new_ty, br, is_first, scope_def_id, is_impl_item) = (anon_arg_info.arg,
60                                                                        anon_arg_info.arg_ty,
61                                                                        anon_arg_info.bound_region,
62                                                                        anon_arg_info.is_first,
63                                                                        region_info.def_id,
64                                                                        region_info.is_impl_item);
65         match br {
66             ty::BrAnon(_) => {}
67             _ => {
68                 /* not an anonymous region */
69                 debug!("try_report_named_anon_conflict: not an anonymous region");
70                 return false;
71             }
72         }
73
74         if is_impl_item {
75             debug!("try_report_named_anon_conflict: impl item, bail out");
76             return false;
77         }
78
79         if self.is_return_type_anon(scope_def_id, br) {
80             debug!("try_report_named_anon_conflict: is_return_type_anon({:?}, {:?}) = true",
81                    scope_def_id,
82                    br);
83             return false;
84         } else if self.is_self_anon(is_first, scope_def_id) {
85             debug!("try_report_named_anon_conflict: is_self_anon({:?}, {:?}) = true",
86                    is_first,
87                    scope_def_id);
88             return false;
89         } else {
90             let (error_var, span_label_var) = if let Some(simple_name) = arg.pat.simple_name() {
91                 (format!("the type of `{}`", simple_name), format!("the type of `{}`", simple_name))
92             } else {
93                 ("parameter type".to_owned(), "type".to_owned())
94             };
95
96             struct_span_err!(self.tcx.sess,
97                              span,
98                              E0621,
99                              "explicit lifetime required in {}",
100                              error_var)
101                     .span_label(arg.pat.span,
102                                 format!("consider changing {} to `{}`", span_label_var, new_ty))
103                     .span_label(span, format!("lifetime `{}` required", named))
104                     .emit();
105             return true;
106         }
107     }
108 }