@@ -4,6 +4,7 @@ use rustc_data_structures::{
4
4
graph:: { iterate:: DepthFirstSearch , vec_graph:: VecGraph } ,
5
5
unord:: { UnordBag , UnordMap , UnordSet } ,
6
6
} ;
7
+ use rustc_infer:: infer:: { DefineOpaqueTypes , InferOk } ;
7
8
use rustc_middle:: ty:: { self , Ty } ;
8
9
9
10
impl < ' tcx > FnCtxt < ' _ , ' tcx > {
@@ -23,20 +24,10 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
23
24
self . fulfillment_cx. borrow_mut( ) . pending_obligations( )
24
25
) ;
25
26
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 ( ) ;
31
28
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 ;
40
31
}
41
32
42
33
// We now see if we can make progress. This might cause us to
@@ -65,6 +56,53 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
65
56
self . select_obligations_where_possible ( |_| { } ) ;
66
57
}
67
58
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
+
68
106
// Tries to apply a fallback to `ty` if it is an unsolved variable.
69
107
//
70
108
// - Unconstrained ints are replaced with `i32`.
0 commit comments