rustc_trait_selection/traits/
engine.rs1use std::cell::RefCell;
2use std::fmt::Debug;
3
4use rustc_data_structures::fx::FxIndexSet;
5use rustc_errors::ErrorGuaranteed;
6use rustc_hir::def_id::{DefId, LocalDefId};
7use rustc_infer::infer::at::ToTrace;
8use rustc_infer::infer::canonical::{
9 Canonical, CanonicalQueryResponse, CanonicalVarValues, QueryResponse,
10};
11use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk, RegionResolutionError, TypeTrace};
12use rustc_infer::traits::{PredicateObligations, TraitErrors};
13use rustc_middle::arena::ArenaAllocatable;
14use rustc_middle::traits::query::NoSolution;
15use rustc_middle::ty::error::TypeError;
16use rustc_middle::ty::relate::Relate;
17use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, Unnormalized, Upcast, Variance};
18use thin_vec::ThinVec;
19
20use super::{FromSolverError, FulfillmentContext, ScrubbedTraitError, TraitEngine};
21use crate::error_reporting::InferCtxtErrorExt;
22use crate::regions::InferCtxtRegionExt;
23use crate::solve::{FulfillmentCtxt as NextFulfillmentCtxt, NextSolverError};
24use crate::traits::fulfill::OldSolverError;
25use crate::traits::{
26 FulfillmentError, NormalizeExt, Obligation, ObligationCause, PredicateObligation,
27 StructurallyNormalizeExt,
28};
29
30pub enum FulfillmentEngine<'tcx, E> {
35 Old(FulfillmentContext<'tcx, E>),
36 Next(NextFulfillmentCtxt<'tcx, E>),
37}
38
39impl<'tcx, E> FulfillmentEngine<'tcx, E>
40where
41 E: FromSolverError<'tcx, NextSolverError<'tcx>> + FromSolverError<'tcx, OldSolverError<'tcx>>,
42{
43 pub fn new(infcx: &InferCtxt<'tcx>) -> Self {
44 if infcx.next_trait_solver() {
45 FulfillmentEngine::Next(NextFulfillmentCtxt::new(infcx))
46 } else {
47 if !!infcx.tcx.next_trait_solver_globally() {
{
::core::panicking::panic_fmt(format_args!("using old solver even though new solver is enabled globally"));
}
};assert!(
48 !infcx.tcx.next_trait_solver_globally(),
49 "using old solver even though new solver is enabled globally"
50 );
51 FulfillmentEngine::Old(FulfillmentContext::new(infcx))
52 }
53 }
54}
55
56impl<'tcx, E> TraitEngine<'tcx, E> for FulfillmentEngine<'tcx, E>
57where
58 E: FromSolverError<'tcx, NextSolverError<'tcx>> + FromSolverError<'tcx, OldSolverError<'tcx>>,
59{
60 fn register_predicate_obligation(
61 &mut self,
62 infcx: &InferCtxt<'tcx>,
63 obligation: PredicateObligation<'tcx>,
64 ) {
65 match self {
66 FulfillmentEngine::Old(engine) => {
67 engine.register_predicate_obligation(infcx, obligation)
68 }
69 FulfillmentEngine::Next(engine) => {
70 engine.register_predicate_obligation(infcx, obligation)
71 }
72 }
73 }
74
75 fn register_predicate_obligations(
76 &mut self,
77 infcx: &InferCtxt<'tcx>,
78 obligations: PredicateObligations<'tcx>,
79 ) {
80 match self {
81 FulfillmentEngine::Old(engine) => {
82 engine.register_predicate_obligations(infcx, obligations)
83 }
84 FulfillmentEngine::Next(engine) => {
85 engine.register_predicate_obligations(infcx, obligations)
86 }
87 }
88 }
89
90 fn try_evaluate_obligations(&mut self, infcx: &InferCtxt<'tcx>) -> TraitErrors<E> {
91 match self {
92 FulfillmentEngine::Old(engine) => engine.try_evaluate_obligations(infcx),
93 FulfillmentEngine::Next(engine) => engine.try_evaluate_obligations(infcx),
94 }
95 }
96
97 fn collect_remaining_errors(&mut self, infcx: &InferCtxt<'tcx>) -> TraitErrors<E> {
98 match self {
99 FulfillmentEngine::Old(engine) => engine.collect_remaining_errors(infcx),
100 FulfillmentEngine::Next(engine) => engine.collect_remaining_errors(infcx),
101 }
102 }
103
104 fn has_pending_obligations(&self) -> bool {
105 match self {
106 FulfillmentEngine::Old(engine) => engine.has_pending_obligations(),
107 FulfillmentEngine::Next(engine) => engine.has_pending_obligations(),
108 }
109 }
110
111 fn pending_obligations(&self) -> PredicateObligations<'tcx> {
112 match self {
113 FulfillmentEngine::Old(engine) => engine.pending_obligations(),
114 FulfillmentEngine::Next(engine) => engine.pending_obligations(),
115 }
116 }
117
118 fn pending_obligations_potentially_referencing_sub_root(
119 &self,
120 infcx: &InferCtxt<'tcx>,
121 sub_root: ty::TyVid,
122 ) -> PredicateObligations<'tcx> {
123 match self {
124 FulfillmentEngine::Old(engine) => {
125 engine.pending_obligations_potentially_referencing_sub_root(infcx, sub_root)
126 }
127 FulfillmentEngine::Next(engine) => {
128 engine.pending_obligations_potentially_referencing_sub_root(infcx, sub_root)
129 }
130 }
131 }
132
133 fn drain_stalled_obligations_for_coroutines(
134 &mut self,
135 infcx: &InferCtxt<'tcx>,
136 ) -> PredicateObligations<'tcx> {
137 match self {
138 FulfillmentEngine::Old(engine) => {
139 engine.drain_stalled_obligations_for_coroutines(infcx)
140 }
141 FulfillmentEngine::Next(engine) => {
142 engine.drain_stalled_obligations_for_coroutines(infcx)
143 }
144 }
145 }
146}
147
148pub struct ObligationCtxt<'a, 'tcx, E = ScrubbedTraitError<'tcx>> {
151 pub infcx: &'a InferCtxt<'tcx>,
152 engine: RefCell<FulfillmentEngine<'tcx, E>>,
153}
154
155impl<'a, 'tcx> ObligationCtxt<'a, 'tcx, FulfillmentError<'tcx>> {
156 pub fn new_with_diagnostics(infcx: &'a InferCtxt<'tcx>) -> Self {
157 Self { infcx, engine: RefCell::new(FulfillmentEngine::new(infcx)) }
158 }
159}
160
161impl<'a, 'tcx> ObligationCtxt<'a, 'tcx, ScrubbedTraitError<'tcx>> {
162 pub fn new(infcx: &'a InferCtxt<'tcx>) -> Self {
163 Self { infcx, engine: RefCell::new(FulfillmentEngine::new(infcx)) }
164 }
165}
166
167impl<'a, 'tcx, E> ObligationCtxt<'a, 'tcx, E>
168where
169 E: FromSolverError<'tcx, NextSolverError<'tcx>> + FromSolverError<'tcx, OldSolverError<'tcx>>,
170{
171 pub fn register_obligation(&self, obligation: PredicateObligation<'tcx>) {
172 self.engine.borrow_mut().register_predicate_obligation(self.infcx, obligation);
173 }
174
175 pub fn register_obligations(
176 &self,
177 obligations: impl IntoIterator<Item = PredicateObligation<'tcx>>,
178 ) {
179 for obligation in obligations {
182 self.engine.borrow_mut().register_predicate_obligation(self.infcx, obligation)
183 }
184 }
185
186 pub fn register_infer_ok_obligations<T>(&self, infer_ok: InferOk<'tcx, T>) -> T {
187 let InferOk { value, obligations } = infer_ok;
188 self.engine.borrow_mut().register_predicate_obligations(self.infcx, obligations);
189 value
190 }
191
192 pub fn register_bound(
196 &self,
197 cause: ObligationCause<'tcx>,
198 param_env: ty::ParamEnv<'tcx>,
199 ty: Ty<'tcx>,
200 def_id: DefId,
201 ) {
202 let tcx = self.infcx.tcx;
203 let trait_ref = ty::TraitRef::new(tcx, def_id, [ty]);
204 self.register_obligation(Obligation {
205 cause,
206 recursion_depth: 0,
207 param_env,
208 predicate: trait_ref.upcast(tcx),
209 });
210 }
211
212 pub fn normalize<T: TypeFoldable<TyCtxt<'tcx>>>(
213 &self,
214 cause: &ObligationCause<'tcx>,
215 param_env: ty::ParamEnv<'tcx>,
216 value: Unnormalized<'tcx, T>,
217 ) -> T {
218 let infer_ok = self.infcx.at(cause, param_env).normalize(value);
219 self.register_infer_ok_obligations(infer_ok)
220 }
221
222 pub fn eq<T: ToTrace<'tcx>>(
223 &self,
224 cause: &ObligationCause<'tcx>,
225 param_env: ty::ParamEnv<'tcx>,
226 expected: T,
227 actual: T,
228 ) -> Result<(), TypeError<'tcx>> {
229 self.infcx
230 .at(cause, param_env)
231 .eq(DefineOpaqueTypes::Yes, expected, actual)
232 .map(|infer_ok| self.register_infer_ok_obligations(infer_ok))
233 }
234
235 pub fn eq_trace<T: Relate<TyCtxt<'tcx>>>(
236 &self,
237 cause: &ObligationCause<'tcx>,
238 param_env: ty::ParamEnv<'tcx>,
239 trace: TypeTrace<'tcx>,
240 expected: T,
241 actual: T,
242 ) -> Result<(), TypeError<'tcx>> {
243 self.infcx
244 .at(cause, param_env)
245 .eq_trace(DefineOpaqueTypes::Yes, trace, expected, actual)
246 .map(|infer_ok| self.register_infer_ok_obligations(infer_ok))
247 }
248
249 pub fn sub<T: ToTrace<'tcx>>(
251 &self,
252 cause: &ObligationCause<'tcx>,
253 param_env: ty::ParamEnv<'tcx>,
254 expected: T,
255 actual: T,
256 ) -> Result<(), TypeError<'tcx>> {
257 self.infcx
258 .at(cause, param_env)
259 .sub(DefineOpaqueTypes::Yes, expected, actual)
260 .map(|infer_ok| self.register_infer_ok_obligations(infer_ok))
261 }
262
263 pub fn relate<T: ToTrace<'tcx>>(
264 &self,
265 cause: &ObligationCause<'tcx>,
266 param_env: ty::ParamEnv<'tcx>,
267 variance: Variance,
268 expected: T,
269 actual: T,
270 ) -> Result<(), TypeError<'tcx>> {
271 self.infcx
272 .at(cause, param_env)
273 .relate(DefineOpaqueTypes::Yes, expected, variance, actual)
274 .map(|infer_ok| self.register_infer_ok_obligations(infer_ok))
275 }
276
277 pub fn sup<T: ToTrace<'tcx>>(
279 &self,
280 cause: &ObligationCause<'tcx>,
281 param_env: ty::ParamEnv<'tcx>,
282 expected: T,
283 actual: T,
284 ) -> Result<(), TypeError<'tcx>> {
285 self.infcx
286 .sup_raw(cause, param_env, DefineOpaqueTypes::Yes, expected, actual)
287 .map(|infer_ok| self.register_infer_ok_obligations(infer_ok))
288 }
289
290 pub fn lub<T: ToTrace<'tcx>>(
292 &self,
293 cause: &ObligationCause<'tcx>,
294 param_env: ty::ParamEnv<'tcx>,
295 expected: T,
296 actual: T,
297 ) -> Result<T, TypeError<'tcx>> {
298 self.infcx
299 .at(cause, param_env)
300 .lub(expected, actual)
301 .map(|infer_ok| self.register_infer_ok_obligations(infer_ok))
302 }
303
304 #[must_use]
313 pub fn try_evaluate_obligations(&self) -> TraitErrors<E> {
314 self.engine.borrow_mut().try_evaluate_obligations(self.infcx)
315 }
316
317 #[must_use]
326 pub fn evaluate_obligations_error_on_ambiguity(&self) -> TraitErrors<E> {
327 self.engine.borrow_mut().evaluate_obligations_error_on_ambiguity(self.infcx)
328 }
329
330 #[must_use]
338 pub fn into_pending_obligations(self) -> PredicateObligations<'tcx> {
339 self.engine.borrow().pending_obligations()
340 }
341
342 pub fn resolve_regions_and_report_errors(
347 self,
348 body_def_id: LocalDefId,
349 param_env: ty::ParamEnv<'tcx>,
350 assumed_wf_tys: impl IntoIterator<Item = Ty<'tcx>>,
351 ) -> Result<(), ErrorGuaranteed> {
352 let errors = self.infcx.resolve_regions(body_def_id, param_env, assumed_wf_tys);
353 if errors.is_empty() {
354 Ok(())
355 } else {
356 Err(self.infcx.err_ctxt().report_region_errors(body_def_id, &errors))
357 }
358 }
359
360 #[must_use]
365 pub fn resolve_regions(
366 self,
367 body_def_id: LocalDefId,
368 param_env: ty::ParamEnv<'tcx>,
369 assumed_wf_tys: impl IntoIterator<Item = Ty<'tcx>>,
370 ) -> Vec<RegionResolutionError<'tcx>> {
371 self.infcx.resolve_regions(body_def_id, param_env, assumed_wf_tys)
372 }
373}
374
375impl<'tcx> ObligationCtxt<'_, 'tcx, FulfillmentError<'tcx>> {
376 pub fn assumed_wf_types_and_report_errors(
377 &self,
378 param_env: ty::ParamEnv<'tcx>,
379 def_id: LocalDefId,
380 ) -> Result<FxIndexSet<Ty<'tcx>>, ErrorGuaranteed> {
381 self.assumed_wf_types(param_env, def_id)
382 .map_err(|errors| self.infcx.err_ctxt().report_fulfillment_errors(errors))
383 }
384}
385
386impl<'tcx> ObligationCtxt<'_, 'tcx, ScrubbedTraitError<'tcx>> {
387 pub fn make_canonicalized_query_response<T>(
388 &self,
389 inference_vars: CanonicalVarValues<'tcx>,
390 answer: T,
391 ) -> Result<CanonicalQueryResponse<'tcx, T>, NoSolution>
392 where
393 T: Debug + TypeFoldable<TyCtxt<'tcx>>,
394 Canonical<'tcx, QueryResponse<'tcx, T>>: ArenaAllocatable<'tcx>,
395 {
396 self.infcx.make_canonicalized_query_response(
397 inference_vars,
398 answer,
399 &mut *self.engine.borrow_mut(),
400 )
401 }
402}
403
404impl<'tcx, E> ObligationCtxt<'_, 'tcx, E>
405where
406 E: FromSolverError<'tcx, NextSolverError<'tcx>> + FromSolverError<'tcx, OldSolverError<'tcx>>,
407{
408 pub fn assumed_wf_types(
409 &self,
410 param_env: ty::ParamEnv<'tcx>,
411 def_id: LocalDefId,
412 ) -> Result<FxIndexSet<Ty<'tcx>>, ThinVec<E>> {
413 let tcx = self.infcx.tcx;
414 let mut implied_bounds = FxIndexSet::default();
415 let mut errors = ThinVec::new();
416 for &(ty, span) in tcx.assumed_wf_types(def_id) {
417 let cause = ObligationCause::misc(span, def_id);
430 match self
431 .infcx
432 .at(&cause, param_env)
433 .deeply_normalize(Unnormalized::new_wip(ty), &mut *self.engine.borrow_mut())
434 {
435 Ok(normalized) => drop(implied_bounds.insert(normalized)),
437 Err(normalization_errors) => errors.extend(normalization_errors),
438 };
439 }
440
441 if errors.is_empty() { Ok(implied_bounds) } else { Err(errors) }
442 }
443
444 pub fn deeply_normalize<T: TypeFoldable<TyCtxt<'tcx>>>(
445 &self,
446 cause: &ObligationCause<'tcx>,
447 param_env: ty::ParamEnv<'tcx>,
448 value: Unnormalized<'tcx, T>,
449 ) -> Result<T, ThinVec<E>> {
450 self.infcx.at(cause, param_env).deeply_normalize(value, &mut *self.engine.borrow_mut())
451 }
452
453 pub fn structurally_normalize_ty(
454 &self,
455 cause: &ObligationCause<'tcx>,
456 param_env: ty::ParamEnv<'tcx>,
457 value: Unnormalized<'tcx, Ty<'tcx>>,
458 ) -> Result<Ty<'tcx>, ThinVec<E>> {
459 self.infcx
460 .at(cause, param_env)
461 .structurally_normalize_ty(value, &mut *self.engine.borrow_mut())
462 }
463
464 pub fn structurally_normalize_const(
465 &self,
466 cause: &ObligationCause<'tcx>,
467 param_env: ty::ParamEnv<'tcx>,
468 value: Unnormalized<'tcx, ty::Const<'tcx>>,
469 ) -> Result<ty::Const<'tcx>, ThinVec<E>> {
470 self.infcx
471 .at(cause, param_env)
472 .structurally_normalize_const(value, &mut *self.engine.borrow_mut())
473 }
474
475 pub fn structurally_normalize_term(
476 &self,
477 cause: &ObligationCause<'tcx>,
478 param_env: ty::ParamEnv<'tcx>,
479 value: Unnormalized<'tcx, ty::Term<'tcx>>,
480 ) -> Result<ty::Term<'tcx>, ThinVec<E>> {
481 self.infcx
482 .at(cause, param_env)
483 .structurally_normalize_term(value, &mut *self.engine.borrow_mut())
484 }
485}