Skip to content

Commit a361a2c

Browse files
committed
changing error message format for E0611
1 parent 4771970 commit a361a2c

11 files changed

+107
-97
lines changed

src/librustc/infer/error_reporting/anon_anon_conflict.rs

Lines changed: 6 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,9 @@
1212
//! where both the regions are anonymous.
1313
use hir;
1414
use infer::InferCtxt;
15-
use ty::{self, Region};
15+
use ty;
1616
use infer::region_inference::RegionResolutionError::*;
1717
use infer::region_inference::RegionResolutionError;
18-
use hir::map as hir_map;
1918
use middle::resolve_lifetime as rl;
2019
use hir::intravisit::{self, Visitor, NestedVisitorMap};
2120

@@ -86,9 +85,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
8685
return false;
8786
}
8887

89-
90-
91-
9288
if anon_arg1 == anon_arg2 {
9389
(format!(" with one lifetime"), format!(" into the other"))
9490
} else {
@@ -119,81 +115,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
119115
return true;
120116

121117
}
122-
123-
/// This function calls the `visit_ty` method for the parameters
124-
/// corresponding to the anonymous regions. The `nested_visitor.found_type`
125-
/// contains the anonymous type.
126-
///
127-
/// # Arguments
128-
///
129-
/// region - the anonymous region corresponding to the anon_anon conflict
130-
/// br - the bound region corresponding to the above region which is of type `BrAnon(_)`
131-
///
132-
/// # Example
133-
/// ```
134-
/// fn foo(x: &mut Vec<&u8>, y: &u8)
135-
/// { x.push(y); }
136-
/// ```
137-
/// The function returns the nested type corresponding to the anonymous region
138-
/// for e.g. `&u8` and Vec<`&u8`.
139-
pub fn find_anon_type(&self, region: Region<'tcx>, br: &ty::BoundRegion) -> Option<(&hir::Ty)> {
140-
if let Some(anon_reg) = self.is_suitable_anonymous_region(region, true) {
141-
let (def_id, _) = anon_reg;
142-
if let Some(node_id) = self.tcx.hir.as_local_node_id(def_id) {
143-
let ret_ty = self.tcx.type_of(def_id);
144-
if let ty::TyFnDef(_, _) = ret_ty.sty {
145-
if let hir_map::NodeItem(it) = self.tcx.hir.get(node_id) {
146-
if let hir::ItemFn(ref fndecl, _, _, _, _, _) = it.node {
147-
return fndecl
148-
.inputs
149-
.iter()
150-
.filter_map(|arg| {
151-
self.find_visitor_found_type(&**arg, br)
152-
})
153-
.next();
154-
}
155-
} else if let hir_map::NodeTraitItem(it) = self.tcx.hir.get(node_id) {
156-
if let hir::TraitItemKind::Method(ref fndecl, _) = it.node {
157-
return fndecl
158-
.decl
159-
.inputs
160-
.iter()
161-
.filter_map(|arg| {
162-
self.find_visitor_found_type(&**arg, br)
163-
})
164-
.next();
165-
}
166-
} else if let hir_map::NodeImplItem(it) = self.tcx.hir.get(node_id) {
167-
if let hir::ImplItemKind::Method(ref fndecl, _) = it.node {
168-
return fndecl
169-
.decl
170-
.inputs
171-
.iter()
172-
.filter_map(|arg| {
173-
self.find_visitor_found_type(&**arg, br)
174-
})
175-
.next();
176-
}
177-
}
178-
}
179-
}
180-
}
181-
None
182-
}
183-
184-
fn find_visitor_found_type(&self,
185-
arg: &'gcx hir::Ty,
186-
br: &ty::BoundRegion)
187-
-> Option<(&'gcx hir::Ty)> {
188-
let mut nested_visitor = FindNestedTypeVisitor {
189-
infcx: &self,
190-
hir_map: &self.tcx.hir,
191-
bound_region: *br,
192-
found_type: None,
193-
};
194-
nested_visitor.visit_ty(arg);
195-
nested_visitor.found_type
196-
}
197118
}
198119

199120
// The FindNestedTypeVisitor captures the corresponding `hir::Ty` of the
@@ -203,15 +124,15 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
203124
// walk the types like &mut Vec<&u8> and &u8 looking for the HIR
204125
// where that lifetime appears. This allows us to highlight the
205126
// specific part of the type in the error message.
206-
struct FindNestedTypeVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
207-
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
208-
hir_map: &'a hir::map::Map<'gcx>,
127+
pub struct FindNestedTypeVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
128+
pub infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
129+
pub hir_map: &'a hir::map::Map<'gcx>,
209130
// The bound_region corresponding to the Refree(freeregion)
210131
// associated with the anonymous region we are looking for.
211-
bound_region: ty::BoundRegion,
132+
pub bound_region: ty::BoundRegion,
212133
// The type where the anonymous lifetime appears
213134
// for e.g. Vec<`&u8`> and <`&u8`>
214-
found_type: Option<&'gcx hir::Ty>,
135+
pub found_type: Option<&'gcx hir::Ty>,
215136
}
216137

217138
impl<'a, 'gcx, 'tcx> Visitor<'gcx> for FindNestedTypeVisitor<'a, 'gcx, 'tcx> {

src/librustc/infer/error_reporting/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -963,4 +963,5 @@ impl<'tcx> ObligationCause<'tcx> {
963963
_ => "types are compatible",
964964
}
965965
}
966+
966967
}

src/librustc/infer/error_reporting/named_anon_conflict.rs

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,16 +30,18 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
3030
// only introduced anonymous regions in parameters) as well as a
3131
// version new_ty of its type where the anonymous region is replaced
3232
// with the named one.
33-
let (named, (arg, new_ty, br, is_first), (scope_def_id, _)) = if
33+
let (named, (arg, new_ty, br, is_first), (scope_def_id, _), anon) = if
3434
sub.is_named_region() && self.is_suitable_anonymous_region(sup, false).is_some() {
3535
(sub,
3636
self.find_arg_with_anonymous_region(sup, sub).unwrap(),
37-
self.is_suitable_anonymous_region(sup, false).unwrap())
37+
self.is_suitable_anonymous_region(sup, false).unwrap(),
38+
sup)
3839
} else if
3940
sup.is_named_region() && self.is_suitable_anonymous_region(sub, false).is_some() {
4041
(sup,
4142
self.find_arg_with_anonymous_region(sub, sup).unwrap(),
42-
self.is_suitable_anonymous_region(sub, false).unwrap())
43+
self.is_suitable_anonymous_region(sub, false).unwrap(),
44+
sub)
4345
} else {
4446
return false; // inapplicable
4547
};
@@ -54,17 +56,22 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
5456
("parameter type".to_owned(), "type".to_owned())
5557
};
5658

59+
let span_label = if let Some(ty_anon) = self.find_anon_type(anon, &br) {
60+
ty_anon.span
61+
} else {
62+
arg.pat.span
63+
};
64+
5765
struct_span_err!(self.tcx.sess,
5866
span,
5967
E0621,
6068
"explicit lifetime required in {}",
6169
error_var)
62-
.span_label(arg.pat.span,
70+
.span_label(span_label,
6371
format!("consider changing {} to `{}`", span_label_var, new_ty))
6472
.span_label(span, format!("lifetime `{}` required", named))
6573
.emit();
6674

67-
6875
}
6976
return true;
7077
}

src/librustc/infer/error_reporting/util.rs

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ use infer::InferCtxt;
1515
use ty::{self, Region};
1616
use hir::def_id::DefId;
1717
use hir::map as hir_map;
18+
use hir::intravisit::Visitor;
19+
use infer::error_reporting::anon_anon_conflict::FindNestedTypeVisitor;
1820

1921
impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
2022
// This method walks the Type of the function body arguments using
@@ -140,6 +142,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
140142
}
141143
false
142144
}
145+
143146
// Here we check for the case where anonymous region
144147
// corresponds to self and if yes, we display E0312.
145148
// FIXME(#42700) - Need to format self properly to
@@ -154,4 +157,82 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
154157
}
155158
false
156159
}
160+
161+
/// This function calls the `visit_ty` method for the parameters
162+
/// corresponding to the anonymous regions. The `nested_visitor.found_type`
163+
/// contains the anonymous type.
164+
///
165+
/// # Arguments
166+
///
167+
/// region - the anonymous region corresponding to the lifetime conflicts
168+
/// due to anonymous regions.
169+
/// br - the bound region corresponding to the above region which is of type `BrAnon(_)`
170+
///
171+
/// # Example
172+
/// ```
173+
/// fn foo(x: &mut Vec<&u8>, y: &u8)
174+
/// { x.push(y); }
175+
/// ```
176+
/// The function returns the nested type corresponding to the anonymous region
177+
/// for e.g. `&u8` and Vec<`&u8`.
178+
pub fn find_anon_type(&self, region: Region<'tcx>, br: &ty::BoundRegion) -> Option<(&hir::Ty)> {
179+
if let Some(anon_reg) = self.is_suitable_anonymous_region(region, true) {
180+
let (def_id, _) = anon_reg;
181+
if let Some(node_id) = self.tcx.hir.as_local_node_id(def_id) {
182+
let ret_ty = self.tcx.type_of(def_id);
183+
if let ty::TyFnDef(_, _) = ret_ty.sty {
184+
if let hir_map::NodeItem(it) = self.tcx.hir.get(node_id) {
185+
if let hir::ItemFn(ref fndecl, _, _, _, _, _) = it.node {
186+
return fndecl
187+
.inputs
188+
.iter()
189+
.filter_map(|arg| {
190+
self.find_visitor_found_type(&**arg, br)
191+
})
192+
.next();
193+
}
194+
} else if let hir_map::NodeTraitItem(it) = self.tcx.hir.get(node_id) {
195+
if let hir::TraitItemKind::Method(ref fndecl, _) = it.node {
196+
return fndecl
197+
.decl
198+
.inputs
199+
.iter()
200+
.filter_map(|arg| {
201+
self.find_visitor_found_type(&**arg, br)
202+
})
203+
.next();
204+
}
205+
} else if let hir_map::NodeImplItem(it) = self.tcx.hir.get(node_id) {
206+
if let hir::ImplItemKind::Method(ref fndecl, _) = it.node {
207+
return fndecl
208+
.decl
209+
.inputs
210+
.iter()
211+
.filter_map(|arg| {
212+
self.find_visitor_found_type(&**arg, br)
213+
})
214+
.next();
215+
}
216+
}
217+
}
218+
}
219+
}
220+
None
221+
}
222+
223+
// This method creates a FindNestedTypeVisitor which returns the
224+
// corresponding anonymous region.
225+
fn find_visitor_found_type(&self,
226+
arg: &'gcx hir::Ty,
227+
br: &ty::BoundRegion)
228+
-> Option<(&'gcx hir::Ty)> {
229+
let mut nested_visitor = FindNestedTypeVisitor {
230+
infcx: &self,
231+
hir_map: &self.tcx.hir,
232+
bound_region: *br,
233+
found_type: None,
234+
};
235+
nested_visitor.visit_ty(arg);
236+
nested_visitor.found_type
237+
}
157238
}

src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-2.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error[E0621]: explicit lifetime required in the type of `x`
22
--> $DIR/ex1-return-one-existing-name-if-else-2.rs:12:16
33
|
44
11 | fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32 {
5-
| - consider changing the type of `x` to `&'a i32`
5+
| ---- consider changing the type of `x` to `&'a i32`
66
12 | if x > y { x } else { y }
77
| ^ lifetime `'a` required
88

src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-3.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error[E0621]: explicit lifetime required in parameter type
22
--> $DIR/ex1-return-one-existing-name-if-else-3.rs:12:27
33
|
44
11 | fn foo<'a>((x, y): (&'a i32, &i32)) -> &'a i32 {
5-
| ------ consider changing type to `(&'a i32, &'a i32)`
5+
| ---- consider changing type to `(&'a i32, &'a i32)`
66
12 | if x > y { x } else { y }
77
| ^ lifetime `'a` required
88

src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-2.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error[E0621]: explicit lifetime required in the type of `x`
22
--> $DIR/ex1-return-one-existing-name-if-else-using-impl-2.rs:14:15
33
|
44
13 | fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32 {
5-
| - consider changing the type of `x` to `&'a i32`
5+
| ---- consider changing the type of `x` to `&'a i32`
66
14 | if x > y { x } else { y }
77
| ^ lifetime `'a` required
88

src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error[E0621]: explicit lifetime required in the type of `x`
22
--> $DIR/ex1-return-one-existing-name-if-else-using-impl-3.rs:18:36
33
|
44
16 | fn foo<'a>(&'a self, x: &i32) -> &i32 {
5-
| - consider changing the type of `x` to `&'a i32`
5+
| ---- consider changing the type of `x` to `&'a i32`
66
17 |
77
18 | if true { &self.field } else { x }
88
| ^ lifetime `'a` required

src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error[E0621]: explicit lifetime required in the type of `y`
22
--> $DIR/ex1-return-one-existing-name-if-else.rs:12:27
33
|
44
11 | fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32 {
5-
| - consider changing the type of `y` to `&'a i32`
5+
| ---- consider changing the type of `y` to `&'a i32`
66
12 | if x > y { x } else { y }
77
| ^ lifetime `'a` required
88

src/test/ui/lifetime-errors/ex2a-push-one-existing-name-2.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error[E0621]: explicit lifetime required in the type of `x`
22
--> $DIR/ex2a-push-one-existing-name-2.rs:16:12
33
|
44
15 | fn foo<'a>(x: Ref<i32>, y: &mut Vec<Ref<'a, i32>>) {
5-
| - consider changing the type of `x` to `Ref<'a, i32>`
5+
| -------- consider changing the type of `x` to `Ref<'a, i32>`
66
16 | y.push(x);
77
| ^ lifetime `'a` required
88

src/test/ui/lifetime-errors/ex2a-push-one-existing-name.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error[E0621]: explicit lifetime required in the type of `y`
22
--> $DIR/ex2a-push-one-existing-name.rs:16:12
33
|
44
15 | fn foo<'a>(x: &mut Vec<Ref<'a, i32>>, y: Ref<i32>) {
5-
| - consider changing the type of `y` to `Ref<'a, i32>`
5+
| -------- consider changing the type of `y` to `Ref<'a, i32>`
66
16 | x.push(y);
77
| ^ lifetime `'a` required
88

0 commit comments

Comments
 (0)