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 .at(cause, param_env)
287 .sup(DefineOpaqueTypes::Yes, expected, actual)
288 .map(|infer_ok| self.register_infer_ok_obligations(infer_ok))
289 }
290
291 pub fn lub<T: ToTrace<'tcx>>(
293 &self,
294 cause: &ObligationCause<'tcx>,
295 param_env: ty::ParamEnv<'tcx>,
296 expected: T,
297 actual: T,
298 ) -> Result<T, TypeError<'tcx>> {
299 self.infcx
300 .at(cause, param_env)
301 .lub(expected, actual)
302 .map(|infer_ok| self.register_infer_ok_obligations(infer_ok))
303 }
304
305 #[must_use]
314 pub fn try_evaluate_obligations(&self) -> TraitErrors<E> {
315 self.engine.borrow_mut().try_evaluate_obligations(self.infcx)
316 }
317
318 #[must_use]
327 pub fn evaluate_obligations_error_on_ambiguity(&self) -> TraitErrors<E> {
328 self.engine.borrow_mut().evaluate_obligations_error_on_ambiguity(self.infcx)
329 }
330
331 #[must_use]
339 pub fn into_pending_obligations(self) -> PredicateObligations<'tcx> {
340 self.engine.borrow().pending_obligations()
341 }
342
343 pub fn resolve_regions_and_report_errors(
348 self,
349 body_def_id: LocalDefId,
350 param_env: ty::ParamEnv<'tcx>,
351 assumed_wf_tys: impl IntoIterator<Item = Ty<'tcx>>,
352 ) -> Result<(), ErrorGuaranteed> {
353 let errors = self.infcx.resolve_regions(body_def_id, param_env, assumed_wf_tys);
354 if errors.is_empty() {
355 Ok(())
356 } else {
357 Err(self.infcx.err_ctxt().report_region_errors(body_def_id, &errors))
358 }
359 }
360
361 #[must_use]
366 pub fn resolve_regions(
367 self,
368 body_def_id: LocalDefId,
369 param_env: ty::ParamEnv<'tcx>,
370 assumed_wf_tys: impl IntoIterator<Item = Ty<'tcx>>,
371 ) -> Vec<RegionResolutionError<'tcx>> {
372 self.infcx.resolve_regions(body_def_id, param_env, assumed_wf_tys)
373 }
374}
375
376impl<'tcx> ObligationCtxt<'_, 'tcx, FulfillmentError<'tcx>> {
377 pub fn assumed_wf_types_and_report_errors(
378 &self,
379 param_env: ty::ParamEnv<'tcx>,
380 def_id: LocalDefId,
381 ) -> Result<FxIndexSet<Ty<'tcx>>, ErrorGuaranteed> {
382 self.assumed_wf_types(param_env, def_id)
383 .map_err(|errors| self.infcx.err_ctxt().report_fulfillment_errors(errors))
384 }
385}
386
387impl<'tcx> ObligationCtxt<'_, 'tcx, ScrubbedTraitError<'tcx>> {
388 pub fn make_canonicalized_query_response<T>(
389 &self,
390 inference_vars: CanonicalVarValues<'tcx>,
391 answer: T,
392 ) -> Result<CanonicalQueryResponse<'tcx, T>, NoSolution>
393 where
394 T: Debug + TypeFoldable<TyCtxt<'tcx>>,
395 Canonical<'tcx, QueryResponse<'tcx, T>>: ArenaAllocatable<'tcx>,
396 {
397 self.infcx.make_canonicalized_query_response(
398 inference_vars,
399 answer,
400 &mut *self.engine.borrow_mut(),
401 )
402 }
403}
404
405impl<'tcx, E> ObligationCtxt<'_, 'tcx, E>
406where
407 E: FromSolverError<'tcx, NextSolverError<'tcx>> + FromSolverError<'tcx, OldSolverError<'tcx>>,
408{
409 pub fn assumed_wf_types(
410 &self,
411 param_env: ty::ParamEnv<'tcx>,
412 def_id: LocalDefId,
413 ) -> Result<FxIndexSet<Ty<'tcx>>, ThinVec<E>> {
414 let tcx = self.infcx.tcx;
415 let mut implied_bounds = FxIndexSet::default();
416 let mut errors = ThinVec::new();
417 for &(ty, span) in tcx.assumed_wf_types(def_id) {
418 let cause = ObligationCause::misc(span, def_id);
431 match self
432 .infcx
433 .at(&cause, param_env)
434 .deeply_normalize(Unnormalized::new_wip(ty), &mut *self.engine.borrow_mut())
435 {
436 Ok(normalized) => drop(implied_bounds.insert(normalized)),
438 Err(normalization_errors) => errors.extend(normalization_errors),
439 };
440 }
441
442 if errors.is_empty() { Ok(implied_bounds) } else { Err(errors) }
443 }
444
445 pub fn deeply_normalize<T: TypeFoldable<TyCtxt<'tcx>>>(
446 &self,
447 cause: &ObligationCause<'tcx>,
448 param_env: ty::ParamEnv<'tcx>,
449 value: Unnormalized<'tcx, T>,
450 ) -> Result<T, ThinVec<E>> {
451 self.infcx.at(cause, param_env).deeply_normalize(value, &mut *self.engine.borrow_mut())
452 }
453
454 pub fn structurally_normalize_ty(
455 &self,
456 cause: &ObligationCause<'tcx>,
457 param_env: ty::ParamEnv<'tcx>,
458 value: Unnormalized<'tcx, Ty<'tcx>>,
459 ) -> Result<Ty<'tcx>, ThinVec<E>> {
460 self.infcx
461 .at(cause, param_env)
462 .structurally_normalize_ty(value, &mut *self.engine.borrow_mut())
463 }
464
465 pub fn structurally_normalize_const(
466 &self,
467 cause: &ObligationCause<'tcx>,
468 param_env: ty::ParamEnv<'tcx>,
469 value: Unnormalized<'tcx, ty::Const<'tcx>>,
470 ) -> Result<ty::Const<'tcx>, ThinVec<E>> {
471 self.infcx
472 .at(cause, param_env)
473 .structurally_normalize_const(value, &mut *self.engine.borrow_mut())
474 }
475
476 pub fn structurally_normalize_term(
477 &self,
478 cause: &ObligationCause<'tcx>,
479 param_env: ty::ParamEnv<'tcx>,
480 value: Unnormalized<'tcx, ty::Term<'tcx>>,
481 ) -> Result<ty::Term<'tcx>, ThinVec<E>> {
482 self.infcx
483 .at(cause, param_env)
484 .structurally_normalize_term(value, &mut *self.engine.borrow_mut())
485 }
486}