@@ -4,6 +4,7 @@ use rustc_data_structures::{
44 graph:: { iterate:: DepthFirstSearch , vec_graph:: VecGraph } ,
55 unord:: { UnordBag , UnordMap , UnordSet } ,
66} ;
7+ use rustc_infer:: infer:: { DefineOpaqueTypes , InferOk } ;
78use rustc_middle:: ty:: { self , Ty } ;
89
910impl < ' tcx > FnCtxt < ' _ , ' tcx > {
@@ -23,20 +24,10 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
2324 self . fulfillment_cx. borrow_mut( ) . pending_obligations( )
2425 ) ;
2526
26- // Check if we have any unsolved variables. If not, no need for fallback.
27- let unsolved_variables = self . unsolved_variables ( ) ;
28- if unsolved_variables. is_empty ( ) {
29- return ;
30- }
27+ let fallback_occured = self . fallback_types ( ) || self . fallback_effects ( ) ;
3128
32- let diverging_fallback = self . calculate_diverging_fallback ( & unsolved_variables) ;
33-
34- // We do fallback in two passes, to try to generate
35- // better error messages.
36- // The first time, we do *not* replace opaque types.
37- for ty in unsolved_variables {
38- debug ! ( "unsolved_variable = {:?}" , ty) ;
39- self . fallback_if_possible ( ty, & diverging_fallback) ;
29+ if !fallback_occured {
30+ return ;
4031 }
4132
4233 // We now see if we can make progress. This might cause us to
@@ -65,6 +56,53 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
6556 self . select_obligations_where_possible ( |_| { } ) ;
6657 }
6758
59+ fn fallback_types ( & self ) -> bool {
60+ // Check if we have any unsolved variables. If not, no need for fallback.
61+ let unsolved_variables = self . unsolved_variables ( ) ;
62+
63+ if unsolved_variables. is_empty ( ) {
64+ return false ;
65+ }
66+
67+ let diverging_fallback = self . calculate_diverging_fallback ( & unsolved_variables) ;
68+
69+ // We do fallback in two passes, to try to generate
70+ // better error messages.
71+ // The first time, we do *not* replace opaque types.
72+ for ty in unsolved_variables {
73+ debug ! ( "unsolved_variable = {:?}" , ty) ;
74+ self . fallback_if_possible ( ty, & diverging_fallback) ;
75+ }
76+
77+ true
78+ }
79+
80+ fn fallback_effects ( & self ) -> bool {
81+ let unsolved_effects = self . unsolved_effects ( ) ;
82+
83+ if unsolved_effects. is_empty ( ) {
84+ return false ;
85+ }
86+
87+ // not setting `fallback_has_occured` here because that field is only used for type fallback
88+ // diagnostics.
89+
90+ for effect in unsolved_effects {
91+ let expected = self . tcx . consts . true_ ;
92+ let cause = self . misc ( rustc_span:: DUMMY_SP ) ;
93+ match self . at ( & cause, self . param_env ) . eq ( DefineOpaqueTypes :: Yes , expected, effect) {
94+ Ok ( InferOk { obligations, value : ( ) } ) => {
95+ self . register_predicates ( obligations) ;
96+ }
97+ Err ( e) => {
98+ bug ! ( "cannot eq unsolved effect: {e:?}" )
99+ }
100+ }
101+ }
102+
103+ true
104+ }
105+
68106 // Tries to apply a fallback to `ty` if it is an unsolved variable.
69107 //
70108 // - Unconstrained ints are replaced with `i32`.
0 commit comments