]> matita.cs.unibo.it Git - helm.git/blobdiff - helm/ocaml/cic_proof_checking/cicTypeChecker.ml
New experimental commit: metavariables representation is changed again,
[helm.git] / helm / ocaml / cic_proof_checking / cicTypeChecker.ml
index 34eb7d23f5795e9fe52ca0e68abdd701afef7f81..2e8b5585f5190c6d2110ef8fab6a576b39f7b614 100644 (file)
@@ -32,6 +32,8 @@ exception ListTooShort;;
 exception NotPositiveOccurrences of string;;
 exception NotWellFormedTypeOfInductiveConstructor of string;;
 exception WrongRequiredArgument of string;;
+exception RelToHiddenHypothesis;;
+exception MetasenvInconsistency;;
 
 let fdebug = ref 0;;
 let debug t context =
@@ -127,15 +129,15 @@ and does_not_occur context n nn te =
     | C.Implicit -> true
     | C.Cast (te,ty) ->
        does_not_occur context n nn te && does_not_occur context n nn ty
-    | C.Prod (_,so,dest) ->
+    | C.Prod (name,so,dest) ->
        does_not_occur context n nn so &&
-        does_not_occur ((C.Decl so)::context) (n + 1) (nn + 1) dest
-    | C.Lambda (_,so,dest) ->
+        does_not_occur((Some (name,(C.Decl so)))::context) (n + 1) (nn + 1) dest
+    | C.Lambda (name,so,dest) ->
        does_not_occur context n nn so &&
-        does_not_occur ((C.Decl so)::context) (n + 1) (nn + 1) dest
-    | C.LetIn (_,so,dest) ->
+        does_not_occur((Some (name,(C.Decl so)))::context) (n + 1) (nn + 1) dest
+    | C.LetIn (name,so,dest) ->
        does_not_occur context n nn so &&
-        does_not_occur ((C.Def so)::context) (n + 1) (nn + 1) dest
+        does_not_occur ((Some (name,(C.Def so)))::context) (n + 1) (nn + 1) dest
     | C.Appl l ->
        List.fold_right (fun x i -> i && does_not_occur context n nn x) l true
     | C.Const _
@@ -149,7 +151,9 @@ and does_not_occur context n nn te =
        let len = List.length fl in
         let n_plus_len = n + len in
         let nn_plus_len = nn + len in
-        let tys = List.map (fun (_,_,ty,_) -> Cic.Decl ty) fl in
+        let tys =
+         List.map (fun (n,_,ty,_) -> Some (C.Name n,(Cic.Decl ty))) fl
+        in
          List.fold_right
           (fun (_,_,ty,bo) i ->
             i && does_not_occur context n nn ty &&
@@ -159,7 +163,9 @@ and does_not_occur context n nn te =
        let len = List.length fl in
         let n_plus_len = n + len in
         let nn_plus_len = nn + len in
-        let tys = List.map (fun (_,ty,_) -> Cic.Decl ty) fl in
+        let tys =
+         List.map (fun (n,ty,_) -> Some (C.Name n,(Cic.Decl ty))) fl
+        in
          List.fold_right
           (fun (_,ty,bo) i ->
             i && does_not_occur context n nn ty &&
@@ -214,17 +220,20 @@ and weakly_positive context n nn uri te =
    | C.Prod (C.Anonimous,source,dest) ->
       strictly_positive context n nn
        (subst_inductive_type_with_dummy_mutind source) &&
-       weakly_positive ((C.Decl source)::context) (n + 1) (nn + 1) uri dest
+       weakly_positive ((Some (C.Anonimous,(C.Decl source)))::context)
+        (n + 1) (nn + 1) uri dest
    | C.Prod (name,source,dest) when
-      does_not_occur ((C.Decl source)::context) 0 n dest ->
+      does_not_occur ((Some (name,(C.Decl source)))::context) 0 n dest ->
        (* dummy abstraction, so we behave as in the anonimous case *)
        strictly_positive context n nn
         (subst_inductive_type_with_dummy_mutind source) &&
-        weakly_positive ((C.Decl source)::context) (n + 1) (nn + 1) uri dest
-   | C.Prod (_,source,dest) ->
+        weakly_positive ((Some (name,(C.Decl source)))::context)
+         (n + 1) (nn + 1) uri dest
+   | C.Prod (name,source,dest) ->
       does_not_occur context n nn
        (subst_inductive_type_with_dummy_mutind source)&&
-       weakly_positive ((C.Decl source)::context) (n + 1) (nn + 1) uri dest
+       weakly_positive ((Some (name,(C.Decl source)))::context)
+        (n + 1) (nn + 1) uri dest
    | _ -> raise (NotWellFormedTypeOfInductiveConstructor ("Guess where the error is ;-)"))
 
 (* instantiate_parameters ps (x1:T1)...(xn:Tn)C                             *)
@@ -247,17 +256,17 @@ and strictly_positive context n nn te =
    | C.Cast (te,ty) ->
       (*CSC: bisogna controllare ty????*)
       strictly_positive context n nn te
-   | C.Prod (_,so,ta) ->
+   | C.Prod (name,so,ta) ->
       does_not_occur context n nn so &&
-       strictly_positive ((C.Decl so)::context) (n+1) (nn+1) ta
+       strictly_positive ((Some (name,(C.Decl so)))::context) (n+1) (nn+1) ta
    | C.Appl ((C.Rel m)::tl) when m > n && m <= nn ->
       List.fold_right (fun x i -> i && does_not_occur context n nn x) tl true
    | C.Appl ((C.MutInd (uri,_,i))::tl) -> 
-      let (ok,paramsno,ity,cl) =
+      let (ok,paramsno,ity,cl,name) =
        match CicEnvironment.get_obj uri with
            C.InductiveDefinition (tl,_,paramsno) ->
-            let (_,_,ity,cl) = List.nth tl i in
-             (List.length tl = 1, paramsno, ity, cl)
+            let (name,_,ity,cl) = List.nth tl i in
+             (List.length tl = 1, paramsno, ity, cl, name)
          | _ -> raise(WrongUriToMutualInductiveDefinitions(U.string_of_uri uri))
       in
        let (params,arguments) = split tl paramsno in
@@ -273,7 +282,8 @@ and strictly_positive context n nn te =
          List.fold_right
           (fun x i ->
             i &&
-             weakly_positive ((Cic.Decl ity)::context) (n+1) (nn+1) uri x
+             weakly_positive
+              ((Some (C.Name name,(Cic.Decl ity)))::context) (n+1) (nn+1) uri x
           ) cl' true
    | t -> does_not_occur context n nn t
 
@@ -306,18 +316,20 @@ and are_all_occurrences_positive context uri indparamsno i n nn te =
        raise (WrongRequiredArgument (UriManager.string_of_uri uri))
    | C.Prod (C.Anonimous,source,dest) ->
       strictly_positive context n nn source &&
-       are_all_occurrences_positive ((C.Decl source)::context) uri indparamsno
+       are_all_occurrences_positive
+        ((Some (C.Anonimous,(C.Decl source)))::context) uri indparamsno
         (i+1) (n + 1) (nn + 1) dest
    | C.Prod (name,source,dest) when
-      does_not_occur ((C.Decl source)::context) 0 n dest ->
+      does_not_occur ((Some (name,(C.Decl source)))::context) 0 n dest ->
       (* dummy abstraction, so we behave as in the anonimous case *)
       strictly_positive context n nn source &&
-       are_all_occurrences_positive ((C.Decl source)::context) uri indparamsno
+       are_all_occurrences_positive
+        ((Some (name,(C.Decl source)))::context) uri indparamsno
         (i+1) (n + 1) (nn + 1) dest
-   | C.Prod (_,source,dest) ->
+   | C.Prod (name,source,dest) ->
       does_not_occur context n nn source &&
-       are_all_occurrences_positive ((C.Decl source)::context) uri indparamsno
-        (i+1) (n + 1) (nn + 1) dest
+       are_all_occurrences_positive ((Some (name,(C.Decl source)))::context)
+        uri indparamsno (i+1) (n + 1) (nn + 1) dest
    | _ -> raise (NotWellFormedTypeOfInductiveConstructor (UriManager.string_of_uri uri))
 
 (*CSC: cambiare il nome, torna unit! *)
@@ -339,7 +351,8 @@ and cooked_mutual_inductive_defs uri =
 (*CSC: siamo sicuri che non debba fare anche un List.rev? Il bug *)
 (*CSC: si manifesterebbe solamene con tipi veramente mutualmente *)
 (*CSC: induttivi...                                              *)
-       let tys = List.map (fun (_,_,ty,_) -> Cic.Decl ty) itl in
+       let tys =
+        List.map (fun (n,_,ty,_) -> Some (Cic.Name n,(Cic.Decl ty))) itl in
        let _ =
         List.fold_right
          (fun (_,_,_,cl) i ->
@@ -425,9 +438,9 @@ and recursive_args context n nn te =
    | C.Sort _
    | C.Implicit
    | C.Cast _ (*CSC ??? *) -> raise (Impossible 3) (* due to type-checking *)
-   | C.Prod (_,so,de) ->
+   | C.Prod (name,so,de) ->
       (not (does_not_occur context n nn so)) ::
-       (recursive_args ((C.Decl so)::context) (n+1) (nn + 1) de)
+       (recursive_args ((Some (name,(C.Decl so)))::context) (n+1) (nn + 1) de)
    | C.Lambda _
    | C.LetIn _ -> raise (Impossible 4) (* due to type-checking *)
    | C.Appl _ -> []
@@ -444,7 +457,7 @@ and get_new_safes context p c rl safes n nn x =
  let module U = UriManager in
  let module R = CicReduction in
   match (R.whd context c, R.whd context p, rl) with
-     (C.Prod (_,so,ta1), C.Lambda (_,_,ta2), b::tl) ->
+     (C.Prod (_,so,ta1), C.Lambda (name,_,ta2), b::tl) ->
        (* we are sure that the two sources are convertible because we *)
        (* have just checked this. So let's go along ...               *)
        let safes' =
@@ -453,8 +466,8 @@ and get_new_safes context p c rl safes n nn x =
         let safes'' =
          if b then 1::safes' else safes'
         in
-         get_new_safes ((C.Decl so)::context) ta2 ta1 tl safes'' (n+1) (nn+1)
-          (x+1)
+         get_new_safes ((Some (name,(C.Decl so)))::context)
+          ta2 ta1 tl safes'' (n+1) (nn+1) (x+1)
    | (C.Prod _, (C.MutConstruct _ as e), _)
    | (C.Prod _, (C.Rel _ as e), _)
    | (C.MutInd _, e, [])
@@ -472,8 +485,8 @@ and split_prods context n te =
  let module R = CicReduction in
   match (n, R.whd context te) with
      (0, _) -> context,te
-   | (n, C.Prod (_,so,ta)) when n > 0 ->
-       split_prods ((C.Decl so)::context) (n - 1) ta
+   | (n, C.Prod (name,so,ta)) when n > 0 ->
+       split_prods ((Some (name,(C.Decl so)))::context) (n - 1) ta
    | (_, _) -> raise (Impossible 8)
 
 and eat_lambdas context n te =
@@ -481,8 +494,10 @@ and eat_lambdas context n te =
  let module R = CicReduction in
   match (n, R.whd context te) with
      (0, _) -> (te, 0, context)
-   | (n, C.Lambda (_,so,ta)) when n > 0 ->
-      let (te, k, context') = eat_lambdas ((C.Decl so)::context) (n - 1) ta in
+   | (n, C.Lambda (name,so,ta)) when n > 0 ->
+      let (te, k, context') =
+       eat_lambdas ((Some (name,(C.Decl so)))::context) (n - 1) ta
+      in
        (te, k + 1, context')
    | (_, _) -> raise (Impossible 9)
 
@@ -508,14 +523,14 @@ and check_is_really_smaller_arg context n nn kl x safes te =
        check_is_really_smaller_arg (n+1) (nn+1) kl (x+1)
         (List.map (fun x -> x + 1) safes) ta*)
    | C.Prod _ -> raise (Impossible 10)
-   | C.Lambda (_,so,ta) ->
+   | C.Lambda (name,so,ta) ->
       check_is_really_smaller_arg context n nn kl x safes so &&
-       check_is_really_smaller_arg ((C.Decl so)::context) (n+1) (nn+1) kl (x+1)
-        (List.map (fun x -> x + 1) safes) ta
-   | C.LetIn (_,so,ta) ->
+       check_is_really_smaller_arg ((Some (name,(C.Decl so)))::context)
+        (n+1) (nn+1) kl (x+1) (List.map (fun x -> x + 1) safes) ta
+   | C.LetIn (name,so,ta) ->
       check_is_really_smaller_arg context n nn kl x safes so &&
-       check_is_really_smaller_arg ((C.Def so)::context) (n+1) (nn+1) kl (x+1)
-        (List.map (fun x -> x + 1) safes) ta
+       check_is_really_smaller_arg ((Some (name,(C.Def so)))::context)
+        (n+1) (nn+1) kl (x+1) (List.map (fun x -> x + 1) safes) ta
    | C.Appl (he::_) ->
       (*CSC: sulla coda ci vogliono dei controlli? secondo noi no, ma *)
       (*CSC: solo perche' non abbiamo trovato controesempi            *)
@@ -531,7 +546,9 @@ and check_is_really_smaller_arg context n nn kl x safes te =
            let (isinductive,paramsno,cl) =
             match CicEnvironment.get_obj uri with
                C.InductiveDefinition (tl,_,paramsno) ->
-                let tys = List.map (fun (_,_,ty,_) -> Cic.Decl ty) tl in
+                let tys =
+                 List.map (fun (n,_,ty,_) -> Some (Cic.Name n,(Cic.Decl ty))) tl
+                in
                  let (_,isinductive,_,cl) = List.nth tl i in
                   let cl' =
                    List.map
@@ -568,7 +585,9 @@ and check_is_really_smaller_arg context n nn kl x safes te =
             match CicEnvironment.get_obj uri with
                C.InductiveDefinition (tl,_,paramsno) ->
                 let (_,isinductive,_,cl) = List.nth tl i in
-                 let tys = List.map (fun (_,_,ty,_) -> Cic.Decl ty) tl in
+                 let tys =
+                  List.map (fun (n,_,ty,_) -> Some(Cic.Name n,(Cic.Decl ty))) tl
+                 in
                   let cl' =
                    List.map
                     (fun (id,ty,r) ->
@@ -612,8 +631,7 @@ and check_is_really_smaller_arg context n nn kl x safes te =
        let n_plus_len = n + len
        and nn_plus_len = nn + len
        and x_plus_len = x + len
-       (*CSC: Is a Decl of the ty ok or should I use Def of a Fix? *)
-       and tys = List.map (fun (_,_,ty,_) -> C.Decl ty) fl
+       and tys = List.map (fun (n,_,ty,_) -> Some (C.Name n,(C.Decl ty))) fl
        and safes' = List.map (fun x -> x + len) safes in
         List.fold_right
          (fun (_,_,ty,bo) i ->
@@ -626,8 +644,7 @@ and check_is_really_smaller_arg context n nn kl x safes te =
        let n_plus_len = n + len
        and nn_plus_len = nn + len
        and x_plus_len = x + len
-       (*CSC: Is a Decl of the ty ok or should I use Def of a Fix? *)
-       and tys = List.map (fun (_,ty,_) -> C.Decl ty) fl
+       and tys = List.map (fun (n,ty,_) -> Some (C.Name n,(C.Decl ty))) fl
        and safes' = List.map (fun x -> x + len) safes in
         List.fold_right
          (fun (_,ty,bo) i ->
@@ -643,8 +660,9 @@ and guarded_by_destructors context n nn kl x safes =
      C.Rel m when m > n && m <= nn -> false
    | C.Rel n ->
       (match List.nth context (n-1) with
-          C.Decl _ -> true
-        | C.Def bo -> guarded_by_destructors context n nn kl x safes bo
+          Some (_,C.Decl _) -> true
+        | Some (_,C.Def bo) -> guarded_by_destructors context n nn kl x safes bo
+       | None -> raise RelToHiddenHypothesis
       )
    | C.Var _
    | C.Meta _
@@ -653,18 +671,18 @@ and guarded_by_destructors context n nn kl x safes =
    | C.Cast (te,ty) ->
       guarded_by_destructors context n nn kl x safes te &&
        guarded_by_destructors context n nn kl x safes ty
-   | C.Prod (_,so,ta) ->
+   | C.Prod (name,so,ta) ->
       guarded_by_destructors context n nn kl x safes so &&
-       guarded_by_destructors ((C.Decl so)::context) (n+1) (nn+1) kl (x+1)
-        (List.map (fun x -> x + 1) safes) ta
-   | C.Lambda (_,so,ta) ->
+       guarded_by_destructors ((Some (name,(C.Decl so)))::context)
+        (n+1) (nn+1) kl (x+1) (List.map (fun x -> x + 1) safes) ta
+   | C.Lambda (name,so,ta) ->
       guarded_by_destructors context n nn kl x safes so &&
-       guarded_by_destructors ((C.Decl so)::context) (n+1) (nn+1) kl (x+1)
-        (List.map (fun x -> x + 1) safes) ta
-   | C.LetIn (_,so,ta) ->
+       guarded_by_destructors ((Some (name,(C.Decl so)))::context)
+        (n+1) (nn+1) kl (x+1) (List.map (fun x -> x + 1) safes) ta
+   | C.LetIn (name,so,ta) ->
       guarded_by_destructors context n nn kl x safes so &&
-       guarded_by_destructors ((C.Def so)::context) (n+1) (nn+1) kl (x+1)
-        (List.map (fun x -> x + 1) safes) ta
+       guarded_by_destructors ((Some (name,(C.Def so)))::context)
+        (n+1) (nn+1) kl (x+1) (List.map (fun x -> x + 1) safes) ta
    | C.Appl ((C.Rel m)::tl) when m > n && m <= nn ->
       let k = List.nth kl (m - n - 1) in
        if not (List.length tl > k) then false
@@ -689,7 +707,9 @@ and guarded_by_destructors context n nn kl x safes =
             match CicEnvironment.get_obj uri with
                C.InductiveDefinition (tl,_,paramsno) ->
                 let (_,isinductive,_,cl) = List.nth tl i in
-                 let tys = List.map (fun (_,_,ty,_) -> Cic.Decl ty) tl in
+                 let tys =
+                  List.map (fun (n,_,ty,_) -> Some(Cic.Name n,(Cic.Decl ty))) tl
+                 in
                   let cl' =
                    List.map
                     (fun (id,ty,r) ->
@@ -730,7 +750,9 @@ and guarded_by_destructors context n nn kl x safes =
             match CicEnvironment.get_obj uri with
                C.InductiveDefinition (tl,_,paramsno) ->
                 let (_,isinductive,_,cl) = List.nth tl i in
-                 let tys = List.map (fun (_,_,ty,_) -> Cic.Decl ty) tl in
+                 let tys =
+                  List.map (fun (n,_,ty,_) -> Some(Cic.Name n,(Cic.Decl ty))) tl
+                 in
                   let cl' =
                    List.map
                     (fun (id,ty,r) ->
@@ -783,8 +805,7 @@ and guarded_by_destructors context n nn kl x safes =
        let n_plus_len = n + len
        and nn_plus_len = nn + len
        and x_plus_len = x + len
-       (*CSC: Is a Decl of the ty ok or should I use Def of a Fix? *)
-       and tys = List.map (fun (_,_,ty,_) -> C.Decl ty) fl
+       and tys = List.map (fun (n,_,ty,_) -> Some (C.Name n,(C.Decl ty))) fl
        and safes' = List.map (fun x -> x + len) safes in
         List.fold_right
          (fun (_,_,ty,bo) i ->
@@ -797,8 +818,7 @@ and guarded_by_destructors context n nn kl x safes =
        let n_plus_len = n + len
        and nn_plus_len = nn + len
        and x_plus_len = x + len
-       (*CSC: Is a Decl of the ty ok or should I use Def of a Fix? *)
-       and tys = List.map (fun (_,ty,_) -> C.Decl ty) fl
+       and tys = List.map (fun (n,ty,_) -> Some (C.Name n,(C.Decl ty))) fl
        and safes' = List.map (fun x -> x + len) safes in
         List.fold_right
          (fun (_,ty,bo) i ->
@@ -828,10 +848,10 @@ and guarded_by_constructors context n nn h te args coInductiveTypeURI =
    | C.Prod _
    | C.LetIn _ ->
       raise (Impossible 17) (* the term has just been type-checked *)
-   | C.Lambda (_,so,de) ->
+   | C.Lambda (name,so,de) ->
       does_not_occur context n nn so &&
-       guarded_by_constructors ((C.Decl so)::context) (n + 1) (nn + 1) h de args
-        coInductiveTypeURI
+       guarded_by_constructors ((Some (name,(C.Decl so)))::context)
+        (n + 1) (nn + 1) h de args coInductiveTypeURI
    | C.Appl ((C.Rel m)::tl) when m > n && m <= nn ->
       h &&
        List.fold_right (fun x i -> i && does_not_occur context n nn x) tl true
@@ -854,8 +874,8 @@ and guarded_by_constructors context n nn h te args coInductiveTypeURI =
             does_not_occur context n nn te
          | C.Implicit
          | C.Cast _ -> raise (Impossible 24) (* due to type-checking *)
-         | C.Prod (_,so,de) ->
-            analyse_branch ((C.Decl so)::context) de te
+         | C.Prod (name,so,de) ->
+            analyse_branch ((Some (name,(C.Decl so)))::context) de te
          | C.Lambda _
          | C.LetIn _ -> raise (Impossible 25) (* due to type-checking *)
          | C.Appl ((C.MutInd (uri,_,_))::tl) as ty
@@ -886,13 +906,14 @@ and guarded_by_constructors context n nn h te args coInductiveTypeURI =
          | C.Sort _
          | C.Implicit
          | C.Cast _ -> raise (Impossible 29) (* due to type-checking *)
-         | C.Prod (_,so,de) ->
+         | C.Prod (name,so,de) ->
             begin
              match l with
                 [] -> true
               | he::tl ->
                  analyse_branch context so he &&
-                  analyse_instantiated_type ((C.Decl so)::context) de tl
+                  analyse_instantiated_type ((Some (name,(C.Decl so)))::context)
+                   de tl
             end
          | C.Lambda _
          | C.LetIn _ -> raise (Impossible 30) (* due to type-checking *)
@@ -940,7 +961,7 @@ and guarded_by_constructors context n nn h te args coInductiveTypeURI =
         let n_plus_len = n + len
         and nn_plus_len = nn + len
         (*CSC: Is a Decl of the ty ok or should I use Def of a Fix? *)
-        and tys = List.map (fun (_,ty,_) -> C.Decl ty) fl in
+        and tys = List.map (fun (n,ty,_) -> Some (C.Name n,(C.Decl ty))) fl in
          List.fold_right
           (fun (_,ty,bo) i ->
             i && does_not_occur context n nn ty &&
@@ -975,7 +996,7 @@ and guarded_by_constructors context n nn h te args coInductiveTypeURI =
        let n_plus_len = n + len
        and nn_plus_len = nn + len
        (*CSC: Is a Decl of the ty ok or should I use Def of a Fix? *)
-       and tys = List.map (fun (_,_,ty,_) -> C.Decl ty) fl in
+       and tys = List.map (fun (n,_,ty,_) -> Some (C.Name n,(C.Decl ty))) fl in
         List.fold_right
          (fun (_,_,ty,bo) i ->
            i && does_not_occur context n nn ty &&
@@ -986,7 +1007,7 @@ and guarded_by_constructors context n nn h te args coInductiveTypeURI =
        let n_plus_len = n + len
        and nn_plus_len = nn + len
        (*CSC: Is a Decl of the ty ok or should I use Def of a Fix? *)
-       and tys = List.map (fun (_,ty,_) -> C.Decl ty) fl in
+       and tys = List.map (fun (n,ty,_) -> Some (C.Name n,(C.Decl ty))) fl in
         List.fold_right
          (fun (_,ty,bo) i ->
            i && does_not_occur context n nn ty &&
@@ -1017,7 +1038,9 @@ and check_allowed_sort_elimination context uri i need_dummy ind arity1 arity2 =
    | (C.Sort C.Set, C.Sort C.Type) when need_dummy ->
        (match CicEnvironment.get_obj uri with
            C.InductiveDefinition (itl,_,paramsno) ->
-            let tys = List.map (fun (_,_,ty,_) -> Cic.Decl ty) itl in
+            let tys =
+             List.map (fun (n,_,ty,_) -> Some (Cic.Name n,(Cic.Decl ty))) itl
+            in
              let (_,_,_,cl) = List.nth itl i in
               List.fold_right
                (fun (_,x,_) i -> i && is_small tys paramsno x) cl true
@@ -1025,11 +1048,11 @@ and check_allowed_sort_elimination context uri i need_dummy ind arity1 arity2 =
            raise (WrongUriToMutualInductiveDefinitions (U.string_of_uri uri))
        )
    | (C.Sort C.Type, C.Sort _) when need_dummy -> true
-   | (C.Sort C.Prop, C.Prod (_,so,ta)) when not need_dummy ->
+   | (C.Sort C.Prop, C.Prod (name,so,ta)) when not need_dummy ->
        let res = CicReduction.are_convertible context so ind
        in
         res &&
-        (match CicReduction.whd ((C.Decl so)::context) ta with
+        (match CicReduction.whd ((Some (name,(C.Decl so)))::context) ta with
             C.Sort C.Prop -> true
           | C.Sort C.Set ->
              (match CicEnvironment.get_obj uri with
@@ -1043,18 +1066,21 @@ and check_allowed_sort_elimination context uri i need_dummy ind arity1 arity2 =
              )
           | _ -> false
         )
-   | (C.Sort C.Set, C.Prod (_,so,ta)) when not need_dummy ->
+   | (C.Sort C.Set, C.Prod (name,so,ta)) when not need_dummy ->
        let res = CicReduction.are_convertible context so ind
        in
         res &&
-        (match CicReduction.whd ((C.Decl so)::context) ta with
+        (match CicReduction.whd ((Some (name,(C.Decl so)))::context) ta with
             C.Sort C.Prop
           | C.Sort C.Set  -> true
           | C.Sort C.Type ->
              (match CicEnvironment.get_obj uri with
                  C.InductiveDefinition (itl,_,paramsno) ->
                   let (_,_,_,cl) = List.nth itl i in
-                   let tys = List.map (fun (_,_,ty,_) -> Cic.Decl ty) itl in
+                   let tys =
+                    List.map
+                     (fun (n,_,ty,_) -> Some (Cic.Name n,(Cic.Decl ty))) itl
+                   in
                     List.fold_right
                      (fun (_,x,_) i -> i && is_small tys paramsno x) cl true
                | _ ->
@@ -1084,12 +1110,46 @@ and type_of_branch context argsno need_dummy outtype term constype =
        else
         C.Appl (outtype::arguments@(if need_dummy then [] else [term]))
    | C.Prod (name,so,de) ->
-      C.Prod (C.Anonimous,so,type_of_branch ((C.Decl so)::context) argsno
-       need_dummy (CicSubstitution.lift 1 outtype)
+      C.Prod (C.Anonimous,so,type_of_branch
+       ((Some (name,(C.Decl so)))::context) argsno need_dummy
+       (CicSubstitution.lift 1 outtype)
        (C.Appl [CicSubstitution.lift 1 term ; C.Rel 1]) de)
   | _ -> raise (Impossible 20)
-       
+
+(* check_metasenv_consistency checks that the "canonical" context of a
+metavariable is consitent - up to relocation via the relocation list l -
+with the actual context *)
+
+and check_metasenv_consistency metasenv context canonical_context l =
+  let module C = Cic in
+  let module R = CicReduction in
+  let module S = CicSubstitution in
+   let lifted_canonical_context = 
+    let rec aux i =
+     function
+        [] -> []
+      | (Some (n,C.Decl t))::tl ->
+         (Some (n,C.Decl (S.lift_meta l (S.lift i t))))::(aux (i+1) tl)
+      | (Some (n,C.Def t))::tl ->
+         (Some (n,C.Def (S.lift_meta l (S.lift i t))))::(aux (i+1) tl)
+      | None::tl -> None::(aux (i+1) tl)
+    in
+     aux 1 canonical_context
+   in
+  List.iter2 
+    (fun t ct -> 
+      let res =
+       match (t,ct) with
+          _,None -> true
+        | Some t,Some (_,C.Def ct) ->
+           R.are_convertible context t ct
+        | Some t,Some (_,C.Decl ct) ->
+           R.are_convertible context (type_of_aux' metasenv context t) ct
+        | _, _  -> false
+      in
+       if not res then raise MetasenvInconsistency
+    ) l lifted_canonical_context 
+
 (* type_of_aux' is just another name (with a different scope) for type_of_aux *)
 and type_of_aux' metasenv context t =
  let rec type_of_aux context =
@@ -1101,8 +1161,9 @@ and type_of_aux' metasenv context t =
       C.Rel n ->
        (try
          match List.nth context (n - 1) with
-            C.Decl t -> S.lift n t
-          | C.Def bo -> type_of_aux context (S.lift n bo)
+            Some (_,C.Decl t) -> S.lift n t
+          | Some (_,C.Def bo) -> type_of_aux context (S.lift n bo)
+         | None -> raise RelToHiddenHypothesis
         with
          _ -> raise (NotWellTyped "Not a close term")
        )
@@ -1111,27 +1172,33 @@ and type_of_aux' metasenv context t =
       let ty = type_of_variable uri in
        decr fdebug ;
        ty
-    | C.Meta n -> List.assoc n metasenv
+    | C.Meta (n,l) -> 
+       let (_,canonical_context,ty) =
+        List.find (function (m,_,_) -> n = m) metasenv
+       in
+        check_metasenv_consistency metasenv context canonical_context l;
+        CicSubstitution.lift_meta l ty
     | C.Sort s -> C.Sort C.Type (*CSC manca la gestione degli universi!!! *)
     | C.Implicit -> raise (Impossible 21)
     | C.Cast (te,ty) ->
        let _ = type_of_aux context ty in
         if R.are_convertible context (type_of_aux context te) ty then ty
         else raise (NotWellTyped "Cast")
-    | C.Prod (_,s,t) ->
+    | C.Prod (name,s,t) ->
        let sort1 = type_of_aux context s
-       and sort2 = type_of_aux ((C.Decl s)::context) t in
-        sort_of_prod (sort1,sort2)
+       and sort2 = type_of_aux ((Some (name,(C.Decl s)))::context) t in
+        sort_of_prod context (name,s) (sort1,sort2)
    | C.Lambda (n,s,t) ->
        let sort1 = type_of_aux context s
-       and type2 = type_of_aux ((C.Decl s)::context) t in
-        let sort2 = type_of_aux ((C.Decl s)::context) type2 in
+       and type2 = type_of_aux ((Some (n,(C.Decl s)))::context) t in
+        let sort2 = type_of_aux ((Some (n,(C.Decl s)))::context) type2 in
          (* only to check if the product is well-typed *)
-         let _ = sort_of_prod (sort1,sort2) in
+         let _ = sort_of_prod context (n,s) (sort1,sort2) in
           C.Prod (n,s,type2)
    | C.LetIn (n,s,t) ->
-       let t' = CicSubstitution.subst s t in
-        type_of_aux context t'
+      (* only to check if s is well-typed *)
+      let _ = type_of_aux context s in
+       C.LetIn (n,s, type_of_aux ((Some (n,(C.Def s)))::context) t)
    | C.Appl (he::tl) when List.length tl > 0 ->
       let hetype = type_of_aux context he
       and tlbody_and_type = List.map (fun x -> (x, type_of_aux context x)) tl in
@@ -1158,8 +1225,8 @@ and type_of_aux' metasenv context t =
        let rec guess_args context t =
         match CicReduction.whd context t with
            C.Sort _ -> (true, 0)
-         | C.Prod (_, s, t) ->
-            let (b, n) = guess_args ((C.Decl s)::context) t in
+         | C.Prod (name, s, t) ->
+            let (b, n) = guess_args ((Some (name,(C.Decl s)))::context) t in
              if n = 0 then
               (* last prod before sort *)
               match CicReduction.whd context s with
@@ -1243,8 +1310,9 @@ and type_of_aux' metasenv context t =
       let types_times_kl =
        List.rev
         (List.map
-          (fun (_,k,ty,_) ->
-            let _ = type_of_aux context ty in (C.Decl ty,k)) fl)
+          (fun (n,k,ty,_) ->
+            let _ = type_of_aux context ty in
+             (Some (C.Name n,(C.Decl ty)),k)) fl)
       in
       let (types,kl) = List.split types_times_kl in
        let len = List.length types in
@@ -1276,7 +1344,8 @@ and type_of_aux' metasenv context t =
       let types =
        List.rev
         (List.map
-          (fun (_,ty,_) -> let _ = type_of_aux context ty in C.Decl ty) fl)
+          (fun (n,ty,_) -> 
+           let _ = type_of_aux context ty in Some (C.Name n,(C.Decl ty))) fl)
       in
        let len = List.length types in
         List.iter
@@ -1287,7 +1356,7 @@ and type_of_aux' metasenv context t =
            then
             begin
              (* let's control that the returned type is coinductive *)
-             match returns_a_coinductive ty with
+             match returns_a_coinductive context ty with
                 None ->
                  raise(NotWellTyped "CoFix: does not return a coinductive type")
               | Some uri ->
@@ -1306,10 +1375,10 @@ and type_of_aux' metasenv context t =
         let (_,ty,_) = List.nth fl i in
          ty
 
- and sort_of_prod (t1, t2) =
+ and sort_of_prod context (name,s) (t1, t2) =
   let module C = Cic in
    let t1' = CicReduction.whd context t1 in
-   let t2' = CicReduction.whd context t2 in
+   let t2' = CicReduction.whd ((Some (name,C.Decl s))::context) t2 in
    match (t1', t2') with
       (C.Sort s1, C.Sort s2)
         when (s2 = C.Prop or s2 = C.Set) -> (* different from Coq manual!!! *)
@@ -1343,7 +1412,7 @@ and type_of_aux' metasenv context t =
       | _ -> raise (NotWellTyped "Appl: wrong Prod-type")
     )
 
- and returns_a_coinductive ty =
+ and returns_a_coinductive context ty =
   let module C = Cic in
    match CicReduction.whd context ty with
       C.MutInd (uri,cookingsno,i) ->
@@ -1365,7 +1434,8 @@ and type_of_aux' metasenv context t =
            raise (WrongUriToMutualInductiveDefinitions
             (UriManager.string_of_uri uri))
         )
-    | C.Prod (_,_,de) -> returns_a_coinductive de
+    | C.Prod (n,so,de) ->
+       returns_a_coinductive ((Some (n,C.Decl so))::context) de
     | _ -> None
 
  in
@@ -1384,11 +1454,11 @@ and is_small context paramsno c =
  let rec is_small_aux context c =
   let module C = Cic in
    match CicReduction.whd context c with
-      C.Prod (_,so,de) ->
+      C.Prod (n,so,de) ->
        (*CSC: [] is an empty metasenv. Is it correct? *)
        let s = type_of_aux' [] context so in
         (s = C.Sort C.Prop || s = C.Sort C.Set) &&
-        is_small_aux ((C.Decl so)::context) de
+        is_small_aux ((Some (n,(C.Decl so)))::context) de
     | _ -> true (*CSC: we trust the type-checker *)
  in
   let (context',dx) = split_prods context paramsno c in