1use std::ops::ControlFlow;
2
3use derive_where::derive_where;
4#[cfg(feature = "nightly")]
5use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable};
6use rustc_type_ir::data_structures::{HashMap, HashSet, ensure_sufficient_stack};
7use rustc_type_ir::fast_reject::DeepRejectCtxt;
8use rustc_type_ir::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
9use rustc_type_ir::inherent::*;
10use rustc_type_ir::relate::Relate;
11use rustc_type_ir::relate::solver_relating::RelateExt;
12use rustc_type_ir::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor};
13use rustc_type_ir::{self as ty, CanonicalVarValues, InferCtxtLike, Interner, TypingMode};
14use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic};
15use tracing::{instrument, trace};
16
17use crate::coherence;
18use crate::delegate::SolverDelegate;
19use crate::solve::inspect::{self, ProofTreeBuilder};
20use crate::solve::search_graph::SearchGraph;
21use crate::solve::{
22 CanonicalInput, Certainty, FIXPOINT_STEP_LIMIT, Goal, GoalEvaluationKind, GoalSource,
23 HasChanged, NestedNormalizationGoals, NoSolution, PredefinedOpaquesData, QueryResult,
24};
25
26pub(super) mod canonical;
27mod probe;
28
29pub struct EvalCtxt<'a, D, I = <D as SolverDelegate>::Interner>
30where
31 D: SolverDelegate<Interner = I>,
32 I: Interner,
33{
34 delegate: &'a D,
50
51 variables: I::CanonicalVars,
54 is_normalizes_to_goal: bool,
62 pub(super) var_values: CanonicalVarValues<I>,
63
64 predefined_opaques_in_body: I::PredefinedOpaques,
65
66 pub(super) max_input_universe: ty::UniverseIndex,
76
77 pub(super) search_graph: &'a mut SearchGraph<D>,
78
79 nested_goals: NestedGoals<I>,
80
81 pub(super) origin_span: I::Span,
82
83 tainted: Result<(), NoSolution>,
90
91 pub(super) inspect: ProofTreeBuilder<D>,
92}
93
94#[derive_where(Clone, Debug, Default; I: Interner)]
95#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
96#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
97struct NestedGoals<I: Interner> {
98 pub normalizes_to_goals: Vec<Goal<I, ty::NormalizesTo<I>>>,
109 pub goals: Vec<(GoalSource, Goal<I, I::Predicate>)>,
111}
112
113impl<I: Interner> NestedGoals<I> {
114 fn new() -> Self {
115 Self { normalizes_to_goals: Vec::new(), goals: Vec::new() }
116 }
117
118 fn is_empty(&self) -> bool {
119 self.normalizes_to_goals.is_empty() && self.goals.is_empty()
120 }
121}
122
123#[derive(PartialEq, Eq, Debug, Hash, Clone, Copy)]
124#[cfg_attr(feature = "nightly", derive(HashStable_NoContext))]
125pub enum GenerateProofTree {
126 Yes,
127 No,
128}
129
130pub trait SolverDelegateEvalExt: SolverDelegate {
131 fn evaluate_root_goal(
136 &self,
137 goal: Goal<Self::Interner, <Self::Interner as Interner>::Predicate>,
138 generate_proof_tree: GenerateProofTree,
139 span: <Self::Interner as Interner>::Span,
140 ) -> (
141 Result<(HasChanged, Certainty), NoSolution>,
142 Option<inspect::GoalEvaluation<Self::Interner>>,
143 );
144
145 fn root_goal_may_hold_with_depth(
153 &self,
154 root_depth: usize,
155 goal: Goal<Self::Interner, <Self::Interner as Interner>::Predicate>,
156 ) -> bool;
157
158 fn evaluate_root_goal_raw(
161 &self,
162 goal: Goal<Self::Interner, <Self::Interner as Interner>::Predicate>,
163 generate_proof_tree: GenerateProofTree,
164 ) -> (
165 Result<(NestedNormalizationGoals<Self::Interner>, HasChanged, Certainty), NoSolution>,
166 Option<inspect::GoalEvaluation<Self::Interner>>,
167 );
168}
169
170impl<D, I> SolverDelegateEvalExt for D
171where
172 D: SolverDelegate<Interner = I>,
173 I: Interner,
174{
175 #[instrument(level = "debug", skip(self))]
176 fn evaluate_root_goal(
177 &self,
178 goal: Goal<I, I::Predicate>,
179 generate_proof_tree: GenerateProofTree,
180 span: I::Span,
181 ) -> (Result<(HasChanged, Certainty), NoSolution>, Option<inspect::GoalEvaluation<I>>) {
182 EvalCtxt::enter_root(self, self.cx().recursion_limit(), generate_proof_tree, span, |ecx| {
183 ecx.evaluate_goal(GoalEvaluationKind::Root, GoalSource::Misc, goal)
184 })
185 }
186
187 fn root_goal_may_hold_with_depth(
188 &self,
189 root_depth: usize,
190 goal: Goal<Self::Interner, <Self::Interner as Interner>::Predicate>,
191 ) -> bool {
192 self.probe(|| {
193 EvalCtxt::enter_root(self, root_depth, GenerateProofTree::No, I::Span::dummy(), |ecx| {
194 ecx.evaluate_goal(GoalEvaluationKind::Root, GoalSource::Misc, goal)
195 })
196 .0
197 })
198 .is_ok()
199 }
200
201 #[instrument(level = "debug", skip(self))]
202 fn evaluate_root_goal_raw(
203 &self,
204 goal: Goal<I, I::Predicate>,
205 generate_proof_tree: GenerateProofTree,
206 ) -> (
207 Result<(NestedNormalizationGoals<I>, HasChanged, Certainty), NoSolution>,
208 Option<inspect::GoalEvaluation<I>>,
209 ) {
210 EvalCtxt::enter_root(
211 self,
212 self.cx().recursion_limit(),
213 generate_proof_tree,
214 I::Span::dummy(),
215 |ecx| ecx.evaluate_goal_raw(GoalEvaluationKind::Root, GoalSource::Misc, goal),
216 )
217 }
218}
219
220impl<'a, D, I> EvalCtxt<'a, D>
221where
222 D: SolverDelegate<Interner = I>,
223 I: Interner,
224{
225 pub(super) fn typing_mode(&self) -> TypingMode<I> {
226 self.delegate.typing_mode()
227 }
228
229 pub(super) fn set_is_normalizes_to_goal(&mut self) {
230 self.is_normalizes_to_goal = true;
231 }
232
233 pub(super) fn enter_root<R>(
237 delegate: &D,
238 root_depth: usize,
239 generate_proof_tree: GenerateProofTree,
240 origin_span: I::Span,
241 f: impl FnOnce(&mut EvalCtxt<'_, D>) -> R,
242 ) -> (R, Option<inspect::GoalEvaluation<I>>) {
243 let mut search_graph = SearchGraph::new(root_depth);
244
245 let mut ecx = EvalCtxt {
246 delegate,
247 search_graph: &mut search_graph,
248 nested_goals: NestedGoals::new(),
249 inspect: ProofTreeBuilder::new_maybe_root(generate_proof_tree),
250
251 predefined_opaques_in_body: delegate
254 .cx()
255 .mk_predefined_opaques_in_body(PredefinedOpaquesData::default()),
256 max_input_universe: ty::UniverseIndex::ROOT,
257 variables: Default::default(),
258 var_values: CanonicalVarValues::dummy(),
259 is_normalizes_to_goal: false,
260 origin_span,
261 tainted: Ok(()),
262 };
263 let result = f(&mut ecx);
264
265 let proof_tree = ecx.inspect.finalize();
266 assert!(
267 ecx.nested_goals.is_empty(),
268 "root `EvalCtxt` should not have any goals added to it"
269 );
270
271 assert!(search_graph.is_empty());
272 (result, proof_tree)
273 }
274
275 fn enter_canonical<R>(
284 cx: I,
285 search_graph: &'a mut SearchGraph<D>,
286 canonical_input: CanonicalInput<I>,
287 canonical_goal_evaluation: &mut ProofTreeBuilder<D>,
288 f: impl FnOnce(&mut EvalCtxt<'_, D>, Goal<I, I::Predicate>) -> R,
289 ) -> R {
290 let (ref delegate, input, var_values) =
291 SolverDelegate::build_with_canonical(cx, &canonical_input);
292
293 let mut ecx = EvalCtxt {
294 delegate,
295 variables: canonical_input.canonical.variables,
296 var_values,
297 is_normalizes_to_goal: false,
298 predefined_opaques_in_body: input.predefined_opaques_in_body,
299 max_input_universe: canonical_input.canonical.max_universe,
300 search_graph,
301 nested_goals: NestedGoals::new(),
302 origin_span: I::Span::dummy(),
303 tainted: Ok(()),
304 inspect: canonical_goal_evaluation.new_goal_evaluation_step(var_values),
305 };
306
307 for &(key, ty) in &input.predefined_opaques_in_body.opaque_types {
308 ecx.delegate.inject_new_hidden_type_unchecked(key, ty, ecx.origin_span);
309 }
310
311 if !ecx.nested_goals.is_empty() {
312 panic!("prepopulating opaque types shouldn't add goals: {:?}", ecx.nested_goals);
313 }
314
315 let result = f(&mut ecx, input.goal);
316 ecx.inspect.probe_final_state(ecx.delegate, ecx.max_input_universe);
317 canonical_goal_evaluation.goal_evaluation_step(ecx.inspect);
318
319 delegate.reset_opaque_types();
325
326 result
327 }
328
329 #[instrument(level = "debug", skip(cx, search_graph, goal_evaluation), ret)]
339 fn evaluate_canonical_goal(
340 cx: I,
341 search_graph: &'a mut SearchGraph<D>,
342 canonical_input: CanonicalInput<I>,
343 goal_evaluation: &mut ProofTreeBuilder<D>,
344 ) -> QueryResult<I> {
345 let mut canonical_goal_evaluation =
346 goal_evaluation.new_canonical_goal_evaluation(canonical_input);
347
348 let result = ensure_sufficient_stack(|| {
352 search_graph.with_new_goal(
353 cx,
354 canonical_input,
355 &mut canonical_goal_evaluation,
356 |search_graph, canonical_goal_evaluation| {
357 EvalCtxt::enter_canonical(
358 cx,
359 search_graph,
360 canonical_input,
361 canonical_goal_evaluation,
362 |ecx, goal| {
363 let result = ecx.compute_goal(goal);
364 ecx.inspect.query_result(result);
365 result
366 },
367 )
368 },
369 )
370 });
371
372 canonical_goal_evaluation.query_result(result);
373 goal_evaluation.canonical_goal_evaluation(canonical_goal_evaluation);
374 result
375 }
376
377 fn evaluate_goal(
380 &mut self,
381 goal_evaluation_kind: GoalEvaluationKind,
382 source: GoalSource,
383 goal: Goal<I, I::Predicate>,
384 ) -> Result<(HasChanged, Certainty), NoSolution> {
385 let (normalization_nested_goals, has_changed, certainty) =
386 self.evaluate_goal_raw(goal_evaluation_kind, source, goal)?;
387 assert!(normalization_nested_goals.is_empty());
388 Ok((has_changed, certainty))
389 }
390
391 pub(super) fn evaluate_goal_raw(
401 &mut self,
402 goal_evaluation_kind: GoalEvaluationKind,
403 _source: GoalSource,
404 goal: Goal<I, I::Predicate>,
405 ) -> Result<(NestedNormalizationGoals<I>, HasChanged, Certainty), NoSolution> {
406 let (orig_values, canonical_goal) = self.canonicalize_goal(goal);
407 let mut goal_evaluation =
408 self.inspect.new_goal_evaluation(goal, &orig_values, goal_evaluation_kind);
409 let canonical_response = EvalCtxt::evaluate_canonical_goal(
410 self.cx(),
411 self.search_graph,
412 canonical_goal,
413 &mut goal_evaluation,
414 );
415 let response = match canonical_response {
416 Err(e) => {
417 self.inspect.goal_evaluation(goal_evaluation);
418 return Err(e);
419 }
420 Ok(response) => response,
421 };
422
423 let has_changed = if !response.value.var_values.is_identity_modulo_regions()
424 || !response.value.external_constraints.opaque_types.is_empty()
425 {
426 HasChanged::Yes
427 } else {
428 HasChanged::No
429 };
430
431 let (normalization_nested_goals, certainty) =
432 self.instantiate_and_apply_query_response(goal.param_env, orig_values, response);
433 self.inspect.goal_evaluation(goal_evaluation);
434
435 Ok((normalization_nested_goals, has_changed, certainty))
446 }
447
448 fn compute_goal(&mut self, goal: Goal<I, I::Predicate>) -> QueryResult<I> {
449 let Goal { param_env, predicate } = goal;
450 let kind = predicate.kind();
451 if let Some(kind) = kind.no_bound_vars() {
452 match kind {
453 ty::PredicateKind::Clause(ty::ClauseKind::Trait(predicate)) => {
454 self.compute_trait_goal(Goal { param_env, predicate }).map(|(r, _via)| r)
455 }
456 ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(predicate)) => {
457 self.compute_host_effect_goal(Goal { param_env, predicate })
458 }
459 ty::PredicateKind::Clause(ty::ClauseKind::Projection(predicate)) => {
460 self.compute_projection_goal(Goal { param_env, predicate })
461 }
462 ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(predicate)) => {
463 self.compute_type_outlives_goal(Goal { param_env, predicate })
464 }
465 ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(predicate)) => {
466 self.compute_region_outlives_goal(Goal { param_env, predicate })
467 }
468 ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => {
469 self.compute_const_arg_has_type_goal(Goal { param_env, predicate: (ct, ty) })
470 }
471 ty::PredicateKind::Subtype(predicate) => {
472 self.compute_subtype_goal(Goal { param_env, predicate })
473 }
474 ty::PredicateKind::Coerce(predicate) => {
475 self.compute_coerce_goal(Goal { param_env, predicate })
476 }
477 ty::PredicateKind::DynCompatible(trait_def_id) => {
478 self.compute_dyn_compatible_goal(trait_def_id)
479 }
480 ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => {
481 self.compute_well_formed_goal(Goal { param_env, predicate: arg })
482 }
483 ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(ct)) => {
484 self.compute_const_evaluatable_goal(Goal { param_env, predicate: ct })
485 }
486 ty::PredicateKind::ConstEquate(_, _) => {
487 panic!("ConstEquate should not be emitted when `-Znext-solver` is active")
488 }
489 ty::PredicateKind::NormalizesTo(predicate) => {
490 self.compute_normalizes_to_goal(Goal { param_env, predicate })
491 }
492 ty::PredicateKind::AliasRelate(lhs, rhs, direction) => self
493 .compute_alias_relate_goal(Goal {
494 param_env,
495 predicate: (lhs, rhs, direction),
496 }),
497 ty::PredicateKind::Ambiguous => {
498 self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
499 }
500 }
501 } else {
502 self.enter_forall(kind, |ecx, kind| {
503 let goal = goal.with(ecx.cx(), ty::Binder::dummy(kind));
504 ecx.add_goal(GoalSource::InstantiateHigherRanked, goal);
505 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
506 })
507 }
508 }
509
510 #[instrument(level = "trace", skip(self))]
513 pub(super) fn try_evaluate_added_goals(&mut self) -> Result<Certainty, NoSolution> {
514 let mut response = Ok(Certainty::overflow(false));
515 for _ in 0..FIXPOINT_STEP_LIMIT {
516 match self.evaluate_added_goals_step() {
519 Ok(Some(cert)) => {
520 response = Ok(cert);
521 break;
522 }
523 Ok(None) => {}
524 Err(NoSolution) => {
525 response = Err(NoSolution);
526 break;
527 }
528 }
529 }
530
531 if response.is_err() {
532 self.tainted = Err(NoSolution);
533 }
534
535 response
536 }
537
538 fn evaluate_added_goals_step(&mut self) -> Result<Option<Certainty>, NoSolution> {
542 let cx = self.cx();
543 let mut goals = core::mem::take(&mut self.nested_goals);
544
545 let mut unchanged_certainty = Some(Certainty::Yes);
547 for goal in goals.normalizes_to_goals {
548 let unconstrained_rhs = self.next_term_infer_of_kind(goal.predicate.term);
551 let unconstrained_goal = goal.with(
552 cx,
553 ty::NormalizesTo { alias: goal.predicate.alias, term: unconstrained_rhs },
554 );
555
556 let (NestedNormalizationGoals(nested_goals), _, certainty) = self.evaluate_goal_raw(
557 GoalEvaluationKind::Nested,
558 GoalSource::Misc,
559 unconstrained_goal,
560 )?;
561 trace!(?nested_goals);
563 goals.goals.extend(nested_goals);
564
565 self.eq_structurally_relating_aliases(
580 goal.param_env,
581 goal.predicate.term,
582 unconstrained_rhs,
583 )?;
584
585 let with_resolved_vars = self.resolve_vars_if_possible(goal);
590 if goal.predicate.alias != with_resolved_vars.predicate.alias {
591 unchanged_certainty = None;
592 }
593
594 match certainty {
595 Certainty::Yes => {}
596 Certainty::Maybe(_) => {
597 self.nested_goals.normalizes_to_goals.push(with_resolved_vars);
598 unchanged_certainty = unchanged_certainty.map(|c| c.unify_with(certainty));
599 }
600 }
601 }
602
603 for (source, goal) in goals.goals {
604 let (has_changed, certainty) =
605 self.evaluate_goal(GoalEvaluationKind::Nested, source, goal)?;
606 if has_changed == HasChanged::Yes {
607 unchanged_certainty = None;
608 }
609
610 match certainty {
611 Certainty::Yes => {}
612 Certainty::Maybe(_) => {
613 self.nested_goals.goals.push((source, goal));
614 unchanged_certainty = unchanged_certainty.map(|c| c.unify_with(certainty));
615 }
616 }
617 }
618
619 Ok(unchanged_certainty)
620 }
621
622 pub(crate) fn record_impl_args(&mut self, impl_args: I::GenericArgs) {
624 self.inspect.record_impl_args(self.delegate, self.max_input_universe, impl_args)
625 }
626
627 pub(super) fn cx(&self) -> I {
628 self.delegate.cx()
629 }
630
631 #[instrument(level = "trace", skip(self))]
632 pub(super) fn add_normalizes_to_goal(&mut self, mut goal: Goal<I, ty::NormalizesTo<I>>) {
633 goal.predicate =
634 goal.predicate.fold_with(&mut ReplaceAliasWithInfer::new(self, goal.param_env));
635 self.inspect.add_normalizes_to_goal(self.delegate, self.max_input_universe, goal);
636 self.nested_goals.normalizes_to_goals.push(goal);
637 }
638
639 #[instrument(level = "debug", skip(self))]
640 pub(super) fn add_goal(&mut self, source: GoalSource, mut goal: Goal<I, I::Predicate>) {
641 goal.predicate =
642 goal.predicate.fold_with(&mut ReplaceAliasWithInfer::new(self, goal.param_env));
643 self.inspect.add_goal(self.delegate, self.max_input_universe, source, goal);
644 self.nested_goals.goals.push((source, goal));
645 }
646
647 #[instrument(level = "trace", skip(self, goals))]
648 pub(super) fn add_goals(
649 &mut self,
650 source: GoalSource,
651 goals: impl IntoIterator<Item = Goal<I, I::Predicate>>,
652 ) {
653 for goal in goals {
654 self.add_goal(source, goal);
655 }
656 }
657
658 pub(super) fn next_region_var(&mut self) -> I::Region {
659 let region = self.delegate.next_region_infer();
660 self.inspect.add_var_value(region);
661 region
662 }
663
664 pub(super) fn next_ty_infer(&mut self) -> I::Ty {
665 let ty = self.delegate.next_ty_infer();
666 self.inspect.add_var_value(ty);
667 ty
668 }
669
670 pub(super) fn next_const_infer(&mut self) -> I::Const {
671 let ct = self.delegate.next_const_infer();
672 self.inspect.add_var_value(ct);
673 ct
674 }
675
676 pub(super) fn next_term_infer_of_kind(&mut self, kind: I::Term) -> I::Term {
679 match kind.kind() {
680 ty::TermKind::Ty(_) => self.next_ty_infer().into(),
681 ty::TermKind::Const(_) => self.next_const_infer().into(),
682 }
683 }
684
685 #[instrument(level = "trace", skip(self), ret)]
690 pub(super) fn term_is_fully_unconstrained(&self, goal: Goal<I, ty::NormalizesTo<I>>) -> bool {
691 let universe_of_term = match goal.predicate.term.kind() {
692 ty::TermKind::Ty(ty) => {
693 if let ty::Infer(ty::TyVar(vid)) = ty.kind() {
694 self.delegate.universe_of_ty(vid).unwrap()
695 } else {
696 return false;
697 }
698 }
699 ty::TermKind::Const(ct) => {
700 if let ty::ConstKind::Infer(ty::InferConst::Var(vid)) = ct.kind() {
701 self.delegate.universe_of_ct(vid).unwrap()
702 } else {
703 return false;
704 }
705 }
706 };
707
708 struct ContainsTermOrNotNameable<'a, D: SolverDelegate<Interner = I>, I: Interner> {
709 term: I::Term,
710 universe_of_term: ty::UniverseIndex,
711 delegate: &'a D,
712 cache: HashSet<I::Ty>,
713 }
714
715 impl<D: SolverDelegate<Interner = I>, I: Interner> ContainsTermOrNotNameable<'_, D, I> {
716 fn check_nameable(&self, universe: ty::UniverseIndex) -> ControlFlow<()> {
717 if self.universe_of_term.can_name(universe) {
718 ControlFlow::Continue(())
719 } else {
720 ControlFlow::Break(())
721 }
722 }
723 }
724
725 impl<D: SolverDelegate<Interner = I>, I: Interner> TypeVisitor<I>
726 for ContainsTermOrNotNameable<'_, D, I>
727 {
728 type Result = ControlFlow<()>;
729 fn visit_ty(&mut self, t: I::Ty) -> Self::Result {
730 if self.cache.contains(&t) {
731 return ControlFlow::Continue(());
732 }
733
734 match t.kind() {
735 ty::Infer(ty::TyVar(vid)) => {
736 if let ty::TermKind::Ty(term) = self.term.kind() {
737 if let ty::Infer(ty::TyVar(term_vid)) = term.kind() {
738 if self.delegate.root_ty_var(vid)
739 == self.delegate.root_ty_var(term_vid)
740 {
741 return ControlFlow::Break(());
742 }
743 }
744 }
745
746 self.check_nameable(self.delegate.universe_of_ty(vid).unwrap())?;
747 }
748 ty::Placeholder(p) => self.check_nameable(p.universe())?,
749 _ => {
750 if t.has_non_region_infer() || t.has_placeholders() {
751 t.super_visit_with(self)?
752 }
753 }
754 }
755
756 assert!(self.cache.insert(t));
757 ControlFlow::Continue(())
758 }
759
760 fn visit_const(&mut self, c: I::Const) -> Self::Result {
761 match c.kind() {
762 ty::ConstKind::Infer(ty::InferConst::Var(vid)) => {
763 if let ty::TermKind::Const(term) = self.term.kind() {
764 if let ty::ConstKind::Infer(ty::InferConst::Var(term_vid)) = term.kind()
765 {
766 if self.delegate.root_const_var(vid)
767 == self.delegate.root_const_var(term_vid)
768 {
769 return ControlFlow::Break(());
770 }
771 }
772 }
773
774 self.check_nameable(self.delegate.universe_of_ct(vid).unwrap())
775 }
776 ty::ConstKind::Placeholder(p) => self.check_nameable(p.universe()),
777 _ => {
778 if c.has_non_region_infer() || c.has_placeholders() {
779 c.super_visit_with(self)
780 } else {
781 ControlFlow::Continue(())
782 }
783 }
784 }
785 }
786 }
787
788 let mut visitor = ContainsTermOrNotNameable {
789 delegate: self.delegate,
790 universe_of_term,
791 term: goal.predicate.term,
792 cache: Default::default(),
793 };
794 goal.predicate.alias.visit_with(&mut visitor).is_continue()
795 && goal.param_env.visit_with(&mut visitor).is_continue()
796 }
797
798 #[instrument(level = "trace", skip(self, param_env), ret)]
799 pub(super) fn eq<T: Relate<I>>(
800 &mut self,
801 param_env: I::ParamEnv,
802 lhs: T,
803 rhs: T,
804 ) -> Result<(), NoSolution> {
805 self.relate(param_env, lhs, ty::Variance::Invariant, rhs)
806 }
807
808 #[instrument(level = "trace", skip(self, param_env), ret)]
814 pub(super) fn relate_rigid_alias_non_alias(
815 &mut self,
816 param_env: I::ParamEnv,
817 alias: ty::AliasTerm<I>,
818 variance: ty::Variance,
819 term: I::Term,
820 ) -> Result<(), NoSolution> {
821 if term.is_infer() {
824 let cx = self.cx();
825 let identity_args = self.fresh_args_for_item(alias.def_id);
834 let rigid_ctor = ty::AliasTerm::new_from_args(cx, alias.def_id, identity_args);
835 let ctor_term = rigid_ctor.to_term(cx);
836 let obligations = self.delegate.eq_structurally_relating_aliases(
837 param_env,
838 term,
839 ctor_term,
840 self.origin_span,
841 )?;
842 debug_assert!(obligations.is_empty());
843 self.relate(param_env, alias, variance, rigid_ctor)
844 } else {
845 Err(NoSolution)
846 }
847 }
848
849 #[instrument(level = "trace", skip(self, param_env), ret)]
853 pub(super) fn eq_structurally_relating_aliases<T: Relate<I>>(
854 &mut self,
855 param_env: I::ParamEnv,
856 lhs: T,
857 rhs: T,
858 ) -> Result<(), NoSolution> {
859 let result = self.delegate.eq_structurally_relating_aliases(
860 param_env,
861 lhs,
862 rhs,
863 self.origin_span,
864 )?;
865 assert_eq!(result, vec![]);
866 Ok(())
867 }
868
869 #[instrument(level = "trace", skip(self, param_env), ret)]
870 pub(super) fn sub<T: Relate<I>>(
871 &mut self,
872 param_env: I::ParamEnv,
873 sub: T,
874 sup: T,
875 ) -> Result<(), NoSolution> {
876 self.relate(param_env, sub, ty::Variance::Covariant, sup)
877 }
878
879 #[instrument(level = "trace", skip(self, param_env), ret)]
880 pub(super) fn relate<T: Relate<I>>(
881 &mut self,
882 param_env: I::ParamEnv,
883 lhs: T,
884 variance: ty::Variance,
885 rhs: T,
886 ) -> Result<(), NoSolution> {
887 let goals = self.delegate.relate(param_env, lhs, variance, rhs, self.origin_span)?;
888 self.add_goals(GoalSource::Misc, goals);
889 Ok(())
890 }
891
892 #[instrument(level = "trace", skip(self, param_env), ret)]
898 pub(super) fn eq_and_get_goals<T: Relate<I>>(
899 &self,
900 param_env: I::ParamEnv,
901 lhs: T,
902 rhs: T,
903 ) -> Result<Vec<Goal<I, I::Predicate>>, NoSolution> {
904 Ok(self.delegate.relate(param_env, lhs, ty::Variance::Invariant, rhs, self.origin_span)?)
905 }
906
907 pub(super) fn instantiate_binder_with_infer<T: TypeFoldable<I> + Copy>(
908 &self,
909 value: ty::Binder<I, T>,
910 ) -> T {
911 self.delegate.instantiate_binder_with_infer(value)
912 }
913
914 pub(super) fn enter_forall<T: TypeFoldable<I> + Copy, U>(
917 &mut self,
918 value: ty::Binder<I, T>,
919 f: impl FnOnce(&mut Self, T) -> U,
920 ) -> U {
921 self.delegate.enter_forall(value, |value| f(self, value))
922 }
923
924 pub(super) fn resolve_vars_if_possible<T>(&self, value: T) -> T
925 where
926 T: TypeFoldable<I>,
927 {
928 self.delegate.resolve_vars_if_possible(value)
929 }
930
931 pub(super) fn fresh_args_for_item(&mut self, def_id: I::DefId) -> I::GenericArgs {
932 let args = self.delegate.fresh_args_for_item(def_id);
933 for arg in args.iter() {
934 self.inspect.add_var_value(arg);
935 }
936 args
937 }
938
939 pub(super) fn register_ty_outlives(&self, ty: I::Ty, lt: I::Region) {
940 self.delegate.register_ty_outlives(ty, lt, self.origin_span);
941 }
942
943 pub(super) fn register_region_outlives(&self, a: I::Region, b: I::Region) {
944 self.delegate.sub_regions(b, a, self.origin_span);
946 }
947
948 pub(super) fn well_formed_goals(
950 &self,
951 param_env: I::ParamEnv,
952 arg: I::GenericArg,
953 ) -> Option<Vec<Goal<I, I::Predicate>>> {
954 self.delegate.well_formed_goals(param_env, arg)
955 }
956
957 pub(super) fn trait_ref_is_knowable(
958 &mut self,
959 param_env: I::ParamEnv,
960 trait_ref: ty::TraitRef<I>,
961 ) -> Result<bool, NoSolution> {
962 let delegate = self.delegate;
963 let lazily_normalize_ty = |ty| self.structurally_normalize_ty(param_env, ty);
964 coherence::trait_ref_is_knowable(&**delegate, trait_ref, lazily_normalize_ty)
965 .map(|is_knowable| is_knowable.is_ok())
966 }
967
968 pub(super) fn fetch_eligible_assoc_item(
969 &self,
970 goal_trait_ref: ty::TraitRef<I>,
971 trait_assoc_def_id: I::DefId,
972 impl_def_id: I::DefId,
973 ) -> Result<Option<I::DefId>, I::ErrorGuaranteed> {
974 self.delegate.fetch_eligible_assoc_item(goal_trait_ref, trait_assoc_def_id, impl_def_id)
975 }
976
977 pub(super) fn insert_hidden_type(
978 &mut self,
979 opaque_type_key: ty::OpaqueTypeKey<I>,
980 param_env: I::ParamEnv,
981 hidden_ty: I::Ty,
982 ) -> Result<(), NoSolution> {
983 let mut goals = Vec::new();
984 self.delegate.insert_hidden_type(opaque_type_key, param_env, hidden_ty, &mut goals)?;
985 self.add_goals(GoalSource::Misc, goals);
986 Ok(())
987 }
988
989 pub(super) fn add_item_bounds_for_hidden_type(
990 &mut self,
991 opaque_def_id: I::DefId,
992 opaque_args: I::GenericArgs,
993 param_env: I::ParamEnv,
994 hidden_ty: I::Ty,
995 ) {
996 let mut goals = Vec::new();
997 self.delegate.add_item_bounds_for_hidden_type(
998 opaque_def_id,
999 opaque_args,
1000 param_env,
1001 hidden_ty,
1002 &mut goals,
1003 );
1004 self.add_goals(GoalSource::AliasWellFormed, goals);
1005 }
1006
1007 pub(super) fn probe_existing_opaque_ty(
1010 &mut self,
1011 key: ty::OpaqueTypeKey<I>,
1012 ) -> Option<(ty::OpaqueTypeKey<I>, I::Ty)> {
1013 let mut matching =
1014 self.delegate.clone_opaque_types_for_query_response().into_iter().filter(
1015 |(candidate_key, _)| {
1016 candidate_key.def_id == key.def_id
1017 && DeepRejectCtxt::relate_rigid_rigid(self.cx())
1018 .args_may_unify(candidate_key.args, key.args)
1019 },
1020 );
1021 let first = matching.next();
1022 let second = matching.next();
1023 assert_eq!(second, None);
1024 first
1025 }
1026
1027 pub(super) fn evaluate_const(
1031 &self,
1032 param_env: I::ParamEnv,
1033 uv: ty::UnevaluatedConst<I>,
1034 ) -> Option<I::Const> {
1035 self.delegate.evaluate_const(param_env, uv)
1036 }
1037
1038 pub(super) fn is_transmutable(
1039 &mut self,
1040 param_env: I::ParamEnv,
1041 dst: I::Ty,
1042 src: I::Ty,
1043 assume: I::Const,
1044 ) -> Result<Certainty, NoSolution> {
1045 self.delegate.is_transmutable(param_env, dst, src, assume)
1046 }
1047}
1048
1049struct ReplaceAliasWithInfer<'me, 'a, D, I>
1057where
1058 D: SolverDelegate<Interner = I>,
1059 I: Interner,
1060{
1061 ecx: &'me mut EvalCtxt<'a, D>,
1062 param_env: I::ParamEnv,
1063 cache: HashMap<I::Ty, I::Ty>,
1064}
1065
1066impl<'me, 'a, D, I> ReplaceAliasWithInfer<'me, 'a, D, I>
1067where
1068 D: SolverDelegate<Interner = I>,
1069 I: Interner,
1070{
1071 fn new(ecx: &'me mut EvalCtxt<'a, D>, param_env: I::ParamEnv) -> Self {
1072 ReplaceAliasWithInfer { ecx, param_env, cache: Default::default() }
1073 }
1074}
1075
1076impl<D, I> TypeFolder<I> for ReplaceAliasWithInfer<'_, '_, D, I>
1077where
1078 D: SolverDelegate<Interner = I>,
1079 I: Interner,
1080{
1081 fn cx(&self) -> I {
1082 self.ecx.cx()
1083 }
1084
1085 fn fold_ty(&mut self, ty: I::Ty) -> I::Ty {
1086 match ty.kind() {
1087 ty::Alias(..) if !ty.has_escaping_bound_vars() => {
1088 let infer_ty = self.ecx.next_ty_infer();
1089 let normalizes_to = ty::PredicateKind::AliasRelate(
1090 ty.into(),
1091 infer_ty.into(),
1092 ty::AliasRelationDirection::Equate,
1093 );
1094 self.ecx.add_goal(
1095 GoalSource::Misc,
1096 Goal::new(self.cx(), self.param_env, normalizes_to),
1097 );
1098 infer_ty
1099 }
1100 _ => {
1101 if !ty.has_aliases() {
1102 ty
1103 } else if let Some(&entry) = self.cache.get(&ty) {
1104 return entry;
1105 } else {
1106 let res = ty.super_fold_with(self);
1107 assert!(self.cache.insert(ty, res).is_none());
1108 res
1109 }
1110 }
1111 }
1112 }
1113
1114 fn fold_const(&mut self, ct: I::Const) -> I::Const {
1115 match ct.kind() {
1116 ty::ConstKind::Unevaluated(..) if !ct.has_escaping_bound_vars() => {
1117 let infer_ct = self.ecx.next_const_infer();
1118 let normalizes_to = ty::PredicateKind::AliasRelate(
1119 ct.into(),
1120 infer_ct.into(),
1121 ty::AliasRelationDirection::Equate,
1122 );
1123 self.ecx.add_goal(
1124 GoalSource::Misc,
1125 Goal::new(self.cx(), self.param_env, normalizes_to),
1126 );
1127 infer_ct
1128 }
1129 _ => ct.super_fold_with(self),
1130 }
1131 }
1132
1133 fn fold_predicate(&mut self, predicate: I::Predicate) -> I::Predicate {
1134 if predicate.allow_normalization() { predicate.super_fold_with(self) } else { predicate }
1135 }
1136}