]> git.proxmox.com Git - rustc.git/blame - src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs
New upstream version 1.25.0+dfsg1
[rustc.git] / src / librustc / infer / error_reporting / nice_region_error / named_anon_conflict.rs
CommitLineData
ff7c6d11
XL
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.
13use infer::error_reporting::nice_region_error::NiceRegionError;
14use ty;
15use util::common::ErrorReported;
16
17impl<'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> {
2c00a5a8 21 let (span, sub, sup) = self.get_regions();
ff7c6d11
XL
22
23 debug!(
24 "try_report_named_anon_conflict(sub={:?}, sup={:?})",
25 sub,
26 sup
27 );
28
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()
38 {
39 (
40 sub,
41 sup,
42 self.find_arg_with_region(sup, sub).unwrap(),
43 self.is_suitable_region(sup).unwrap(),
44 )
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()
47 {
48 (
49 sup,
50 sub,
51 self.find_arg_with_region(sub, sup).unwrap(),
52 self.is_suitable_region(sub).unwrap(),
53 )
54 } else {
55 return None; // inapplicable
56 };
57
58 debug!("try_report_named_anon_conflict: named = {:?}", named);
59 debug!(
60 "try_report_named_anon_conflict: anon_arg_info = {:?}",
61 anon_arg_info
62 );
63 debug!(
64 "try_report_named_anon_conflict: region_info = {:?}",
65 region_info
66 );
67
68 let (arg, new_ty, br, is_first, scope_def_id, is_impl_item) = (
69 anon_arg_info.arg,
70 anon_arg_info.arg_ty,
71 anon_arg_info.bound_region,
72 anon_arg_info.is_first,
73 region_info.def_id,
74 region_info.is_impl_item,
75 );
76 match br {
77 ty::BrAnon(_) => {}
78 _ => {
79 /* not an anonymous region */
80 debug!("try_report_named_anon_conflict: not an anonymous region");
81 return None;
82 }
83 }
84
85 if is_impl_item {
86 debug!("try_report_named_anon_conflict: impl item, bail out");
87 return None;
88 }
89
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)
93 {
94 return None;
95 }
96 }
97
98 let (error_var, span_label_var) = if let Some(simple_name) = arg.pat.simple_name() {
99 (
100 format!("the type of `{}`", simple_name),
101 format!("the type of `{}`", simple_name),
102 )
103 } else {
104 ("parameter type".to_owned(), "type".to_owned())
105 };
106
107 struct_span_err!(
108 self.tcx.sess,
109 span,
110 E0621,
111 "explicit lifetime required in {}",
112 error_var
113 ).span_label(
114 arg.pat.span,
115 format!("consider changing {} to `{}`", span_label_var, new_ty),
116 )
117 .span_label(span, format!("lifetime `{}` required", named))
118 .emit();
119 return Some(ErrorReported);
120 }
2c00a5a8
XL
121
122 // This method returns whether the given Region is Named
123 pub(super) fn is_named_region(&self, region: ty::Region<'tcx>) -> bool {
124 match *region {
125 ty::ReStatic => true,
126 ty::ReFree(ref free_region) => match free_region.bound_region {
127 ty::BrNamed(..) => true,
128 _ => false,
129 },
130 ty::ReEarlyBound(_) => true,
131 _ => false,
132 }
133 }
ff7c6d11 134}