@@ -14,7 +14,7 @@ use super::method::MethodCallee;
14
14
use rustc:: infer:: { InferCtxt , InferOk } ;
15
15
use rustc:: session:: DiagnosticMessageId ;
16
16
use rustc:: traits:: { self , TraitEngine } ;
17
- use rustc:: ty:: { self , Ty , TraitRef } ;
17
+ use rustc:: ty:: { self , Ty , TyCtxt , TraitRef } ;
18
18
use rustc:: ty:: { ToPredicate , TypeFoldable } ;
19
19
use rustc:: ty:: adjustment:: { Adjustment , Adjust , OverloadedDeref } ;
20
20
@@ -39,6 +39,8 @@ pub struct Autoderef<'a, 'gcx: 'tcx, 'tcx: 'a> {
39
39
at_start : bool ,
40
40
include_raw_pointers : bool ,
41
41
span : Span ,
42
+ silence_errors : bool ,
43
+ reached_recursion_limit : bool
42
44
}
43
45
44
46
impl < ' a , ' gcx , ' tcx > Iterator for Autoderef < ' a , ' gcx , ' tcx > {
@@ -57,24 +59,10 @@ impl<'a, 'gcx, 'tcx> Iterator for Autoderef<'a, 'gcx, 'tcx> {
57
59
}
58
60
59
61
if self . steps . len ( ) >= * tcx. sess . recursion_limit . get ( ) {
60
- // We've reached the recursion limit, error gracefully.
61
- let suggested_limit = * tcx. sess . recursion_limit . get ( ) * 2 ;
62
- let msg = format ! ( "reached the recursion limit while auto-dereferencing `{:?}`" ,
63
- self . cur_ty) ;
64
- let error_id = ( DiagnosticMessageId :: ErrorId ( 55 ) , Some ( self . span ) , msg) ;
65
- let fresh = tcx. sess . one_time_diagnostics . borrow_mut ( ) . insert ( error_id) ;
66
- if fresh {
67
- struct_span_err ! ( tcx. sess,
68
- self . span,
69
- E0055 ,
70
- "reached the recursion limit while auto-dereferencing `{:?}`" ,
71
- self . cur_ty)
72
- . span_label ( self . span , "deref recursion limit reached" )
73
- . help ( & format ! (
74
- "consider adding a `#![recursion_limit=\" {}\" ]` attribute to your crate" ,
75
- suggested_limit) )
76
- . emit ( ) ;
62
+ if !self . silence_errors {
63
+ report_autoderef_recursion_limit_error ( tcx, self . span , self . cur_ty ) ;
77
64
}
65
+ self . reached_recursion_limit = true ;
78
66
return None ;
79
67
}
80
68
@@ -123,6 +111,8 @@ impl<'a, 'gcx, 'tcx> Autoderef<'a, 'gcx, 'tcx> {
123
111
obligations : vec ! [ ] ,
124
112
at_start : true ,
125
113
include_raw_pointers : false ,
114
+ silence_errors : false ,
115
+ reached_recursion_limit : false ,
126
116
span,
127
117
}
128
118
}
@@ -240,6 +230,15 @@ impl<'a, 'gcx, 'tcx> Autoderef<'a, 'gcx, 'tcx> {
240
230
self
241
231
}
242
232
233
+ pub fn silence_errors ( mut self ) -> Self {
234
+ self . silence_errors = true ;
235
+ self
236
+ }
237
+
238
+ pub fn reached_recursion_limit ( & self ) -> bool {
239
+ self . reached_recursion_limit
240
+ }
241
+
243
242
pub fn finalize ( self , fcx : & FnCtxt < ' a , ' gcx , ' tcx > ) {
244
243
fcx. register_predicates ( self . into_obligations ( ) ) ;
245
244
}
@@ -249,6 +248,29 @@ impl<'a, 'gcx, 'tcx> Autoderef<'a, 'gcx, 'tcx> {
249
248
}
250
249
}
251
250
251
+ pub fn report_autoderef_recursion_limit_error < ' a , ' gcx , ' tcx > (
252
+ tcx : TyCtxt < ' a , ' gcx , ' tcx > , span : Span , ty : Ty < ' tcx > )
253
+ {
254
+ // We've reached the recursion limit, error gracefully.
255
+ let suggested_limit = * tcx. sess . recursion_limit . get ( ) * 2 ;
256
+ let msg = format ! ( "reached the recursion limit while auto-dereferencing `{:?}`" ,
257
+ ty) ;
258
+ let error_id = ( DiagnosticMessageId :: ErrorId ( 55 ) , Some ( span) , msg) ;
259
+ let fresh = tcx. sess . one_time_diagnostics . borrow_mut ( ) . insert ( error_id) ;
260
+ if fresh {
261
+ struct_span_err ! ( tcx. sess,
262
+ span,
263
+ E0055 ,
264
+ "reached the recursion limit while auto-dereferencing `{:?}`" ,
265
+ ty)
266
+ . span_label ( span, "deref recursion limit reached" )
267
+ . help ( & format ! (
268
+ "consider adding a `#![recursion_limit=\" {}\" ]` attribute to your crate" ,
269
+ suggested_limit) )
270
+ . emit ( ) ;
271
+ }
272
+ }
273
+
252
274
impl < ' a , ' gcx , ' tcx > FnCtxt < ' a , ' gcx , ' tcx > {
253
275
pub fn autoderef ( & ' a self , span : Span , base_ty : Ty < ' tcx > ) -> Autoderef < ' a , ' gcx , ' tcx > {
254
276
Autoderef :: new ( self , self . param_env , self . body_id , span, base_ty)
0 commit comments