@@ -14,7 +14,7 @@ use super::method::MethodCallee;
1414use rustc:: infer:: { InferCtxt , InferOk } ;
1515use rustc:: session:: DiagnosticMessageId ;
1616use rustc:: traits:: { self , TraitEngine } ;
17- use rustc:: ty:: { self , Ty , TraitRef } ;
17+ use rustc:: ty:: { self , Ty , TyCtxt , TraitRef } ;
1818use rustc:: ty:: { ToPredicate , TypeFoldable } ;
1919use rustc:: ty:: adjustment:: { Adjustment , Adjust , OverloadedDeref } ;
2020
@@ -39,6 +39,8 @@ pub struct Autoderef<'a, 'gcx: 'tcx, 'tcx: 'a> {
3939 at_start : bool ,
4040 include_raw_pointers : bool ,
4141 span : Span ,
42+ silence_errors : bool ,
43+ reached_recursion_limit : bool
4244}
4345
4446impl < ' a , ' gcx , ' tcx > Iterator for Autoderef < ' a , ' gcx , ' tcx > {
@@ -57,24 +59,10 @@ impl<'a, 'gcx, 'tcx> Iterator for Autoderef<'a, 'gcx, 'tcx> {
5759 }
5860
5961 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 ) ;
7764 }
65+ self . reached_recursion_limit = true ;
7866 return None ;
7967 }
8068
@@ -123,6 +111,8 @@ impl<'a, 'gcx, 'tcx> Autoderef<'a, 'gcx, 'tcx> {
123111 obligations : vec ! [ ] ,
124112 at_start : true ,
125113 include_raw_pointers : false ,
114+ silence_errors : false ,
115+ reached_recursion_limit : false ,
126116 span,
127117 }
128118 }
@@ -240,6 +230,15 @@ impl<'a, 'gcx, 'tcx> Autoderef<'a, 'gcx, 'tcx> {
240230 self
241231 }
242232
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+
243242 pub fn finalize ( self , fcx : & FnCtxt < ' a , ' gcx , ' tcx > ) {
244243 fcx. register_predicates ( self . into_obligations ( ) ) ;
245244 }
@@ -249,6 +248,29 @@ impl<'a, 'gcx, 'tcx> Autoderef<'a, 'gcx, 'tcx> {
249248 }
250249}
251250
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+
252274impl < ' a , ' gcx , ' tcx > FnCtxt < ' a , ' gcx , ' tcx > {
253275 pub fn autoderef ( & ' a self , span : Span , base_ty : Ty < ' tcx > ) -> Autoderef < ' a , ' gcx , ' tcx > {
254276 Autoderef :: new ( self , self . param_env , self . body_id , span, base_ty)
0 commit comments