@@ -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