@@ -119,16 +119,60 @@ pub fn predicates_for_generics<'tcx>(
119
119
120
120
/// Determines whether the type `ty` is known to meet `bound` and
121
121
/// returns true if so. Returns false if `ty` either does not meet
122
- /// `bound` or is not known to meet bound.
122
+ /// `bound` or is not known to meet bound (note that this is
123
+ /// conservative towards *no impl*, which is the opposite of the
124
+ /// `evaluate` methods).
123
125
pub fn type_known_to_meet_bound_modulo_regions < ' tcx > (
124
126
infcx : & InferCtxt < ' tcx > ,
125
127
param_env : ty:: ParamEnv < ' tcx > ,
126
128
ty : Ty < ' tcx > ,
127
129
def_id : DefId ,
128
130
) -> bool {
129
131
let trait_ref = ty:: TraitRef :: new ( infcx. tcx , def_id, [ ty] ) ;
130
- let obligation = Obligation :: new ( infcx. tcx , ObligationCause :: dummy ( ) , param_env, trait_ref) ;
131
- infcx. predicate_must_hold_modulo_regions ( & obligation)
132
+ pred_known_to_hold_modulo_regions ( infcx, param_env, trait_ref)
133
+ }
134
+
135
+ /// FIXME(@lcnr): this function doesn't seem right and shouldn't exist?
136
+ ///
137
+ /// Ping me on zulip if you want to use this method and need help with finding
138
+ /// an appropriate replacement.
139
+ #[ instrument( level = "debug" , skip( infcx, param_env, pred) , ret) ]
140
+ fn pred_known_to_hold_modulo_regions < ' tcx > (
141
+ infcx : & InferCtxt < ' tcx > ,
142
+ param_env : ty:: ParamEnv < ' tcx > ,
143
+ pred : impl ToPredicate < ' tcx > ,
144
+ ) -> bool {
145
+ let obligation = Obligation :: new ( infcx. tcx , ObligationCause :: dummy ( ) , param_env, pred) ;
146
+
147
+ let result = infcx. evaluate_obligation_no_overflow ( & obligation) ;
148
+ debug ! ( ?result) ;
149
+
150
+ if result. must_apply_modulo_regions ( ) {
151
+ true
152
+ } else if result. may_apply ( ) {
153
+ // Sometimes obligations are ambiguous because the recursive evaluator
154
+ // is not smart enough, so we fall back to fulfillment when we're not certain
155
+ // that an obligation holds or not. Even still, we must make sure that
156
+ // the we do no inference in the process of checking this obligation.
157
+ let goal = infcx. resolve_vars_if_possible ( ( obligation. predicate , obligation. param_env ) ) ;
158
+ infcx. probe ( |_| {
159
+ let ocx = ObligationCtxt :: new ( infcx) ;
160
+ ocx. register_obligation ( obligation) ;
161
+
162
+ let errors = ocx. select_all_or_error ( ) ;
163
+ match errors. as_slice ( ) {
164
+ // Only known to hold if we did no inference.
165
+ [ ] => infcx. shallow_resolve ( goal) == goal,
166
+
167
+ errors => {
168
+ debug ! ( ?errors) ;
169
+ false
170
+ }
171
+ }
172
+ } )
173
+ } else {
174
+ false
175
+ }
132
176
}
133
177
134
178
#[ instrument( level = "debug" , skip( tcx, elaborated_env) ) ]
0 commit comments