@@ -22,7 +22,7 @@ use rustc_errors::{DiagnosticBuilder, EmissionGuarantee};
2222use rustc_hir:: def:: DefKind ;
2323use rustc_hir:: def_id:: { DefId , LOCAL_CRATE } ;
2424use rustc_infer:: infer:: { DefineOpaqueTypes , InferCtxt , TyCtxtInferExt } ;
25- use rustc_infer:: traits:: { util, TraitEngine , TraitEngineExt } ;
25+ use rustc_infer:: traits:: { util, FulfillmentErrorCode , TraitEngine , TraitEngineExt } ;
2626use rustc_middle:: traits:: query:: NoSolution ;
2727use rustc_middle:: traits:: solve:: { CandidateSource , Certainty , Goal } ;
2828use rustc_middle:: traits:: specialization_graph:: OverlapMode ;
@@ -35,6 +35,8 @@ use rustc_span::DUMMY_SP;
3535use std:: fmt:: Debug ;
3636use std:: ops:: ControlFlow ;
3737
38+ use super :: error_reporting:: suggest_new_overflow_limit;
39+
3840/// Whether we do the orphan check relative to this crate or
3941/// to some remote crate.
4042#[ derive( Copy , Clone , Debug ) ]
@@ -56,6 +58,9 @@ pub struct OverlapResult<'tcx> {
5658 /// `true` if the overlap might've been permitted before the shift
5759 /// to universes.
5860 pub involves_placeholder : bool ,
61+
62+ /// Used in the new solver to suggest increasing the recursion limit.
63+ pub overflowing_predicates : Vec < ty:: Predicate < ' tcx > > ,
5964}
6065
6166pub fn add_placeholder_note < G : EmissionGuarantee > ( err : & mut DiagnosticBuilder < ' _ , G > ) {
@@ -65,6 +70,18 @@ pub fn add_placeholder_note<G: EmissionGuarantee>(err: &mut DiagnosticBuilder<'_
6570 ) ;
6671}
6772
73+ pub fn suggest_increasing_recursion_limit < ' tcx , G : EmissionGuarantee > (
74+ tcx : TyCtxt < ' tcx > ,
75+ err : & mut DiagnosticBuilder < ' _ , G > ,
76+ overflowing_predicates : & [ ty:: Predicate < ' tcx > ] ,
77+ ) {
78+ for pred in overflowing_predicates {
79+ err. note ( format ! ( "overflow evaluating the requirement `{}`" , pred) ) ;
80+ }
81+
82+ suggest_new_overflow_limit ( tcx, err) ;
83+ }
84+
6885#[ derive( Debug , Clone , Copy ) ]
6986enum TrackAmbiguityCauses {
7087 Yes ,
@@ -221,11 +238,11 @@ fn overlap<'tcx>(
221238 ) ,
222239 ) ;
223240
241+ let mut overflowing_predicates = Vec :: new ( ) ;
224242 if overlap_mode. use_implicit_negative ( ) {
225- if let Some ( _failing_obligation) =
226- impl_intersection_has_impossible_obligation ( selcx, & obligations)
227- {
228- return None ;
243+ match impl_intersection_has_impossible_obligation ( selcx, & obligations) {
244+ Ok ( ( ) ) => return None ,
245+ Err ( p) => overflowing_predicates = p,
229246 }
230247 }
231248
@@ -261,7 +278,12 @@ fn overlap<'tcx>(
261278 impl_header = deeply_normalize_for_diagnostics ( & infcx, param_env, impl_header) ;
262279 }
263280
264- Some ( OverlapResult { impl_header, intercrate_ambiguity_causes, involves_placeholder } )
281+ Some ( OverlapResult {
282+ impl_header,
283+ intercrate_ambiguity_causes,
284+ involves_placeholder,
285+ overflowing_predicates,
286+ } )
265287}
266288
267289#[ instrument( level = "debug" , skip( infcx) , ret) ]
@@ -305,10 +327,14 @@ fn equate_impl_headers<'tcx>(
305327/// of the two impls above to be empty.
306328///
307329/// Importantly, this works even if there isn't a `impl !Error for MyLocalType`.
330+ ///
331+ /// If there is no impossible obligation, this returns a list of obligations which
332+ /// overflowed by hitting the `recursion_limit` in the new solver. This is used
333+ /// to improve the error message.
308334fn impl_intersection_has_impossible_obligation < ' a , ' cx , ' tcx > (
309335 selcx : & mut SelectionContext < ' cx , ' tcx > ,
310336 obligations : & ' a [ PredicateObligation < ' tcx > ] ,
311- ) -> Option < PredicateObligation < ' tcx > > {
337+ ) -> Result < ( ) , Vec < ty :: Predicate < ' tcx > > > {
312338 let infcx = selcx. infcx ;
313339
314340 if infcx. next_trait_solver ( ) {
@@ -317,28 +343,42 @@ fn impl_intersection_has_impossible_obligation<'a, 'cx, 'tcx>(
317343
318344 // We only care about the obligations that are *definitely* true errors.
319345 // Ambiguities do not prove the disjointness of two impls.
320- let mut errors = fulfill_cx. select_where_possible ( infcx) ;
321- errors. pop ( ) . map ( |err| err. obligation )
346+ let errors = fulfill_cx. select_where_possible ( infcx) ;
347+ if errors. is_empty ( ) {
348+ let overflow_errors = fulfill_cx. collect_remaining_errors ( infcx) ;
349+ let overflowing_predicates = overflow_errors
350+ . into_iter ( )
351+ . filter ( |e| match e. code {
352+ FulfillmentErrorCode :: Ambiguity { overflow : Some ( true ) } => true ,
353+ _ => false ,
354+ } )
355+ . map ( |e| infcx. resolve_vars_if_possible ( e. obligation . predicate ) )
356+ . collect ( ) ;
357+ Err ( overflowing_predicates)
358+ } else {
359+ Ok ( ( ) )
360+ }
322361 } else {
323- obligations
324- . iter ( )
325- . find ( |obligation| {
326- // We use `evaluate_root_obligation` to correctly track intercrate
327- // ambiguity clauses. We cannot use this in the new solver.
328- let evaluation_result = selcx. evaluate_root_obligation ( obligation) ;
329-
330- match evaluation_result {
331- Ok ( result) => !result. may_apply ( ) ,
332- // If overflow occurs, we need to conservatively treat the goal as possibly holding,
333- // since there can be instantiations of this goal that don't overflow and result in
334- // success. This isn't much of a problem in the old solver, since we treat overflow
335- // fatally (this still can be encountered: <https://github.com/rust-lang/rust/issues/105231>),
336- // but in the new solver, this is very important for correctness, since overflow
337- // *must* be treated as ambiguity for completeness.
338- Err ( _overflow) => false ,
362+ for obligation in obligations {
363+ // We use `evaluate_root_obligation` to correctly track intercrate
364+ // ambiguity clauses.
365+ let evaluation_result = selcx. evaluate_root_obligation ( obligation) ;
366+
367+ match evaluation_result {
368+ Ok ( result) => {
369+ if !result. may_apply ( ) {
370+ return Ok ( ( ) ) ;
371+ }
339372 }
340- } )
341- . cloned ( )
373+ // If overflow occurs, we need to conservatively treat the goal as possibly holding,
374+ // since there can be instantiations of this goal that don't overflow and result in
375+ // success. While this isn't much of a problem in the old solver, since we treat overflow
376+ // fatally, this still can be encountered: <https://github.com/rust-lang/rust/issues/105231>.
377+ Err ( _overflow) => { }
378+ }
379+ }
380+
381+ Err ( Vec :: new ( ) )
342382 }
343383}
344384
0 commit comments