@@ -532,33 +532,50 @@ end
532
532
private meta def simp_lhs (ty : expr): tactic expr :=
533
533
prod.fst <$> simp_lhs_rhs ty
534
534
535
- /-- `simp_is_conditional ty` returns true iff the simp lemma with type `ty` is conditional. -/
536
- private meta def simp_is_conditional : expr → tactic bool | ty := do
535
+ /--
536
+ `simp_is_conditional_core ty` returns `none` if `ty` is a conditional simp
537
+ lemma, and `some lhs` otherwise.
538
+ -/
539
+ private meta def simp_is_conditional_core : expr → tactic (option expr) | ty := do
537
540
ty ← whnf ty transparency.semireducible,
538
541
match ty with
539
- | `(¬ %%lhs) := pure ff
540
- | `(%%lhs = _) := pure ff
541
- | `(%%lhs ↔ _) := pure ff
542
- | (expr.pi n bi a b) :=
543
- if bi ≠ binder_info.inst_implicit ∧ ¬ b.has_var then
544
- pure tt
545
- else do
546
- l ← mk_local' n bi a,
547
- simp_is_conditional (b.instantiate_var l)
548
- | ty := pure ff
542
+ | `(¬ %%lhs) := pure lhs
543
+ | `(%%lhs = _) := pure lhs
544
+ | `(%%lhs ↔ _) := pure lhs
545
+ | (expr.pi n bi a b) := do
546
+ l ← mk_local' n bi a,
547
+ some lhs ← simp_is_conditional_core (b.instantiate_var l) | pure none,
548
+ if bi ≠ binder_info.inst_implicit ∧
549
+ ¬ (lhs.abstract_local l.local_uniq_name).has_var then
550
+ pure none
551
+ else
552
+ pure lhs
553
+ | ty := pure ty
549
554
end
550
555
556
+ /--
557
+ `simp_is_conditional ty` returns true iff the simp lemma with type `ty` is conditional.
558
+ -/
559
+ private meta def simp_is_conditional (ty : expr) : tactic bool :=
560
+ option.is_none <$> simp_is_conditional_core ty
561
+
551
562
private meta def heuristic_simp_lemma_extraction (prf : expr) : tactic (list name) :=
552
563
prf.list_constant.to_list.mfilter is_simp_lemma
553
564
565
+ /-- Checks whether two expressions are equal for the simplifier. That is,
566
+ they are reducibly-definitional equal, and they have the same head symbol. -/
567
+ meta def is_simp_eq (a b : expr) : tactic bool :=
568
+ if a.get_app_fn.const_name ≠ b.get_app_fn.const_name then pure ff else
569
+ succeeds $ is_def_eq a b transparency.reducible
570
+
554
571
/-- Reports declarations that are simp lemmas whose left-hand side is not in simp-normal form. -/
555
572
meta def simp_nf_linter (timeout := 200000 ) (d : declaration) : tactic (option string) := do
556
573
tt ← is_simp_lemma d.to_name | pure none,
557
574
-- Sometimes, a definition is tagged @[ simp ] to add the equational lemmas to the simp set.
558
575
-- In this case, ignore the declaration if it is not a valid simp lemma by itself.
559
576
tt ← is_valid_simp_lemma_cnst d.to_name | pure none,
560
- (λ tac, tactic.try_for timeout tac <|> pure (some " timeout " )) $ -- last resort
561
- (λ tac : tactic _, tac <|> pure none) $ -- tc resolution depth
577
+ [] ← get_eqn_lemmas_for ff d.to_name | pure none,
578
+ try_for timeout $
562
579
retrieve $ do
563
580
reset_instance_cache,
564
581
g ← mk_meta_var d.type,
@@ -567,14 +584,16 @@ intros,
567
584
(lhs, rhs) ← target >>= simp_lhs_rhs,
568
585
sls ← simp_lemmas.mk_default,
569
586
let sls' := sls.erase [d.to_name],
570
- -- TODO: should we do something special about rfl-lemmas?
571
- (lhs', prf1) ← simplify sls [] lhs {fail_if_unchanged := ff},
587
+ (lhs', prf1) ← decorate_error " simplify fails on left-hand side: " $
588
+ simplify sls [] lhs {fail_if_unchanged := ff},
572
589
prf1_lems ← heuristic_simp_lemma_extraction prf1,
573
590
if d.to_name ∈ prf1_lems then pure none else do
574
- (rhs', prf2) ← simplify sls [] rhs {fail_if_unchanged := ff},
575
- lhs'_eq_rhs' ← succeeds (is_def_eq lhs' rhs' transparency.reducible),
576
- lhs_in_nf ← succeeds (is_def_eq lhs' lhs transparency.reducible),
577
- if lhs'_eq_rhs' ∧ lhs'.get_app_fn.const_name = rhs'.get_app_fn.const_name then do
591
+ is_cond ← simp_is_conditional d.type,
592
+ (rhs', prf2) ← decorate_error " simplify fails on right-hand side:" $
593
+ simplify sls [] rhs {fail_if_unchanged := ff},
594
+ lhs'_eq_rhs' ← is_simp_eq lhs' rhs',
595
+ lhs_in_nf ← is_simp_eq lhs' lhs,
596
+ if lhs'_eq_rhs' then do
578
597
used_lemmas ← heuristic_simp_lemma_extraction (prf1 prf2),
579
598
pure $ pure $ " simp can prove this:\n "
580
599
++ " by simp only " ++ to_string used_lemmas ++ " \n "
@@ -589,6 +608,8 @@ else if ¬ lhs_in_nf then do
589
608
++ " to" ++ lhs'.group.indent 2 ++ format.line
590
609
++ " using " ++ (to_fmt prf1_lems).group.indent 2 ++ format.line
591
610
++ " Try to change the left-hand side to the simplified term!\n "
611
+ else if ¬ is_cond ∧ lhs = lhs' then do
612
+ pure " Left-hand side does not simplify.\n You need to debug this yourself using `set_option trace.simplify.rewrite true`"
592
613
else
593
614
pure none
594
615
@@ -705,8 +726,17 @@ checks.mmap $ λ ⟨linter_name, linter⟩, do
705
726
let test_decls := if linter.auto_decls then all_decls else non_auto_decls,
706
727
results ← test_decls.mfoldl (λ (results : rb_map name string) decl, do
707
728
tt ← should_be_linted linter_name decl.to_name | pure results,
708
- some linter_warning ← linter.test decl | pure results,
709
- pure $ results.insert decl.to_name linter_warning) mk_rb_map,
729
+ s ← read,
730
+ let linter_warning : option string :=
731
+ match linter.test decl s with
732
+ | result.success w _ := w
733
+ | result.exception msg _ _ :=
734
+ some $ " LINTER FAILED:\n " ++ msg.elim " (no message)" (λ msg, to_string $ msg ())
735
+ end ,
736
+ match linter_warning with
737
+ | some w := pure $ results.insert decl.to_name w
738
+ | none := pure results
739
+ end ) mk_rb_map,
710
740
pure (linter_name, linter, results)
711
741
712
742
/-- Sorts a map with declaration keys as names by line number. -/
0 commit comments