1use std::borrow::Cow;
2
3use ftml_ontology::terms::{
4 ApplicationTerm, Argument, BindingTerm, BoundArgument, ComponentVar, MaybeSequence, Term,
5};
6use ftml_solver_trace::{CheckerRule, CheckingTask, traceref};
7use ftml_uris::Id;
8
9use crate::{
10 CheckRef,
11 impls::solving::{TermExtSolvable, is_solvable_var},
12 rules::{
13 implicits::{ImplicitExtApp, ImplicitExtBound},
14 unknowns::beta_unknowns_cow,
15 },
16 split::SplitStrategy,
17};
18
19const LOOP_LIMIT: usize = 64;
20const RECURSION_LIMIT: usize = 128;
21const TOTAL_LIMIT: usize = 4096 * 512;
22
23static NOEXPAND: std::sync::LazyLock<Id> =
24 std::sync::LazyLock::new(|| unsafe { "noexpand".parse().unwrap_unchecked() });
25
26#[derive(Debug, Copy, Clone, PartialEq, Eq)]
27#[allow(clippy::enum_variant_names)]
28pub enum Expansion {
29 Full,
30 NoDefinitionExpansion,
31 NoNoexpands,
32}
33impl Expansion {
34 fn with_defs(self) -> Self {
35 if self == Self::NoNoexpands {
36 Self::NoNoexpands
37 } else {
38 Self::Full
39 }
40 }
41}
42
43impl<'t, Split: SplitStrategy> CheckRef<'t, '_, Split> {
44 pub fn simplify_full(&mut self, expand: Expansion, term: &'t Term) -> Option<Term> {
45 if matches!(term, Term::Symbol { .. } | Term::Number(_)) {
46 return None;
47 }
48 self.untraced(CheckingTask::Simplify(term), |slf| {
49 slf.simplify_full_i(expand, term,&mut 0,&mut 0)
50 }).inspect(|t| {
51 self.add_msg(traceref!("Simplified: ",t.clone()).into());
52 })
53 }
54 fn simplify_full_first(
55 &mut self,
56 expand: Expansion,
57 term: &'t Term,
58 recursion_limit: &mut usize,
59 total_limit: &mut usize,
60 ) -> Option<Cow<'t, Term>> {
61 match term {
62 Term::Symbol { uri, .. } if expand == Expansion::NoNoexpands => {
63 let s = self.get_symbol(uri).ok()?;
64 if s.data.role.contains(&NOEXPAND) {
65 None
66 } else {
67 self.get_symbol_definiens(uri).map(|t| {
68 self.comment("expanded definition");
69 Some(Cow::Owned(t))
70 })?
71 }
72 }
73 Term::Symbol { uri, .. } => {
74 self.get_symbol_definiens(uri).map(|t| {
75 self.comment("expanded definition");
76 Some(Cow::Owned(t))
77 })?
78 }
79 Term::Var { variable, .. } => {
80 if let Some(name) = is_solvable_var(variable)
81 && let Some(t) = self.get_solution(name)
82 {
83 Some(Cow::Owned(t))
84 } else if
85 let Some(df) = self.get_var_definiens(variable) {
88 Some(Cow::Owned(df))
89 } else {
90 None
92 }
93 }
94 Term::Number(_) => {
95 None
97 }
98 Term::Application(app) => {
99 let mut changed = false;
100 let nhead = self
101 .simplify_full_i(expand, &app.head, recursion_limit, total_limit)
102 .map_or(Cow::Borrowed(&app.head), |t| {
103 changed = true;
104 Cow::Owned(t)
105 });
106 let args = app
107 .arguments
108 .iter()
109 .map(|a| {
110 self.arg_full(expand, a, recursion_limit, total_limit)
111 .map_or(Cow::Borrowed(a), |a| {
112 changed = true;
113 Cow::Owned(a)
114 })
115 })
116 .collect::<Vec<_>>();
117 Some(if changed {
118 Cow::Owned(Term::Application(ApplicationTerm::new(
119 nhead.into_owned(),
120 args.into_iter().map(Cow::into_owned).collect(),
121 app.presentation.clone(),
122 )))
123 } else {
124 Cow::Borrowed(term)
125 })
126 }
127 Term::Bound(app) => {
128 let mut changed = false;
129 let nhead = self
130 .simplify_full_i(expand.with_defs(), &app.head, recursion_limit, total_limit)
131 .map_or(Cow::Borrowed(&app.head), |t| {
132 changed = true;
133 Cow::Owned(t)
134 });
135 let args = app
136 .arguments
137 .iter()
138 .map(|a| {
139 self.bound_arg_full(expand, a, recursion_limit, total_limit)
140 .map_or(Cow::Borrowed(a), |a| {
141 changed = true;
142 Cow::Owned(a)
143 })
144 })
145 .collect::<Vec<_>>();
146 Some(if changed {
147 Cow::Owned(Term::Bound(BindingTerm::new(
148 nhead.into_owned(),
149 args.into_iter().map(Cow::into_owned).collect(),
150 app.presentation.clone(),
151 )))
152 } else {
153 Cow::Borrowed(term)
154 })
155 }
156 _ => Some(Cow::Borrowed(term)),
157 }
158 }
159 fn simplify_full_i(
160 &mut self,
161 expand: Expansion,
162 term: &'t Term,
163 recursion_limit: &mut usize,
164 total_limit: &mut usize,
165 ) -> Option<Term> {
166 if expand == Expansion::Full
167 && let Some(r) = self
168 .judgment_cache
169 .get_simplification(term, self.context.as_ref())
170 {
171 return Some(r);
172 }
173 tracing::debug!(
174 "Fully Simplifying {:?} (expand:{expand:?})",
175 term.debug_short()
176 );
177 if
178 true {
181 match self.simplify_implicit(term) {
182 Ok(Some(t)) => {
183 let r = self
184 .scoped(|slf| slf.simplify_full_i(expand, &t, recursion_limit, total_limit))
185 .unwrap_or(t);
186 return Some(r);
187 }
188 Ok(None) => (),
189 Err(()) => return None,
190 }
191 }
192 *recursion_limit += 1;
197 let Some(mut current) =
198 self.simplify_full_first(expand, term, recursion_limit, total_limit)
199 else {
200 *recursion_limit -= 1;
201 return None;
202 };
203 let mut loop_limit = 0;
204 loop {
205 loop_limit += 1;
206 *total_limit += 1;
207 if loop_limit >= LOOP_LIMIT
208 || *recursion_limit >= RECURSION_LIMIT
209 || *total_limit >= TOTAL_LIMIT
210 {
211 *recursion_limit -= 1;
212 return match current {
213 Cow::Borrowed(_) => {
214 None
216 }
217 Cow::Owned(t) => {
218 if expand == Expansion::Full {
228 self.judgment_cache
229 .add_simplification(term, &t, self.context.as_ref());
230 }
231 Some(t)
233 }
234 };
235 }
236 if let Some(next) = self.scoped(|slf| slf.simplify_one(expand, ¤t)) {
237 current = Cow::Owned(next);
238 } else {
239 return match current {
240 Cow::Borrowed(_) => {
241 *recursion_limit -= 1;
243 None
244 }
245 Cow::Owned(mut t) => {
246 while let Some(r) = self.scoped(|slf| {
247 slf.simplify_full_i(expand, &t, recursion_limit, total_limit)
248 }) {
249 t = r;
250 }
251 if expand == Expansion::Full {
254 self.judgment_cache
255 .add_simplification(term, &t, self.context.as_ref());
256 }
257 *recursion_limit -= 1;
258 Some(t)
259 }
260 };
261 }
262 }
263 }
265
266 pub fn simplify_until(
267 &mut self,
268 term: &'t Term,
269 mut until: impl FnMut(&Self, &Term) -> bool,
270 ) -> Option<Cow<'t, Term>> {
271 if until(self, term) {
272 return Some(Cow::Borrowed(term));
273 }
274 self.wrap_check(CheckingTask::Simplify(term), |slf| {
275 slf.simplify_until_i(term, until, &mut 0, &mut 0)
276 })
277 }
278 fn simplify_until_i(
279 &mut self,
280 term: &'t Term,
281 mut until: impl FnMut(&Self, &Term) -> bool,
282 recursion_limit: &mut usize,
283 total_limit: &mut usize,
284 ) -> Option<Cow<'t, Term>> {
285 if until(self, term) {
286 return Some(Cow::Borrowed(term));
287 }
288 let mut current = Cow::<'t, _>::Borrowed(term);
289 *recursion_limit += 1;
290 let mut loop_limit = 0;
291 loop {
292 loop_limit += 1;
293 *total_limit += 1;
294 if *recursion_limit >= RECURSION_LIMIT
295 || loop_limit >= LOOP_LIMIT
296 || *total_limit >= TOTAL_LIMIT
297 {
298 *recursion_limit -= 1;
299 return None;
300 }
301 let Some(next) = self.scoped(|slf| slf.simplify_one(Expansion::Full, ¤t)) else {
302 *recursion_limit -= 1;
303 return None;
305 };
306 if until(self, &next) {
307 *recursion_limit -= 1;
308 return Some(Cow::Owned(next));
309 }
310 current = Cow::Owned(next);
311 }
312 }
313
314 pub(crate) fn simplify_rules<Rl: CheckerRule + ?Sized, R>(
315 &mut self,
316 rules: &'t [Box<Rl>],
317 term: &'t Term,
318 applicable: impl Fn(&Rl, &Term) -> bool,
319 apply: impl for<'s> Fn(CheckRef<'s, '_, Split>, &Rl, &'s Term) -> Option<R> + Send + Sync,
320 ) -> Option<R>
321 where
322 R: Send + Sync + std::fmt::Debug + Clone + 'static,
323 {
324 let mut applicables = smallvec::SmallVec::<_, 2>::default();
325 match self.simplify_until(term, |_, t| {
326 applicables = rules
327 .iter()
328 .filter_map(|rl| {
329 if applicable(&**rl, t) {
330 Some(&**rl)
331 } else {
332 None
333 }
334 })
335 .collect();
336 !applicables.is_empty()
337 }) {
338 Some(Cow::Borrowed(term)) => {
339 if let Some(r) =
340 Split::split(self, true, applicables, |slf, rl| apply(slf, rl, term))
341 {
342 return Some(r);
343 }
344 self.simplify_one(Expansion::Full, term).and_then(|term| {
345 self.scoped(|slf| slf.simplify_rules(rules, &term, applicable, apply))
346 })
347 }
348 Some(Cow::Owned(term)) => self.scoped(|slf| {
349 if let Some(r) =
350 Split::split(slf, true, applicables, |slf, rl| apply(slf, rl, &term))
351 {
352 return Some(r);
353 }
354 slf.simplify_one(Expansion::Full, &term).and_then(|term| {
355 slf.scoped(|slf| slf.simplify_rules(rules, &term, applicable, apply))
356 })
357 }),
358 None => {
359 self.failure("No rule applicable (1)");
360 None
362 }
363 }
364 }
365
366 pub(crate) fn simplify_until_two(
367 &mut self,
368 term1: &'t Term,
369 term2: &'t Term,
370 mut until: impl FnMut(&Self, &Term, &Term) -> bool,
371 ) -> Option<(Cow<'t, Term>, Cow<'t, Term>)> {
372 let mut left = true;
373 let mut right = true;
374 let mut next_left = true;
375 let mut t1 = Cow::Borrowed(term1);
376 let mut t2 = Cow::Borrowed(term2);
377 loop {
378 if next_left && left {
379 if until(self, &t1, &t2) {
380 return Some((t1, t2));
381 }
382 if right {
383 next_left = false;
384 }
385 if let Some(next) = self.scoped(|slf| slf.simplify_one(Expansion::Full, &t1)) {
386 t1 = Cow::Owned(next);
387 continue;
388 }
389 left = false;
390 }
391 if right {
392 if until(self, &t1, &t2) {
393 return Some((t1, t2));
394 }
395 next_left = true;
396 if let Some(next) = self.scoped(|slf| slf.simplify_one(Expansion::Full, &t2)) {
397 t2 = Cow::Owned(next);
398 continue;
399 }
400 right = false;
401 continue;
402 }
403 break;
404 }
405 self.add_msg(
406 traceref!(FAIL
407 "Final simplifications: ",
408 t1.into_owned(),
409 " and ",
410 t2.into_owned()
411 )
412 .into(),
413 );
414 None
415 }
416
417 pub(crate) fn simplify_rules_two<Rl: CheckerRule + ?Sized + 'static, R>(
418 &mut self,
419 rules: &'t [Box<Rl>],
420 term1: &'t Term,
421 term2: &'t Term,
422 applicable: impl Fn(&CheckRef<'_, '_, Split>, &Rl, &Term, &Term) -> bool,
423 apply: impl for<'s> Fn(CheckRef<'s, '_, Split>, &Rl, &'s Term, &'s Term) -> Option<R> + Sync,
424 abort: impl Fn(&Term, &Term) -> bool + Send + Sync,
425 ) -> either::Either<Option<R>, (Term, Term)>
426 where
427 R: Send + Sync + std::fmt::Debug + Clone + 'static,
428 {
429 let mut applicables = smallvec::SmallVec::<_, 2>::default();
431 let mut left = true;
432 let mut right = true;
433 let mut next_left = true;
434 let mut t1 = Cow::Borrowed(term1);
435 let mut t2 = Cow::Borrowed(term2);
436 loop {
437 macro_rules! set {
438 () => {
439 set!(NOBREAK);
440 if !applicables.is_empty() {
441 break;
442 }
443 };
444 (NOBREAK) => {
445 if abort(&*t1, &*t2) {
446 return either::Right((t1.into_owned(), t2.into_owned()));
448 }
449 applicables = rules
450 .iter()
451 .filter_map(|rl| {
452 if applicable(self, &**rl, &*t1, &*t2) {
453 Some(&**rl)
454 } else {
455 None
456 }
457 })
458 .collect();
459 };
460 }
461 loop {
462 if next_left && left {
469 set!();
470 if right {
471 next_left = false;
472 }
473 if let Some(next) = self.scoped(|slf| slf.simplify_one(Expansion::Full, &t1)) {
474 t1 = Cow::Owned(next);
475 continue;
476 }
477 left = false;
478 }
479 if right {
480 set!();
481 if left {
482 next_left = true;
483 }
484 if let Some(next) = self.scoped(|slf| slf.simplify_one(Expansion::Full, &t2)) {
485 t2 = Cow::Owned(next);
486 continue;
487 }
488 right = false;
489 if left {
490 continue;
491 }
492 }
493 break;
494 }
495
496 if applicables.is_empty() {
497 self.failure("No rule applicable (2)");
498 self.add_msg(
499 traceref!(FAIL
500 "Final simplifications: ",
501 t1.into_owned(),
502 " and ",
503 t2.into_owned()
504 )
505 .into(),
506 );
507 return either::Left(None);
509 }
510 if let Some(r) = self.scoped(|slf| {
511 Split::split(slf, true, std::mem::take(&mut applicables), |slf, rl| {
512 apply(slf, rl, &t1, &t2)
513 })
514 }) {
515 return either::Left(Some(r));
517 }
518 if next_left && left {
519 if right {
520 next_left = false;
521 }
522 if let Some(next) = self.scoped(|slf| slf.simplify_one(Expansion::Full, &t1)) {
523 t1 = Cow::Owned(next);
524 continue;
526 }
527 left = false;
528 }
529 if right {
530 if left {
531 next_left = true;
532 }
533 if let Some(next) = self.scoped(|slf| slf.simplify_one(Expansion::Full, &t2)) {
534 t2 = Cow::Owned(next);
535 continue;
537 }
538 right = false;
539 if left {
540 continue;
541 }
542 }
543 break;
544 }
545 self.failure("No rule applicable (3)");
546 either::Left(None)
548 }
549
550 pub(super) fn simplify_one(&mut self, expand: Expansion, term: &'t Term) -> Option<Term> {
551 if term.has_solvable() {
552 let nterm = self.subst(term.clone());
553 if *term != nterm {
554 return Some(nterm); }
556 }
557 if let Cow::Owned(nterm) = beta_unknowns_cow(term)
558 && *term != nterm
559 {
560 return Some(nterm); }
562
563 if
571 true {
574 match self.simplify_implicit(term) {
575 Ok(Some(t)) => return Some(t),
576 Ok(None) => (),
577 Err(()) => return None,
578 }
579 }
580 self.simplify_one_i(expand, term)
581 }
582 fn simplify_one_i(&mut self, expand: Expansion, term: &'t Term) -> Option<Term> {
583 let applicables = self
585 .top
586 .rules
587 .simplification()
588 .iter()
589 .filter_map(|rl| {
590 if rl.applicable(term) {
591 Some(&**rl)
592 } else {
593 None
594 }
595 })
596 .collect::<smallvec::SmallVec<_, 2>>();
597 match Split::split(self, false, applicables, |slf, rl| {
598 match rl.apply(slf, term) {
599 Ok(t) => Some(either::Left(t)),
600 Err(Some(v)) => Some(either::Right(v)),
601 _ => None,
602 }
603 }) {
604 Some(either::Left(t)) => return Some(t),
605 Some(_) => {
606 }
608 None => (),
609 }
610
611 self.simplify_one_default(expand, term)
619 }
620
621 fn simplify_morph(&mut self, expand: Expansion, term: &'t Term) -> Option<Term> {
622 let (m, r) = crate::rules::MorphismRule::is_morphism_appl(term, self)?;
623 if matches!(r, Term::Symbol { .. })
639 && let Some(nt) = self.simplify_one_default(expand, r)
640 && let Ok(nt) = m.apply(&nt, &mut |s| {
641 self.top
642 .get_symbol_like(s, |t| self.prepare(t, None).1)
643 .ok()
644 })
645 && *nt != *term
646 {
647 Some(nt.into_owned())
648 } else if let Ok(Some(nt)) = self.simplify_implicit(r)
649 && let Ok(nt) = m.apply(&nt, &mut |s| {
650 self.top
651 .get_symbol_like(s, |t| self.prepare(t, None).1)
652 .ok()
653 })
654 && *nt != *term
655 {
656 Some(nt.into_owned())
657 } else {
658 None
659 }
660 }
661
662 fn simplify_one_default(&mut self, expand: Expansion, term: &'t Term) -> Option<Term> {
663 if
664 true {
667 match self.simplify_implicit(term) {
668 Ok(Some(t)) => return Some(t),
669 Ok(None) => (),
670 Err(()) => return None,
671 }
672 }
673 if let Some(t) = self.simplify_morph(expand, term) {
674 return Some(t);
675 }
676 match term {
677 Term::Symbol { uri, .. } if expand == Expansion::NoNoexpands => {
679 let s = self.get_symbol(uri).ok()?;
680 if s.data.role.contains(&NOEXPAND) {
681 None
682 } else {
683 self.get_symbol_definiens(uri).inspect(|_| {
684 self.comment("expanded definition");
685 })
686 }
687 }
688 Term::Symbol { uri, .. } => {
689 self.get_symbol_definiens(uri).inspect(|_| {
690 self.comment("expanded definition");
691 })
692 }
693 Term::Var { variable, .. }
694 if true|| is_solvable_var(variable).is_some() =>
696 {
697 self.get_var_definiens(variable).inspect(|_| {
698 self.comment("expanded definition");
699 })
700 }
701
702 Term::Application(app) if self.top.hoas().is_some_and(|h| h.judgment.as_ref().is_some_and(|j|
703 app.head.is(j)
704 )) && let [Argument::Simple(p)] = &*app.arguments => {
705 self.simplify_one(expand, p).map(|r| Term::Application(ApplicationTerm::new(
706 app.head.clone(),Box::new([Argument::Simple(r)]),app.presentation.clone()
707 )))
708 }
709
710 Term::Application(app) => self.simplify_one(expand, &app.head).map(|nh| {
711 Term::Application(ApplicationTerm::new(
712 nh,
713 app.arguments.clone(),
714 app.presentation.clone(),
715 ))
716 }),
717 Term::Bound(app) => self.simplify_one(expand.with_defs(), &app.head).map(|nh| {
718 Term::Bound(BindingTerm::new(
719 nh,
720 app.arguments.clone(),
721 app.presentation.clone(),
722 ))
723 }),
724 _ => None,
725 }
726 }
727
728 fn arg_full(
729 &mut self,
730 expand: Expansion,
731 arg: &'t Argument,
732 recursion_limit: &mut usize,
733 total_limit: &mut usize,
734 ) -> Option<Argument> {
735 match arg {
736 Argument::Simple(t) => self
737 .simplify_full_i(expand, t, recursion_limit, total_limit)
738 .map(Argument::Simple),
739 Argument::Sequence(MaybeSequence::One(t)) => self
740 .simplify_full_i(expand, t, recursion_limit, total_limit)
741 .map(|t| Argument::Sequence(MaybeSequence::One(t))),
742 Argument::Sequence(MaybeSequence::Seq(ts)) => {
743 let mut changed = false;
744 let nts = ts
745 .iter()
746 .map(|t| {
747 self.simplify_full_i(expand, t, recursion_limit, total_limit)
748 .map_or(Cow::Borrowed(t), |a| {
749 changed = true;
750 Cow::Owned(a)
751 })
752 })
753 .collect::<Vec<_>>();
754 if changed {
755 Some(Argument::Sequence(MaybeSequence::Seq(
756 nts.into_iter().map(Cow::into_owned).collect(),
757 )))
758 } else {
759 None
760 }
761 }
762 }
763 }
764 fn bound_arg_full(
765 &mut self,
766 expand: Expansion,
767 arg: &'t BoundArgument,
768 recusion_limit: &mut usize,
769 total_limit: &mut usize,
770 ) -> Option<BoundArgument> {
771 match arg {
772 BoundArgument::Simple(t) => self
773 .simplify_full_i(expand, t, recusion_limit, total_limit)
774 .map(BoundArgument::Simple),
775 BoundArgument::Bound(cv) => self
776 .cv_full(expand, cv, recusion_limit, total_limit)
777 .map(BoundArgument::Bound),
778 BoundArgument::Sequence(MaybeSequence::One(t)) => self
779 .simplify_full_i(expand, t, recusion_limit, total_limit)
780 .map(|t| BoundArgument::Sequence(MaybeSequence::One(t))),
781 BoundArgument::BoundSeq(MaybeSequence::One(cv)) => self
782 .cv_full(expand, cv, recusion_limit, total_limit)
783 .map(|t| BoundArgument::BoundSeq(MaybeSequence::One(t))),
784 BoundArgument::Sequence(MaybeSequence::Seq(ts)) => {
785 let mut changed = false;
786 let nts = ts
787 .iter()
788 .map(|t| {
789 self.simplify_full_i(expand, t, recusion_limit, total_limit)
790 .map_or(Cow::Borrowed(t), |a| {
791 changed = true;
792 Cow::Owned(a)
793 })
794 })
795 .collect::<Vec<_>>();
796 if changed {
797 Some(BoundArgument::Sequence(MaybeSequence::Seq(
798 nts.into_iter().map(Cow::into_owned).collect(),
799 )))
800 } else {
801 None
802 }
803 }
804 BoundArgument::BoundSeq(MaybeSequence::Seq(cvs)) => {
805 let mut changed = false;
806 let ncvs = cvs
807 .iter()
808 .map(|t| {
809 self.cv_full(expand, t, recusion_limit, total_limit).map_or(
810 Cow::Borrowed(t),
811 |a| {
812 changed = true;
813 Cow::Owned(a)
814 },
815 )
816 })
817 .collect::<Vec<_>>();
818 if changed {
819 Some(BoundArgument::BoundSeq(MaybeSequence::Seq(
820 ncvs.into_iter().map(Cow::into_owned).collect(),
821 )))
822 } else {
823 None
824 }
825 }
826 }
827 }
828
829 fn cv_full(
830 &mut self,
831 expand: Expansion,
832 arg: &'t ComponentVar,
833 recursion_limit: &mut usize,
834 total_limit: &mut usize,
835 ) -> Option<ComponentVar> {
836 match (arg.tp.as_ref(), arg.df.as_ref()) {
837 (None, None) => None,
838 (Some(tp), None) => self
839 .simplify_full_i(expand, tp, recursion_limit, total_limit)
840 .map(|tp| ComponentVar {
841 var: arg.var.clone(),
842 tp: Some(tp),
843 df: None,
844 }),
845 (None, Some(df)) => self
846 .simplify_full_i(expand, df, recursion_limit, total_limit)
847 .map(|df| ComponentVar {
848 var: arg.var.clone(),
849 tp: None,
850 df: Some(df),
851 }),
852 (Some(tp), Some(df)) => {
853 let ntp = self.simplify_full_i(expand, tp, recursion_limit, total_limit);
854 let ndf = self.simplify_full_i(expand, df, recursion_limit, total_limit);
855 if ntp.is_none() && ndf.is_none() {
856 return None;
857 }
858 Some(ComponentVar {
859 var: arg.var.clone(),
860 tp: Some(ntp.unwrap_or_else(|| tp.clone())),
861 df: Some(ndf.unwrap_or_else(|| df.clone())),
862 })
863 }
864 }
865 }
866
867 pub(crate) fn simplify_implicit(&mut self, term: &'t Term) -> Result<Option<Term>, ()> {
868 let Some((Term::Symbol { uri, .. }, args)) = term.unapply_implicits(false) else {
869 return Ok(None);
870 };
871 let Some(def) = self.get_symbol_definiens(uri) else {
872 self.comment(format!("Symbol has no definiens: {uri}"));
873 return Err(());
874 };
875 let Some((def, vars)) = def.get_bound_implicits() else {
876 self.failure("definiens has no implicit arguments");
877 return Err(());
878 };
879 if args.len() != vars.len() {
880 self.failure("number of implicit arguments don't match");
881 return Err(());
882 };
883 let mut substs = Vec::new();
884 for (ComponentVar { var, tp, .. }, arg) in vars.iter().zip(args) {
885 if let Some(tp) = tp {
886 let tp: Cow<Term> = tp / &*substs;
887 if self.scoped(|checker| checker.check_type(arg, &tp)) != Some(true) {
888 return Err(());
889 }
890 substs.push((var.name(), arg));
891 }
892 }
893 let r = def / &*substs;
894 tracing::debug!("Unapplied implicits: {:?}", r.debug_short());
895 Ok(Some(r.into_owned()))
896 }
897}