@@ -75,6 +75,7 @@ use std::collections::HashSet;
75
75
use ast_map;
76
76
use middle:: def;
77
77
use middle:: infer;
78
+ use middle:: region;
78
79
use middle:: subst;
79
80
use middle:: ty:: { self , Ty } ;
80
81
use middle:: ty:: { Region , ReFree } ;
@@ -84,16 +85,135 @@ use std::string::String;
84
85
use syntax:: ast;
85
86
use syntax:: ast_util:: name_to_dummy_lifetime;
86
87
use syntax:: owned_slice:: OwnedSlice ;
87
- use syntax:: codemap;
88
+ use syntax:: codemap:: { Pos , Span } ;
88
89
use syntax:: parse:: token;
89
90
use syntax:: print:: pprust;
90
91
use syntax:: ptr:: P ;
91
- use util:: ppaux:: note_and_explain_region;
92
92
93
93
// Note: only import UserString, not Repr, since user-facing error
94
94
// messages shouldn't include debug serializations.
95
95
use util:: ppaux:: UserString ;
96
96
97
+ pub fn note_and_explain_region ( tcx : & ty:: ctxt ,
98
+ prefix : & str ,
99
+ region : ty:: Region ,
100
+ suffix : & str ) {
101
+ fn item_scope_tag ( item : & ast:: Item ) -> & ' static str {
102
+ match item. node {
103
+ ast:: ItemImpl ( ..) => "impl" ,
104
+ ast:: ItemStruct ( ..) => "struct" ,
105
+ ast:: ItemEnum ( ..) => "enum" ,
106
+ ast:: ItemTrait ( ..) => "trait" ,
107
+ ast:: ItemFn ( ..) => "function body" ,
108
+ _ => "item"
109
+ }
110
+ }
111
+
112
+ fn explain_span ( tcx : & ty:: ctxt , heading : & str , span : Span )
113
+ -> ( String , Option < Span > ) {
114
+ let lo = tcx. sess . codemap ( ) . lookup_char_pos_adj ( span. lo ) ;
115
+ ( format ! ( "the {} at {}:{}" , heading, lo. line, lo. col. to_usize( ) ) ,
116
+ Some ( span) )
117
+ }
118
+
119
+ let ( description, span) = match region {
120
+ ty:: ReScope ( scope) => {
121
+ let new_string;
122
+ let unknown_scope = || {
123
+ format ! ( "{}unknown scope: {:?}{}. Please report a bug." ,
124
+ prefix, scope, suffix)
125
+ } ;
126
+ let span = match scope. span ( & tcx. map ) {
127
+ Some ( s) => s,
128
+ None => return tcx. sess . note ( & unknown_scope ( ) )
129
+ } ;
130
+ let tag = match tcx. map . find ( scope. node_id ( ) ) {
131
+ Some ( ast_map:: NodeBlock ( _) ) => "block" ,
132
+ Some ( ast_map:: NodeExpr ( expr) ) => match expr. node {
133
+ ast:: ExprCall ( ..) => "call" ,
134
+ ast:: ExprMethodCall ( ..) => "method call" ,
135
+ ast:: ExprMatch ( _, _, ast:: MatchSource :: IfLetDesugar { .. } ) => "if let" ,
136
+ ast:: ExprMatch ( _, _, ast:: MatchSource :: WhileLetDesugar ) => "while let" ,
137
+ ast:: ExprMatch ( _, _, ast:: MatchSource :: ForLoopDesugar ) => "for" ,
138
+ ast:: ExprMatch ( ..) => "match" ,
139
+ _ => "expression" ,
140
+ } ,
141
+ Some ( ast_map:: NodeStmt ( _) ) => "statement" ,
142
+ Some ( ast_map:: NodeItem ( it) ) => item_scope_tag ( & * it) ,
143
+ Some ( _) | None => {
144
+ return tcx. sess . span_note ( span, & unknown_scope ( ) ) ;
145
+ }
146
+ } ;
147
+ let scope_decorated_tag = match scope {
148
+ region:: CodeExtent :: Misc ( _) => tag,
149
+ region:: CodeExtent :: ParameterScope { .. } => {
150
+ "scope of parameters for function"
151
+ }
152
+ region:: CodeExtent :: DestructionScope ( _) => {
153
+ new_string = format ! ( "destruction scope surrounding {}" , tag) ;
154
+ & new_string[ ..]
155
+ }
156
+ region:: CodeExtent :: Remainder ( r) => {
157
+ new_string = format ! ( "block suffix following statement {}" ,
158
+ r. first_statement_index) ;
159
+ & new_string[ ..]
160
+ }
161
+ } ;
162
+ explain_span ( tcx, scope_decorated_tag, span)
163
+ }
164
+
165
+ ty:: ReFree ( ref fr) => {
166
+ let prefix = match fr. bound_region {
167
+ ty:: BrAnon ( idx) => {
168
+ format ! ( "the anonymous lifetime #{} defined on" , idx + 1 )
169
+ }
170
+ ty:: BrFresh ( _) => "an anonymous lifetime defined on" . to_owned ( ) ,
171
+ _ => {
172
+ format ! ( "the lifetime {} as defined on" ,
173
+ fr. bound_region. user_string( tcx) )
174
+ }
175
+ } ;
176
+
177
+ match tcx. map . find ( fr. scope . node_id ) {
178
+ Some ( ast_map:: NodeBlock ( ref blk) ) => {
179
+ let ( msg, opt_span) = explain_span ( tcx, "block" , blk. span ) ;
180
+ ( format ! ( "{} {}" , prefix, msg) , opt_span)
181
+ }
182
+ Some ( ast_map:: NodeItem ( it) ) => {
183
+ let tag = item_scope_tag ( & * it) ;
184
+ let ( msg, opt_span) = explain_span ( tcx, tag, it. span ) ;
185
+ ( format ! ( "{} {}" , prefix, msg) , opt_span)
186
+ }
187
+ Some ( _) | None => {
188
+ // this really should not happen
189
+ ( format ! ( "{} unknown free region bounded by scope {:?}" ,
190
+ prefix, fr. scope) , None )
191
+ }
192
+ }
193
+ }
194
+
195
+ ty:: ReStatic => ( "the static lifetime" . to_owned ( ) , None ) ,
196
+
197
+ ty:: ReEmpty => ( "the empty lifetime" . to_owned ( ) , None ) ,
198
+
199
+ ty:: ReEarlyBound ( ref data) => {
200
+ ( format ! ( "{}" , token:: get_name( data. name) ) , None )
201
+ }
202
+
203
+ // I believe these cases should not occur (except when debugging,
204
+ // perhaps)
205
+ ty:: ReInfer ( _) | ty:: ReLateBound ( ..) => {
206
+ ( format ! ( "lifetime {:?}" , region) , None )
207
+ }
208
+ } ;
209
+ let message = format ! ( "{}{}{}" , prefix, description, suffix) ;
210
+ if let Some ( span) = span {
211
+ tcx. sess . span_note ( span, & message) ;
212
+ } else {
213
+ tcx. sess . note ( & message) ;
214
+ }
215
+ }
216
+
97
217
pub trait ErrorReporting < ' tcx > {
98
218
fn report_region_errors ( & self ,
99
219
errors : & Vec < RegionResolutionError < ' tcx > > ) ;
@@ -161,7 +281,7 @@ trait ErrorReportingHelpers<'tcx> {
161
281
ident : ast:: Ident ,
162
282
opt_explicit_self : Option < & ast:: ExplicitSelf_ > ,
163
283
generics : & ast:: Generics ,
164
- span : codemap :: Span ) ;
284
+ span : Span ) ;
165
285
}
166
286
167
287
impl < ' a , ' tcx > ErrorReporting < ' tcx > for InferCtxt < ' a , ' tcx > {
@@ -1430,7 +1550,7 @@ impl<'a, 'tcx> ErrorReportingHelpers<'tcx> for InferCtxt<'a, 'tcx> {
1430
1550
ident : ast:: Ident ,
1431
1551
opt_explicit_self : Option < & ast:: ExplicitSelf_ > ,
1432
1552
generics : & ast:: Generics ,
1433
- span : codemap :: Span ) {
1553
+ span : Span ) {
1434
1554
let suggested_fn = pprust:: fun_to_string ( decl, unsafety, constness, ident,
1435
1555
opt_explicit_self, generics) ;
1436
1556
let msg = format ! ( "consider using an explicit lifetime \
0 commit comments