(** Save primitive notation that will be overloaded. **)
Local Notation CoqGenericIf c vT vF := (if c then vT else vF) (only parsing).Local Notation CoqGenericDependentIf c x R vT vF :=
  (if c as x return R then vT else vF) (only parsing).Notation "'if' c 'then' vT 'else' vF" :=
  (CoqGenericIf c vT vF) (only parsing) : general_if_scope.Notation "'if' c 'return' R 'then' vT 'else' vF" :=
  (CoqGenericDependentIf c c R vT vF) (only parsing) : general_if_scope.Notation "'if' c 'as' x 'return' R 'then' vT 'else' vF" :=
  (CoqGenericDependentIf c x R vT vF) (only parsing) : general_if_scope.(**  Constants for abstract: and #[#: name #]# intro pattern  **)
Definition abstract_lock := unit.Definition abstract_key := tt.Notation "<hidden n >" := (abstract _ n _) : ssr_scope.Notation "T (* n *)" := (abstract T n abstract_key) : ssr_scope.Variant put vT sT (v1 v2 : vT) (s : sT) : Prop := Put.Variant put vT sT (v1 v2 : vT) (s : sT) : Prop := Put.(**
 The following are "format only" versions of the above notations.
 We need to do this to prevent the formatter from being be thrown off by
 application collapsing, coercion insertion and beta reduction in the right
 hand side of the notations above.                                           **)

Notation "[ 'the' sT 'of' v 'by' f ]" := (@get_by _ sT f v _ _)
  (only printing) : form_scope.Notation "[ 'the' sT 'of' v ]" := (@get _ sT v _ _)
  (only printing) : form_scope.Notation "{ 'type' 'of' c 'for' s }" := (dependentReturnType c s) : type_scope.(**
 A generic "phantom" type (actually, a unit type with a phantom parameter).
 This type can be used for type definitions that require some Structure
 on one of their parameters, to allow Coq to infer said structure so it
 does not have to be supplied explicitly or via the " #[#the _ of _ #]#" notation
 (the latter interacts poorly with other Notation).
   The definition of a (co)inductive type with a parameter p : p_type, that
 needs to use the operations of a structure
  Structure p_str : Type := p_Str {p_repr :> p_type; p_op : p_repr -> ...}
 should be given as
  Inductive indt_type (p : p_str) := Indt ... .
  Definition indt_of (p : p_str) & phantom p_type p := indt_type p.
  Notation "{ 'indt' p }" := (indt_of (Phantom p)).
  Definition indt p x y ... z : {indt p} := @Indt p x y ... z.
  Notation " #[# 'indt' x y ... z #]#" := (indt x y ... z).
 That is, the concrete type and its constructor should be shadowed by
 definitions that use a phantom argument to infer and display the true
 value of p (in practice, the "indt" constructor often performs additional
 functions, like "locking" the representation -- see below).
   We also define a simpler version ("phant" / "Phant") of phantom for the
 common case where p_type is Type.                                           **)

Variant phantom T (p : T) : Prop := Phantom.(**
 A generic "phantom" type (actually, a unit type with a phantom parameter).
 This type can be used for type definitions that require some Structure
 on one of their parameters, to allow Coq to infer said structure so it
 does not have to be supplied explicitly or via the " #[#the _ of _ #]#" notation
 (the latter interacts poorly with other Notation).
   The definition of a (co)inductive type with a parameter p : p_type, that
 needs to use the operations of a structure
  Structure p_str : Type := p_Str {p_repr :> p_type; p_op : p_repr -> ...}
 should be given as
  Inductive indt_type (p : p_str) := Indt ... .
  Definition indt_of (p : p_str) & phantom p_type p := indt_type p.
  Notation "{ 'indt' p }" := (indt_of (Phantom p)).
  Definition indt p x y ... z : {indt p} := @Indt p x y ... z.
  Notation " #[# 'indt' x y ... z #]#" := (indt x y ... z).
 That is, the concrete type and its constructor should be shadowed by
 definitions that use a phantom argument to infer and display the true
 value of p (in practice, the "indt" constructor often performs additional
 functions, like "locking" the representation -- see below).
   We also define a simpler version ("phant" / "Phant") of phantom for the
 common case where p_type is Type.                                           **)

Variant phantom T (p : T) : Prop := Phantom.Variant phant (p : Type) : Prop := Phant.Variant phant (p : Type) : Prop := Phant.(**  Internal tagging used by the implementation of the ssreflect elim.  **)

Definition protect_term (A : Type) (x : A) : A := x.(**
 The ssreflect idiom for a non-keyed pattern:
  - unkeyed t will match any subterm that unifies with t, regardless of
    whether it displays the same head symbol as t.
  - unkeyed t a b will match any application of a term f unifying with t,
    to two arguments unifying with a and b, respectively, regardless of
    apparent head symbols.
  - unkeyed x where x is a variable will match any subterm with the same
    type as x (when x would raise the 'indeterminate pattern' error).        **)

Notation unkeyed x := (let flex := x in flex).(**  Ssreflect converse rewrite rule rule idiom.  **)
Definition ssr_converse R (r : R) := (Logic.I, r).Notation "=^~ r" := (ssr_converse r) : form_scope.

(* Specifications: *)
Lemma master_key : unit.
Lemma lock A x : x = locked x :> A.