/- Copyright (c) 2016 Microsoft Corporation. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Leonardo de Moura -/ prelude import init.meta.tactic init.function namespace tactic open nat tactic environment expr list private meta_definition mk_intro_name : name → list name → name | n₁ (n₂ :: ns) := n₂ | n [] := if n = `a then `H else n -- Auxiliary function for introducing the new equalities produced by the -- injection tactic private meta_definition injection_intro : expr → list name → tactic unit | (pi n bi b d) ns := do Hname ← return $ mk_intro_name n ns, H ← intro Hname, Ht ← infer_type H, -- Clear new hypothesis if it is of the form (a = a) @try unit $ do { (lhs, rhs) ← match_eq Ht, unify lhs rhs, clear H }, -- If new hypothesis is of the form (@heq A a B b) where -- A and B can be unified then convert it into (a = b) using -- the eq_of_heq lemma @try unit $ do { (A, lhs, B, rhs) ← match_heq Ht, unify A B, Heq ← mk_app `eq [lhs, rhs], pr ← mk_app `eq_of_heq [H], assertv Hname Heq pr, clear H }, injection_intro d (tail ns) | e ns := skip meta_definition injection_with (H : expr) (ns : list name) : tactic unit := do Ht ← infer_type H, (lhs, rhs) ← match_eq Ht, env ← get_env, if is_constructor_app env lhs = tt ∧ is_constructor_app env rhs = tt ∧ const_name (get_app_fn lhs) = const_name (get_app_fn rhs) then do tgt ← target, I_name ← return $ name.get_prefix (const_name (get_app_fn lhs)), pr ← mk_app (I_name <.> "no_confusion") [tgt, lhs, rhs, H], pr_type ← infer_type pr, pr_type ← whnf pr_type, apply pr, injection_intro (binding_domain pr_type) ns else fail "injection tactic failed, argument must be an equality proof where lhs and rhs are of the form (c ...), where c is a constructor" meta_definition injection (H : expr) : tactic unit := injection_with H [] end tactic