1use crate::normalize_deep::DeepNormalizer;
2use crate::slg::ResolventOps;
3use crate::{ExClause, Literal, TimeStamp};
4use chalk_ir::cast::Caster;
5use chalk_ir::fold::shift::Shift;
6use chalk_ir::fold::TypeFoldable;
7use chalk_ir::interner::{HasInterner, Interner};
8use chalk_ir::zip::{Zip, Zipper};
9use chalk_ir::*;
10use chalk_solve::infer::InferenceTable;
11use tracing::{debug, instrument};
12
13impl<I: Interner> ResolventOps<I> for InferenceTable<I> {
50 #[instrument(level = "debug", skip(self, interner, environment, subst))]
59 fn resolvent_clause(
60 &mut self,
61 db: &dyn UnificationDatabase<I>,
62 interner: I,
63 environment: &Environment<I>,
64 goal: &DomainGoal<I>,
65 subst: &Substitution<I>,
66 clause: &ProgramClause<I>,
67 ) -> Fallible<ExClause<I>> {
68 let ProgramClauseImplication {
78 consequence,
79 conditions,
80 constraints,
81 priority: _,
82 } = {
83 let ProgramClauseData(implication) = clause.data(interner);
84
85 self.instantiate_binders_existentially(interner, implication.clone())
86 };
87 debug!(?consequence, ?conditions, ?constraints);
88
89 let unification_result = self.relate(
91 interner,
92 db,
93 environment,
94 Variance::Invariant,
95 goal,
96 &consequence,
97 )?;
98
99 let mut ex_clause = ExClause {
101 subst: subst.clone(),
102 ambiguous: false,
103 constraints: vec![],
104 subgoals: vec![],
105 delayed_subgoals: vec![],
106 answer_time: TimeStamp::default(),
107 floundered_subgoals: vec![],
108 };
109
110 ex_clause.subgoals.extend(
112 unification_result
113 .goals
114 .into_iter()
115 .casted(interner)
116 .map(Literal::Positive),
117 );
118
119 ex_clause
120 .constraints
121 .extend(constraints.as_slice(interner).to_owned());
122
123 ex_clause
125 .subgoals
126 .extend(conditions.iter(interner).map(|c| match c.data(interner) {
127 GoalData::Not(c1) => {
128 Literal::Negative(InEnvironment::new(environment, Goal::clone(c1)))
129 }
130 _ => Literal::Positive(InEnvironment::new(environment, Goal::clone(c))),
131 }));
132
133 Ok(ex_clause)
134 }
135
136 #[instrument(level = "debug", skip(self, interner))]
215 fn apply_answer_subst(
216 &mut self,
217 interner: I,
218 unification_database: &dyn UnificationDatabase<I>,
219 ex_clause: &mut ExClause<I>,
220 selected_goal: &InEnvironment<Goal<I>>,
221 answer_table_goal: &Canonical<InEnvironment<Goal<I>>>,
222 canonical_answer_subst: Canonical<AnswerSubst<I>>,
223 ) -> Fallible<()> {
224 debug!(selected_goal = ?DeepNormalizer::normalize_deep(self, interner, selected_goal.clone()));
225
226 let AnswerSubst {
228 subst: answer_subst,
229
230 constraints: answer_constraints,
236
237 delayed_subgoals,
238 } = self.instantiate_canonical(interner, canonical_answer_subst);
239
240 AnswerSubstitutor::substitute(
241 interner,
242 unification_database,
243 self,
244 &selected_goal.environment,
245 &answer_subst,
246 ex_clause,
247 &answer_table_goal.value,
248 selected_goal,
249 )?;
250 ex_clause
251 .constraints
252 .extend(answer_constraints.as_slice(interner).to_vec());
253 ex_clause.delayed_subgoals.extend(delayed_subgoals);
256 Ok(())
257 }
258}
259
260struct AnswerSubstitutor<'t, I: Interner> {
261 table: &'t mut InferenceTable<I>,
262 environment: &'t Environment<I>,
263 answer_subst: &'t Substitution<I>,
264
265 outer_binder: DebruijnIndex,
277
278 ex_clause: &'t mut ExClause<I>,
279 interner: I,
280 unification_database: &'t dyn UnificationDatabase<I>,
281}
282
283impl<I: Interner> AnswerSubstitutor<'_, I> {
284 fn substitute<T: Zip<I>>(
285 interner: I,
286 unification_database: &dyn UnificationDatabase<I>,
287 table: &mut InferenceTable<I>,
288 environment: &Environment<I>,
289 answer_subst: &Substitution<I>,
290 ex_clause: &mut ExClause<I>,
291 answer: &T,
292 pending: &T,
293 ) -> Fallible<()> {
294 let mut this = AnswerSubstitutor {
295 interner,
296 unification_database,
297 table,
298 environment,
299 answer_subst,
300 ex_clause,
301 outer_binder: DebruijnIndex::INNERMOST,
302 };
303 Zip::zip_with(&mut this, Variance::Invariant, answer, pending)?;
304 Ok(())
305 }
306
307 fn unify_free_answer_var(
308 &mut self,
309 interner: I,
310 db: &dyn UnificationDatabase<I>,
311 variance: Variance,
312 answer_var: BoundVar,
313 pending: GenericArgData<I>,
314 ) -> Fallible<bool> {
315 let answer_index = match answer_var.index_if_bound_at(self.outer_binder) {
316 Some(index) => index,
317
318 None => return Ok(false),
321 };
322
323 let answer_param = self.answer_subst.at(interner, answer_index);
324
325 let pending_shifted = pending
326 .shifted_out_to(interner, self.outer_binder)
327 .expect("truncate extracted a pending value that references internal binder");
328
329 let result = self.table.relate(
330 interner,
331 db,
332 self.environment,
333 variance,
334 answer_param,
335 &GenericArg::new(interner, pending_shifted),
336 )?;
337
338 self.ex_clause.subgoals.extend(
339 result
340 .goals
341 .into_iter()
342 .casted(interner)
343 .map(Literal::Positive),
344 );
345
346 Ok(true)
347 }
348
349 fn assert_matching_vars(
356 &mut self,
357 answer_var: BoundVar,
358 pending_var: BoundVar,
359 ) -> Fallible<()> {
360 let BoundVar {
361 debruijn: answer_depth,
362 index: answer_index,
363 } = answer_var;
364 let BoundVar {
365 debruijn: pending_depth,
366 index: pending_index,
367 } = pending_var;
368
369 assert!(answer_depth.within(self.outer_binder));
371
372 assert_eq!(answer_depth, pending_depth);
374
375 assert_eq!(answer_index, pending_index,);
377
378 Ok(())
379 }
380}
381
382impl<'i, I: Interner> Zipper<I> for AnswerSubstitutor<'i, I> {
383 fn zip_tys(&mut self, variance: Variance, answer: &Ty<I>, pending: &Ty<I>) -> Fallible<()> {
384 let interner = self.interner;
385
386 if let Some(pending) = self.table.normalize_ty_shallow(interner, pending) {
387 return Zip::zip_with(self, variance, answer, &pending);
388 }
389
390 if let TyKind::BoundVar(answer_depth) = answer.kind(interner) {
395 if self.unify_free_answer_var(
396 interner,
397 self.unification_database,
398 variance,
399 *answer_depth,
400 GenericArgData::Ty(pending.clone()),
401 )? {
402 return Ok(());
403 }
404 }
405
406 match (answer.kind(interner), pending.kind(interner)) {
409 (TyKind::BoundVar(answer_depth), TyKind::BoundVar(pending_depth)) => {
410 self.assert_matching_vars(*answer_depth, *pending_depth)
411 }
412
413 (TyKind::Dyn(answer), TyKind::Dyn(pending)) => {
414 Zip::zip_with(self, variance, answer, pending)
415 }
416
417 (TyKind::Alias(answer), TyKind::Alias(pending)) => {
418 Zip::zip_with(self, variance, answer, pending)
419 }
420
421 (TyKind::Placeholder(answer), TyKind::Placeholder(pending)) => {
422 Zip::zip_with(self, variance, answer, pending)
423 }
424
425 (TyKind::Function(answer), TyKind::Function(pending)) => Zip::zip_with(
426 self,
427 variance,
428 &answer.clone().into_binders(interner),
429 &pending.clone().into_binders(interner),
430 ),
431
432 (TyKind::InferenceVar(_, _), _) | (_, TyKind::InferenceVar(_, _)) => panic!(
433 "unexpected inference var in answer `{:?}` or pending goal `{:?}`",
434 answer, pending,
435 ),
436
437 (TyKind::Adt(id_a, substitution_a), TyKind::Adt(id_b, substitution_b)) => {
438 if id_a != id_b {
439 return Err(NoSolution);
440 }
441 self.zip_substs(
442 variance,
443 Some(self.unification_database().adt_variance(*id_a)),
444 substitution_a.as_slice(interner),
445 substitution_b.as_slice(interner),
446 )
447 }
448 (
449 TyKind::AssociatedType(id_a, substitution_a),
450 TyKind::AssociatedType(id_b, substitution_b),
451 ) => {
452 if id_a != id_b {
453 return Err(NoSolution);
454 }
455 self.zip_substs(
456 variance,
457 None,
458 substitution_a.as_slice(interner),
459 substitution_b.as_slice(interner),
460 )
461 }
462 (TyKind::Scalar(scalar_a), TyKind::Scalar(scalar_b)) => {
463 Zip::zip_with(self, variance, scalar_a, scalar_b)
464 }
465 (TyKind::Str, TyKind::Str) => Ok(()),
466 (TyKind::Tuple(arity_a, substitution_a), TyKind::Tuple(arity_b, substitution_b)) => {
467 if arity_a != arity_b {
468 return Err(NoSolution);
469 }
470 self.zip_substs(
471 variance,
472 None,
473 substitution_a.as_slice(interner),
474 substitution_b.as_slice(interner),
475 )
476 }
477 (
478 TyKind::OpaqueType(id_a, substitution_a),
479 TyKind::OpaqueType(id_b, substitution_b),
480 ) => {
481 if id_a != id_b {
482 return Err(NoSolution);
483 }
484 self.zip_substs(
485 variance,
486 None,
487 substitution_a.as_slice(interner),
488 substitution_b.as_slice(interner),
489 )
490 }
491 (TyKind::Slice(ty_a), TyKind::Slice(ty_b)) => Zip::zip_with(self, variance, ty_a, ty_b),
492 (TyKind::FnDef(id_a, substitution_a), TyKind::FnDef(id_b, substitution_b)) => {
493 if id_a != id_b {
494 return Err(NoSolution);
495 }
496 self.zip_substs(
497 variance,
498 Some(self.unification_database().fn_def_variance(*id_a)),
499 substitution_a.as_slice(interner),
500 substitution_b.as_slice(interner),
501 )
502 }
503 (
504 TyKind::Ref(mutability_a, lifetime_a, ty_a),
505 TyKind::Ref(mutability_b, lifetime_b, ty_b),
506 ) => {
507 if mutability_a != mutability_b {
508 return Err(NoSolution);
509 }
510 Zip::zip_with(
512 self,
513 variance.xform(Variance::Contravariant),
514 lifetime_a,
515 lifetime_b,
516 )?;
517 let output_variance = match mutability_a {
519 Mutability::Not => Variance::Covariant,
520 Mutability::Mut => Variance::Invariant,
521 };
522 Zip::zip_with(self, variance.xform(output_variance), ty_a, ty_b)
523 }
524 (TyKind::Raw(mutability_a, ty_a), TyKind::Raw(mutability_b, ty_b)) => {
525 if mutability_a != mutability_b {
526 return Err(NoSolution);
527 }
528 let ty_variance = match mutability_a {
529 Mutability::Not => Variance::Covariant,
530 Mutability::Mut => Variance::Invariant,
531 };
532 Zip::zip_with(self, variance.xform(ty_variance), ty_a, ty_b)
533 }
534 (TyKind::Never, TyKind::Never) => Ok(()),
535 (TyKind::Array(ty_a, const_a), TyKind::Array(ty_b, const_b)) => {
536 Zip::zip_with(self, variance, ty_a, ty_b)?;
537 Zip::zip_with(self, variance, const_a, const_b)
538 }
539 (TyKind::Closure(id_a, substitution_a), TyKind::Closure(id_b, substitution_b)) => {
540 if id_a != id_b {
541 return Err(NoSolution);
542 }
543 self.zip_substs(
544 variance,
545 None,
546 substitution_a.as_slice(interner),
547 substitution_b.as_slice(interner),
548 )
549 }
550 (TyKind::Coroutine(id_a, substitution_a), TyKind::Coroutine(id_b, substitution_b)) => {
551 if id_a != id_b {
552 return Err(NoSolution);
553 }
554 self.zip_substs(
555 variance,
556 None,
557 substitution_a.as_slice(interner),
558 substitution_b.as_slice(interner),
559 )
560 }
561 (
562 TyKind::CoroutineWitness(id_a, substitution_a),
563 TyKind::CoroutineWitness(id_b, substitution_b),
564 ) => {
565 if id_a != id_b {
566 return Err(NoSolution);
567 }
568 self.zip_substs(
569 variance,
570 None,
571 substitution_a.as_slice(interner),
572 substitution_b.as_slice(interner),
573 )
574 }
575 (TyKind::Foreign(id_a), TyKind::Foreign(id_b)) => {
576 Zip::zip_with(self, variance, id_a, id_b)
577 }
578 (TyKind::Error, TyKind::Error) => Ok(()),
579
580 (_, _) => panic!(
581 "structural mismatch between answer `{:?}` and pending goal `{:?}`",
582 answer, pending,
583 ),
584 }
585 }
586
587 fn zip_lifetimes(
588 &mut self,
589 variance: Variance,
590 answer: &Lifetime<I>,
591 pending: &Lifetime<I>,
592 ) -> Fallible<()> {
593 let interner = self.interner;
594 if let Some(pending) = self.table.normalize_lifetime_shallow(interner, pending) {
595 return Zip::zip_with(self, variance, answer, &pending);
596 }
597
598 if let LifetimeData::BoundVar(answer_depth) = answer.data(interner) {
599 if self.unify_free_answer_var(
600 interner,
601 self.unification_database,
602 variance,
603 *answer_depth,
604 GenericArgData::Lifetime(pending.clone()),
605 )? {
606 return Ok(());
607 }
608 }
609
610 match (answer.data(interner), pending.data(interner)) {
611 (LifetimeData::BoundVar(answer_depth), LifetimeData::BoundVar(pending_depth)) => {
612 self.assert_matching_vars(*answer_depth, *pending_depth)
613 }
614
615 (LifetimeData::Static, LifetimeData::Static)
616 | (LifetimeData::Placeholder(_), LifetimeData::Placeholder(_))
617 | (LifetimeData::Erased, LifetimeData::Erased) => {
618 assert_eq!(answer, pending);
619 Ok(())
620 }
621
622 (LifetimeData::InferenceVar(_), _) | (_, LifetimeData::InferenceVar(_)) => panic!(
623 "unexpected inference var in answer `{:?}` or pending goal `{:?}`",
624 answer, pending,
625 ),
626
627 (LifetimeData::Static, _)
628 | (LifetimeData::BoundVar(_), _)
629 | (LifetimeData::Placeholder(_), _)
630 | (LifetimeData::Erased, _)
631 | (LifetimeData::Error, _) => panic!(
632 "structural mismatch between answer `{:?}` and pending goal `{:?}`",
633 answer, pending,
634 ),
635
636 (LifetimeData::Phantom(void, _), _) => match *void {},
637 }
638 }
639
640 fn zip_consts(
641 &mut self,
642 variance: Variance,
643 answer: &Const<I>,
644 pending: &Const<I>,
645 ) -> Fallible<()> {
646 let interner = self.interner;
647 if let Some(pending) = self.table.normalize_const_shallow(interner, pending) {
648 return Zip::zip_with(self, variance, answer, &pending);
649 }
650
651 let ConstData {
652 ty: answer_ty,
653 value: answer_value,
654 } = answer.data(interner);
655 let ConstData {
656 ty: pending_ty,
657 value: pending_value,
658 } = pending.data(interner);
659
660 self.zip_tys(variance, answer_ty, pending_ty)?;
661
662 if let ConstValue::BoundVar(answer_depth) = answer_value {
663 if self.unify_free_answer_var(
664 interner,
665 self.unification_database,
666 variance,
667 *answer_depth,
668 GenericArgData::Const(pending.clone()),
669 )? {
670 return Ok(());
671 }
672 }
673
674 match (answer_value, pending_value) {
675 (ConstValue::BoundVar(answer_depth), ConstValue::BoundVar(pending_depth)) => {
676 self.assert_matching_vars(*answer_depth, *pending_depth)
677 }
678
679 (ConstValue::Placeholder(_), ConstValue::Placeholder(_)) => {
680 assert_eq!(answer, pending);
681 Ok(())
682 }
683
684 (ConstValue::Concrete(c1), ConstValue::Concrete(c2)) => {
685 assert!(c1.const_eq(answer_ty, c2, interner));
686 Ok(())
687 }
688
689 (ConstValue::InferenceVar(_), _) | (_, ConstValue::InferenceVar(_)) => panic!(
690 "unexpected inference var in answer `{:?}` or pending goal `{:?}`",
691 answer, pending,
692 ),
693
694 (ConstValue::BoundVar(_), _)
695 | (ConstValue::Placeholder(_), _)
696 | (ConstValue::Concrete(_), _) => panic!(
697 "structural mismatch between answer `{:?}` and pending goal `{:?}`",
698 answer, pending,
699 ),
700 }
701 }
702
703 fn zip_binders<T>(
704 &mut self,
705 variance: Variance,
706 answer: &Binders<T>,
707 pending: &Binders<T>,
708 ) -> Fallible<()>
709 where
710 T: HasInterner<Interner = I> + Zip<I> + TypeFoldable<I>,
711 {
712 self.outer_binder.shift_in();
713 Zip::zip_with(
714 self,
715 variance,
716 answer.skip_binders(),
717 pending.skip_binders(),
718 )?;
719 self.outer_binder.shift_out();
720 Ok(())
721 }
722
723 fn interner(&self) -> I {
724 self.interner
725 }
726
727 fn unification_database(&self) -> &dyn UnificationDatabase<I> {
728 self.unification_database
729 }
730}