Skip to content

Commit 3280e5a

Browse files
committed
Improve error messages when illegal lifetimes are used
1 parent d26f6ed commit 3280e5a

File tree

8 files changed

+109
-56
lines changed

8 files changed

+109
-56
lines changed

src/librustc/middle/typeck/astconv.rs

Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -58,14 +58,14 @@ use middle::ty::{arg, field, substs};
5858
use middle::ty::{ty_param_substs_and_ty};
5959
use middle::ty;
6060
use middle::typeck::rscope::{in_binding_rscope};
61-
use middle::typeck::rscope::{region_scope, type_rscope};
61+
use middle::typeck::rscope::{region_scope, type_rscope, RegionError};
6262
use middle::typeck::{CrateCtxt, write_substs_to_tcx, write_ty_to_tcx};
6363

6464
use core::result;
6565
use core::vec;
6666
use syntax::ast;
6767
use syntax::codemap::span;
68-
use syntax::print::pprust::path_to_str;
68+
use syntax::print::pprust::{region_to_str, path_to_str};
6969
use util::common::indenter;
7070

7171
pub trait AstConv {
@@ -76,17 +76,31 @@ pub trait AstConv {
7676
fn ty_infer(&self, span: span) -> ty::t;
7777
}
7878

79-
pub fn get_region_reporting_err(tcx: ty::ctxt,
80-
span: span,
81-
res: Result<ty::Region, ~str>)
82-
-> ty::Region {
83-
79+
pub fn get_region_reporting_err(
80+
tcx: ty::ctxt,
81+
span: span,
82+
a_r: Option<@ast::region>,
83+
res: Result<ty::Region, RegionError>) -> ty::Region
84+
{
8485
match res {
85-
result::Ok(r) => r,
86-
result::Err(ref e) => {
87-
tcx.sess.span_err(span, (/*bad*/copy *e));
88-
ty::re_static
89-
}
86+
result::Ok(r) => r,
87+
result::Err(ref e) => {
88+
let descr = match a_r {
89+
None => ~"anonymous lifetime",
90+
Some(a) if a.node == ast::re_anon => {
91+
~"anonymous lifetime"
92+
}
93+
Some(a) => {
94+
fmt!("lifetime %s",
95+
region_to_str(a, tcx.sess.intr()))
96+
}
97+
};
98+
tcx.sess.span_err(
99+
span,
100+
fmt!("Illegal %s: %s",
101+
descr, e.msg));
102+
e.replacement
103+
}
90104
}
91105
}
92106

@@ -103,7 +117,7 @@ pub fn ast_region_to_region<AC:AstConv,RS:region_scope + Copy + Durable>(
103117
ast::re_named(id) => rscope.named_region(span, id)
104118
};
105119

106-
get_region_reporting_err(self.tcx(), span, res)
120+
get_region_reporting_err(self.tcx(), span, Some(a_r), res)
107121
}
108122

109123
pub fn ast_path_to_substs_and_ty<AC:AstConv,RS:region_scope + Copy + Durable>(
@@ -139,7 +153,7 @@ pub fn ast_path_to_substs_and_ty<AC:AstConv,RS:region_scope + Copy + Durable>(
139153
}
140154
(Some(_), None) => {
141155
let res = rscope.anon_region(path.span);
142-
let r = get_region_reporting_err(self.tcx(), path.span, res);
156+
let r = get_region_reporting_err(self.tcx(), path.span, None, res);
143157
Some(r)
144158
}
145159
(Some(_), Some(r)) => {
@@ -521,7 +535,7 @@ pub fn ty_of_closure<AC:AstConv,RS:region_scope + Copy + Durable>(
521535
ast::BorrowedSigil => {
522536
// &fn() defaults to an anonymous region:
523537
let r_result = rscope.anon_region(span);
524-
get_region_reporting_err(self.tcx(), span, r_result)
538+
get_region_reporting_err(self.tcx(), span, None, r_result)
525539
}
526540
}
527541
}

src/librustc/middle/typeck/check/mod.rs

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
n// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
1+
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
22
// file at the top-level directory of this distribution and at
33
// http://rust-lang.org/COPYRIGHT.
44
//
@@ -96,6 +96,7 @@ use middle::typeck::CrateCtxt;
9696
use middle::typeck::infer::{resolve_type, force_tvar};
9797
use middle::typeck::infer;
9898
use middle::typeck::rscope::{binding_rscope, bound_self_region};
99+
use middle::typeck::rscope::{RegionError};
99100
use middle::typeck::rscope::{in_binding_rscope, region_scope, type_rscope};
100101
use middle::typeck::rscope;
101102
use middle::typeck::{isr_alist, lookup_def_ccx, method_map_entry};
@@ -651,7 +652,8 @@ pub impl FnCtxt {
651652
fn infcx(&self) -> @mut infer::InferCtxt { self.inh.infcx }
652653
fn search_in_scope_regions(
653654
&self,
654-
br: ty::bound_region) -> Result<ty::Region, ~str>
655+
span: span,
656+
br: ty::bound_region) -> Result<ty::Region, RegionError>
655657
{
656658
let in_scope_regions = self.in_scope_regions;
657659
match in_scope_regions.find(br) {
@@ -661,25 +663,28 @@ pub impl FnCtxt {
661663
if br == blk_br {
662664
result::Ok(self.block_region())
663665
} else {
664-
result::Err(fmt!("named region `%s` not in scope here",
665-
bound_region_to_str(self.tcx(), br)))
666+
result::Err(RegionError {
667+
msg: fmt!("named region `%s` not in scope here",
668+
bound_region_to_str(self.tcx(), br)),
669+
replacement: self.infcx().next_region_var_nb(span)
670+
})
666671
}
667672
}
668673
}
669674
}
670675
}
671676

672677
impl region_scope for FnCtxt {
673-
fn anon_region(&self, span: span) -> Result<ty::Region, ~str> {
678+
fn anon_region(&self, span: span) -> Result<ty::Region, RegionError> {
674679
result::Ok(self.infcx().next_region_var_nb(span))
675680
}
676-
fn self_region(&self, _span: span) -> Result<ty::Region, ~str> {
677-
self.search_in_scope_regions(ty::br_self)
681+
fn self_region(&self, span: span) -> Result<ty::Region, RegionError> {
682+
self.search_in_scope_regions(span, ty::br_self)
678683
}
679684
fn named_region(&self,
680-
_span: span,
681-
id: ast::ident) -> Result<ty::Region, ~str> {
682-
self.search_in_scope_regions(ty::br_named(id))
685+
span: span,
686+
id: ast::ident) -> Result<ty::Region, RegionError> {
687+
self.search_in_scope_regions(span, ty::br_named(id))
683688
}
684689
}
685690

src/librustc/middle/typeck/rscope.rs

Lines changed: 53 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -17,24 +17,33 @@ use core::result;
1717
use syntax::ast;
1818
use syntax::codemap::span;
1919

20+
pub struct RegionError {
21+
msg: ~str,
22+
replacement: ty::Region
23+
}
24+
2025
pub trait region_scope {
21-
fn anon_region(&self, span: span) -> Result<ty::Region, ~str>;
22-
fn self_region(&self, span: span) -> Result<ty::Region, ~str>;
26+
fn anon_region(&self, span: span) -> Result<ty::Region, RegionError>;
27+
fn self_region(&self, span: span) -> Result<ty::Region, RegionError>;
2328
fn named_region(&self, span: span, id: ast::ident)
24-
-> Result<ty::Region, ~str>;
29+
-> Result<ty::Region, RegionError>;
2530
}
2631

2732
pub enum empty_rscope { empty_rscope }
2833
impl region_scope for empty_rscope {
29-
fn anon_region(&self, _span: span) -> Result<ty::Region, ~str> {
30-
result::Err(~"only the static region is allowed here")
34+
fn anon_region(&self, _span: span) -> Result<ty::Region, RegionError> {
35+
result::Err(RegionError {
36+
msg: ~"only 'static is allowed here",
37+
replacement: ty::re_static
38+
})
3139
}
32-
fn self_region(&self, _span: span) -> Result<ty::Region, ~str> {
33-
result::Err(~"only the static region is allowed here")
40+
fn self_region(&self, _span: span) -> Result<ty::Region, RegionError> {
41+
self.anon_region(_span)
3442
}
3543
fn named_region(&self, _span: span, _id: ast::ident)
36-
-> Result<ty::Region, ~str> {
37-
result::Err(~"only the static region is allowed here")
44+
-> Result<ty::Region, RegionError>
45+
{
46+
self.anon_region(_span)
3847
}
3948
}
4049

@@ -43,38 +52,59 @@ pub struct MethodRscope {
4352
region_parameterization: Option<ty::region_variance>
4453
}
4554
impl region_scope for MethodRscope {
46-
fn anon_region(&self, _span: span) -> Result<ty::Region, ~str> {
47-
result::Err(~"anonymous region types are not permitted here")
55+
fn anon_region(&self, _span: span) -> Result<ty::Region, RegionError> {
56+
result::Err(RegionError {
57+
msg: ~"anonymous lifetimes are not permitted here",
58+
replacement: ty::re_bound(ty::br_self)
59+
})
4860
}
49-
fn self_region(&self, _span: span) -> Result<ty::Region, ~str> {
61+
fn self_region(&self, _span: span) -> Result<ty::Region, RegionError> {
5062
assert self.region_parameterization.is_some() ||
5163
self.self_ty.is_borrowed();
5264
result::Ok(ty::re_bound(ty::br_self))
5365
}
5466
fn named_region(&self, span: span, id: ast::ident)
55-
-> Result<ty::Region, ~str> {
67+
-> Result<ty::Region, RegionError> {
5668
do empty_rscope.named_region(span, id).chain_err |_e| {
57-
result::Err(~"region is not in scope here")
69+
result::Err(RegionError {
70+
msg: ~"lifetime is not in scope",
71+
replacement: ty::re_bound(ty::br_self)
72+
})
5873
}
5974
}
6075
}
6176

6277
pub enum type_rscope = Option<ty::region_variance>;
78+
impl type_rscope {
79+
priv fn replacement(&self) -> ty::Region {
80+
if self.is_some() {
81+
ty::re_bound(ty::br_self)
82+
} else {
83+
ty::re_static
84+
}
85+
}
86+
}
6387
impl region_scope for type_rscope {
64-
fn anon_region(&self, _span: span) -> Result<ty::Region, ~str> {
65-
result::Err(~"anonymous region types are not permitted here")
88+
fn anon_region(&self, _span: span) -> Result<ty::Region, RegionError> {
89+
result::Err(RegionError {
90+
msg: ~"anonymous lifetimes are not permitted here",
91+
replacement: self.replacement()
92+
})
6693
}
67-
fn self_region(&self, _span: span) -> Result<ty::Region, ~str> {
94+
fn self_region(&self, _span: span) -> Result<ty::Region, RegionError> {
6895
// if the self region is used, region parameterization should
6996
// have inferred that this type is RP
7097
assert self.is_some();
7198
result::Ok(ty::re_bound(ty::br_self))
7299
}
73100
fn named_region(&self, span: span, id: ast::ident)
74-
-> Result<ty::Region, ~str> {
101+
-> Result<ty::Region, RegionError> {
75102
do empty_rscope.named_region(span, id).chain_err |_e| {
76-
result::Err(~"named regions other than `self` are not \
77-
allowed as part of a type declaration")
103+
result::Err(RegionError {
104+
msg: ~"only 'self is allowed allowed as \
105+
part of a type declaration",
106+
replacement: self.replacement()
107+
})
78108
}
79109
}
80110
}
@@ -98,17 +128,17 @@ pub fn in_binding_rscope<RS:region_scope + Copy + Durable>(self: &RS)
98128
binding_rscope { base: base, anon_bindings: @mut 0 }
99129
}
100130
impl region_scope for binding_rscope {
101-
fn anon_region(&self, _span: span) -> Result<ty::Region, ~str> {
131+
fn anon_region(&self, _span: span) -> Result<ty::Region, RegionError> {
102132
let idx = *self.anon_bindings;
103133
*self.anon_bindings += 1;
104134
result::Ok(ty::re_bound(ty::br_anon(idx)))
105135
}
106-
fn self_region(&self, span: span) -> Result<ty::Region, ~str> {
136+
fn self_region(&self, span: span) -> Result<ty::Region, RegionError> {
107137
self.base.self_region(span)
108138
}
109139
fn named_region(&self,
110140
span: span,
111-
id: ast::ident) -> Result<ty::Region, ~str>
141+
id: ast::ident) -> Result<ty::Region, RegionError>
112142
{
113143
do self.base.named_region(span, id).chain_err |_e| {
114144
result::Ok(ty::re_bound(ty::br_named(id)))

src/libsyntax/print/pprust.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,10 @@ pub fn expr_to_str(e: @ast::expr, intr: @ident_interner) -> ~str {
147147
to_str(e, print_expr, intr)
148148
}
149149

150+
pub fn region_to_str(e: @ast::region, intr: @ident_interner) -> ~str {
151+
to_str(e, |s, e| print_region(s, ~"&", e, ~""), intr)
152+
}
153+
150154
pub fn tt_to_str(tt: ast::token_tree, intr: @ident_interner) -> ~str {
151155
to_str(tt, print_tt, intr)
152156
}

src/test/compile-fail/regions-in-consts.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
const c_x: &'blk int = &22; //~ ERROR only the static region is allowed here
12-
const c_y: &int = &22; //~ ERROR only the static region is allowed here
11+
const c_x: &'blk int = &22; //~ ERROR Illegal lifetime &blk: only 'static is allowed here
12+
const c_y: &int = &22; //~ ERROR Illegal anonymous lifetime: only 'static is allowed here
1313
const c_z: &'static int = &22;
1414

1515
fn main() {

src/test/compile-fail/regions-in-enums.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,15 @@
1010

1111
enum yes0<'lt> {
1212
// This will eventually be legal (and in fact the only way):
13-
X3(&'lt uint) //~ ERROR named regions other than `self` are not allowed as part of a type declaration
13+
X3(&'lt uint) //~ ERROR Illegal lifetime &lt: only 'self is allowed allowed as part of a type declaration
1414
}
1515

1616
enum yes1 {
1717
X4(&'self uint)
1818
}
1919

2020
enum yes2 {
21-
X5(&'foo uint) //~ ERROR named regions other than `self` are not allowed as part of a type declaration
21+
X5(&'foo uint) //~ ERROR Illegal lifetime &foo: only 'self is allowed allowed as part of a type declaration
2222
}
2323

2424
fn main() {}

src/test/compile-fail/regions-in-structs.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,15 @@
99
// except according to those terms.
1010

1111
struct yes0<'self> {
12-
x: &uint, //~ ERROR anonymous region types are not permitted here
12+
x: &uint, //~ ERROR Illegal anonymous lifetime: anonymous lifetimes are not permitted here
1313
}
1414

1515
struct yes1<'self> {
1616
x: &'self uint,
1717
}
1818

1919
struct yes2<'self> {
20-
x: &'foo uint, //~ ERROR named regions other than `self` are not allowed as part of a type declaration
20+
x: &'foo uint, //~ ERROR Illegal lifetime &foo: only 'self is allowed allowed as part of a type declaration
2121
}
2222

2323
fn main() {}

src/test/compile-fail/regions-in-type-items.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,15 @@
99
// except according to those terms.
1010

1111
type item_ty_yes0 = {
12-
x: &uint //~ ERROR anonymous region types are not permitted here
12+
x: &uint //~ ERROR Illegal anonymous lifetime: anonymous lifetimes are not permitted here
1313
};
1414

1515
type item_ty_yes1 = {
1616
x: &'self uint
1717
};
1818

1919
type item_ty_yes2 = {
20-
x: &'foo uint //~ ERROR named regions other than `self` are not allowed as part of a type declaration
20+
x: &'foo uint //~ ERROR Illegal lifetime &foo: only 'self is allowed allowed as part of a type declaration
2121
};
2222

2323
fn main() {}

0 commit comments

Comments
 (0)