~ubuntu-branches/ubuntu/wily/coq-doc/wily

« back to all changes in this revision

Viewing changes to checker/subtyping.ml

  • Committer: Bazaar Package Importer
  • Author(s): Stéphane Glondu, Stéphane Glondu, Samuel Mimram
  • Date: 2010-01-07 22:50:39 UTC
  • mfrom: (1.2.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20100107225039-n3cq82589u0qt0s2
Tags: 8.2pl1-1
[ Stéphane Glondu ]
* New upstream release (Closes: #563669)
  - remove patches
* Packaging overhaul:
  - use git, advertise it in Vcs-* fields of debian/control
  - use debhelper 7 and dh with override
  - use source format 3.0 (quilt)
* debian/control:
  - set Maintainer to d-o-m, set Uploaders to Sam and myself
  - add Homepage field
  - bump Standards-Version to 3.8.3
* Register PDF documentation into doc-base
* Add debian/watch
* Update debian/copyright

[ Samuel Mimram ]
* Change coq-doc's description to mention that it provides documentation in
  pdf format, not postscript, closes: #543545.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
(************************************************************************)
 
2
(*  v      *   The Coq Proof Assistant  /  The Coq Development Team     *)
 
3
(* <O___,, * CNRS-Ecole Polytechnique-INRIA Futurs-Universite Paris Sud *)
 
4
(*   \VV/  **************************************************************)
 
5
(*    //   *      This file is distributed under the terms of the       *)
 
6
(*         *       GNU Lesser General Public License Version 2.1        *)
 
7
(************************************************************************)
 
8
 
 
9
(*i $Id: subtyping.ml 10664 2008-03-14 11:27:37Z soubiran $ i*)
 
10
 
 
11
(*i*)
 
12
open Util
 
13
open Names
 
14
open Univ
 
15
open Term
 
16
open Declarations
 
17
open Environ
 
18
open Reduction
 
19
open Inductive
 
20
open Modops
 
21
(*i*)
 
22
open Pp      
 
23
 
 
24
 
 
25
 
 
26
(* This local type is used to subtype a constant with a constructor or
 
27
   an inductive type. It can also be useful to allow reorderings in
 
28
   inductive types *)
 
29
type namedobject = 
 
30
  | Constant of constant_body
 
31
  | IndType of inductive * mutual_inductive_body
 
32
  | IndConstr of constructor * mutual_inductive_body
 
33
  | Module of module_body
 
34
  | Modtype of module_type_body
 
35
  | Alias of module_path * struct_expr_body option
 
36
 
 
37
(* adds above information about one mutual inductive: all types and
 
38
   constructors *)
 
39
 
 
40
let add_nameobjects_of_mib ln mib map = 
 
41
  let add_nameobjects_of_one j oib map =
 
42
    let ip = (ln,j) in
 
43
    let map = 
 
44
      array_fold_right_i 
 
45
      (fun i id map ->
 
46
        Labmap.add (label_of_id id) (IndConstr((ip,i+1), mib)) map)
 
47
      oib.mind_consnames
 
48
      map
 
49
    in
 
50
      Labmap.add (label_of_id oib.mind_typename) (IndType (ip, mib)) map
 
51
  in
 
52
    array_fold_right_i add_nameobjects_of_one mib.mind_packets map
 
53
 
 
54
 
 
55
(* creates namedobject map for the whole signature *)
 
56
 
 
57
let make_label_map mp list = 
 
58
  let add_one (l,e) map = 
 
59
   let add_map obj = Labmap.add l obj map in
 
60
   match e with
 
61
    | SFBconst cb -> add_map (Constant cb)
 
62
    | SFBmind mib ->
 
63
       add_nameobjects_of_mib (make_kn mp empty_dirpath l) mib map
 
64
    | SFBmodule mb -> add_map (Module mb)
 
65
    | SFBmodtype mtb -> add_map (Modtype mtb)
 
66
    | SFBalias (mp,t,cst) -> add_map (Alias (mp,t))
 
67
  in
 
68
    List.fold_right add_one list Labmap.empty
 
69
 
 
70
let check_conv_error error f env a1 a2 =
 
71
  try
 
72
    f env a1 a2
 
73
  with
 
74
      NotConvertible -> error ()
 
75
 
 
76
(* for now we do not allow reorderings *)
 
77
let check_inductive env msid1 l info1 mib2 spec2 = 
 
78
  let kn = make_kn (MPself msid1) empty_dirpath l in
 
79
  let error () = error_not_match l spec2 in
 
80
  let check_conv f = check_conv_error error f in
 
81
  let mib1 = 
 
82
    match info1 with
 
83
      | IndType ((_,0), mib) -> mib
 
84
      | _ -> error ()
 
85
  in
 
86
  let check_inductive_type env t1 t2 =
 
87
 
 
88
    (* Due to sort-polymorphism in inductive types, the conclusions of
 
89
       t1 and t2, if in Type, are generated as the least upper bounds
 
90
       of the types of the constructors. 
 
91
 
 
92
       By monotonicity of the infered l.u.b.  wrt subtyping (i.e.  if X:U
 
93
       |- T(X):s and |- M:U' and U'<=U then infer_type(T(M))<=s), each
 
94
       universe in the conclusion of t1 has an bounding universe in
 
95
       the conclusion of t2, so that we don't need to check the
 
96
       subtyping of the conclusions of t1 and t2.
 
97
 
 
98
       Even if we'd like to recheck it, the inference of constraints
 
99
       is not designed to deal with algebraic constraints of the form
 
100
       max-univ(u1..un) <= max-univ(u'1..u'n), so that it is not easy
 
101
       to recheck it (in short, we would need the actual graph of
 
102
       constraints as input while type checking is currently designed
 
103
       to output a set of constraints instead) *)
 
104
 
 
105
    (* So we cheat and replace the subtyping problem on algebraic
 
106
       constraints of the form max-univ(u1..un) <= max-univ(u'1..u'n)
 
107
       (that we know are necessary true) by trivial constraints that
 
108
       the constraint generator knows how to deal with *)
 
109
 
 
110
    let (ctx1,s1) = dest_arity env t1 in
 
111
    let (ctx2,s2) = dest_arity env t2 in
 
112
    let s1,s2 =
 
113
      match s1, s2 with
 
114
      | Type _, Type _ -> (* shortcut here *) Prop Null, Prop Null
 
115
      | (Prop _, Type _) | (Type _,Prop _) -> error ()
 
116
      | _ -> (s1, s2) in
 
117
    check_conv conv_leq env 
 
118
      (mkArity (ctx1,s1)) (mkArity (ctx2,s2))
 
119
  in
 
120
 
 
121
  let check_packet p1 p2 =
 
122
    let check f = if f p1 <> f p2 then error () in
 
123
      check (fun p -> p.mind_consnames);
 
124
      check (fun p -> p.mind_typename);
 
125
      (* nf_lc later *)
 
126
      (* nf_arity later *)
 
127
      (* user_lc ignored *)
 
128
      (* user_arity ignored *)
 
129
      check (fun p -> p.mind_nrealargs);
 
130
      (* kelim ignored *)
 
131
      (* listrec ignored *)
 
132
      (* finite done *)
 
133
      (* nparams done *)
 
134
      (* params_ctxt done because part of the inductive types *)
 
135
      (* Don't check the sort of the type if polymorphic *)
 
136
      check_inductive_type env
 
137
        (type_of_inductive env (mib1,p1)) (type_of_inductive env (mib2,p2))
 
138
  in
 
139
  let check_cons_types i p1 p2 =
 
140
    array_iter2 (check_conv conv env)
 
141
      (arities_of_specif kn (mib1,p1))
 
142
      (arities_of_specif kn (mib2,p2))
 
143
  in
 
144
  let check f = if f mib1 <> f mib2 then error () in
 
145
  check (fun mib -> mib.mind_finite);
 
146
  check (fun mib -> mib.mind_ntypes);
 
147
  assert (mib1.mind_hyps=[] && mib2.mind_hyps=[]);
 
148
  assert (Array.length mib1.mind_packets >= 1 
 
149
            && Array.length mib2.mind_packets >= 1);
 
150
 
 
151
  (* Check that the expected numbers of uniform parameters are the same *)
 
152
  (* No need to check the contexts of parameters: it is checked *)
 
153
  (* at the time of checking the inductive arities in check_packet. *)
 
154
  (* Notice that we don't expect the local definitions to match: only *)
 
155
  (* the inductive types and constructors types have to be convertible *)
 
156
  check (fun mib -> mib.mind_nparams);
 
157
 
 
158
  begin 
 
159
    match mib2.mind_equiv with
 
160
      | None -> ()
 
161
      | Some kn2' -> 
 
162
          let kn2 = scrape_mind env kn2' in
 
163
          let kn1 = match mib1.mind_equiv with
 
164
              None -> kn
 
165
            | Some kn1' -> scrape_mind env kn1'
 
166
          in
 
167
            if kn1 <> kn2 then error ()
 
168
  end;
 
169
  (* we check that records and their field names are preserved. *)
 
170
  check (fun mib -> mib.mind_record);
 
171
  if mib1.mind_record then begin 
 
172
    let rec names_prod_letin t = match t with 
 
173
      | Prod(n,_,t) -> n::(names_prod_letin t)
 
174
      | LetIn(n,_,_,t) -> n::(names_prod_letin t)
 
175
      | Cast(t,_,_) -> names_prod_letin t
 
176
      | _ -> []
 
177
    in 
 
178
    assert (Array.length mib1.mind_packets = 1);
 
179
    assert (Array.length mib2.mind_packets = 1);
 
180
    assert (Array.length mib1.mind_packets.(0).mind_user_lc = 1); 
 
181
    assert (Array.length mib2.mind_packets.(0).mind_user_lc = 1); 
 
182
    check (fun mib -> names_prod_letin mib.mind_packets.(0).mind_user_lc.(0));
 
183
  end;
 
184
  (* we first check simple things *)
 
185
  array_iter2 check_packet mib1.mind_packets mib2.mind_packets;
 
186
  (* and constructor types in the end *)
 
187
  let _ = array_map2_i check_cons_types mib1.mind_packets mib2.mind_packets
 
188
  in ()
 
189
 
 
190
let check_constant env msid1 l info1 cb2 spec2 = 
 
191
  let error () = error_not_match l spec2 in
 
192
  let check_conv f = check_conv_error error f in
 
193
  let check_type env t1 t2 = 
 
194
 
 
195
    (* If the type of a constant is generated, it may mention
 
196
       non-variable algebraic universes that the general conversion
 
197
       algorithm is not ready to handle. Anyway, generated types of
 
198
       constants are functions of the body of the constant. If the
 
199
       bodies are the same in environments that are subtypes one of
 
200
       the other, the types are subtypes too (i.e. if Gamma <= Gamma',
 
201
       Gamma |- A |> T, Gamma |- A' |> T' and Gamma |- A=A' then T <= T').
 
202
       Hence they don't have to be checked again *)
 
203
 
 
204
    let t1,t2 = 
 
205
      if isArity t2 then
 
206
        let (ctx2,s2) = destArity t2 in
 
207
        match s2 with
 
208
        | Type v when not (is_univ_variable v) ->
 
209
          (* The type in the interface is inferred and is made of algebraic
 
210
             universes *)
 
211
          begin try
 
212
            let (ctx1,s1) = dest_arity env t1 in
 
213
            match s1 with
 
214
            | Type u when not (is_univ_variable u) ->
 
215
              (* Both types are inferred, no need to recheck them. We
 
216
                 cheat and collapse the types to Prop *)
 
217
                mkArity (ctx1,Prop Null), mkArity (ctx2,Prop Null)
 
218
            | Prop _ ->
 
219
              (* The type in the interface is inferred, it may be the case
 
220
                 that the type in the implementation is smaller because
 
221
                 the body is more reduced. We safely collapse the upper
 
222
                 type to Prop *)
 
223
                mkArity (ctx1,Prop Null), mkArity (ctx2,Prop Null)
 
224
            | Type _ ->
 
225
              (* The type in the interface is inferred and the type in the
 
226
                 implementation is not inferred or is inferred but from a
 
227
                 more reduced body so that it is just a variable. Since
 
228
                 constraints of the form "univ <= max(...)" are not
 
229
                 expressible in the system of algebraic universes: we fail
 
230
                 (the user has to use an explicit type in the interface *)
 
231
                error ()
 
232
          with UserError _ (* "not an arity" *) ->
 
233
            error () end
 
234
        | _ -> t1,t2
 
235
      else
 
236
        (t1,t2) in
 
237
    check_conv conv_leq env t1 t2
 
238
  in
 
239
 
 
240
  match info1 with
 
241
   | Constant cb1 ->
 
242
      assert (cb1.const_hyps=[] && cb2.const_hyps=[]) ;
 
243
      (*Start by checking types*)
 
244
      let typ1 = Typeops.type_of_constant_type env cb1.const_type in
 
245
      let typ2 = Typeops.type_of_constant_type env cb2.const_type in
 
246
      check_type env typ1 typ2;
 
247
      let con = make_con (MPself msid1) empty_dirpath l in
 
248
      (match cb2 with
 
249
        | {const_body=Some lc2;const_opaque=false} ->
 
250
            let c2 = force_constr lc2 in
 
251
            let c1 = match cb1.const_body with
 
252
              | Some lc1 -> force_constr lc1
 
253
              | None -> Const con
 
254
            in
 
255
               check_conv conv env c1 c2
 
256
        | _ -> ())
 
257
   | IndType ((kn,i),mind1) ->
 
258
      ignore (Util.error (
 
259
       "The kernel does not recognize yet that a parameter can be " ^
 
260
       "instantiated by an inductive type. Hint: you can rename the " ^
 
261
       "inductive type and give a definition to map the old name to the new " ^
 
262
       "name."));
 
263
      assert (mind1.mind_hyps=[] && cb2.const_hyps=[]) ;
 
264
      if cb2.const_body <> None then error () ;
 
265
      let arity1 = type_of_inductive env (mind1,mind1.mind_packets.(i)) in
 
266
      let typ2 = Typeops.type_of_constant_type env cb2.const_type in
 
267
       check_conv conv_leq env arity1 typ2
 
268
   | IndConstr (((kn,i),j) as cstr,mind1) ->
 
269
      ignore (Util.error (
 
270
       "The kernel does not recognize yet that a parameter can be " ^
 
271
       "instantiated by a constructor. Hint: you can rename the " ^
 
272
       "constructor and give a definition to map the old name to the new " ^
 
273
       "name."));
 
274
      assert (mind1.mind_hyps=[] && cb2.const_hyps=[]) ;
 
275
      if cb2.const_body <> None then error () ;
 
276
      let ty1 = type_of_constructor cstr (mind1,mind1.mind_packets.(i)) in
 
277
      let ty2 = Typeops.type_of_constant_type env cb2.const_type in
 
278
       check_conv conv env ty1 ty2
 
279
   | _ -> error ()
 
280
 
 
281
let rec check_modules env msid1 l msb1 msb2 =
 
282
  let mp = (MPdot(MPself msid1,l)) in
 
283
  let mty1 = module_type_of_module (Some mp) msb1 in
 
284
  let mty2 =  module_type_of_module None msb2 in
 
285
  check_modtypes env mty1 mty2 false
 
286
        
 
287
 
 
288
and check_signatures env (msid1,sig1) alias (msid2,sig2') = 
 
289
  let mp1 = MPself msid1 in
 
290
  let env = add_signature mp1 sig1 env in 
 
291
  let alias = update_subst_alias alias (map_msid msid2 mp1) in
 
292
  let sig2 = subst_structure alias sig2' in
 
293
  let sig2 = subst_signature_msid msid2 mp1 sig2 in
 
294
  let map1 = make_label_map mp1 sig1 in
 
295
  let check_one_body (l,spec2) = 
 
296
    let info1 = 
 
297
      try 
 
298
        Labmap.find l map1 
 
299
      with 
 
300
          Not_found -> error_no_such_label_sub l msid1 msid2
 
301
    in
 
302
      match spec2 with
 
303
        | SFBconst cb2 ->
 
304
            check_constant env msid1 l info1 cb2 spec2
 
305
        | SFBmind mib2 -> 
 
306
            check_inductive env msid1 l info1 mib2 spec2
 
307
        | SFBmodule msb2 ->  
 
308
            begin
 
309
              match info1 with
 
310
                | Module msb -> check_modules env msid1 l msb msb2
 
311
                | Alias (mp,typ_opt) ->let msb = 
 
312
                    {mod_expr = Some (SEBident mp);
 
313
                     mod_type = typ_opt;
 
314
                     mod_constraints = Constraint.empty;
 
315
                     mod_alias = (lookup_modtype mp env).typ_alias;
 
316
                     mod_retroknowledge = []} in
 
317
                    check_modules env msid1 l msb msb2
 
318
                | _ -> error_not_match l spec2
 
319
            end
 
320
        | SFBalias (mp,typ_opt,_) ->
 
321
            begin       
 
322
              match info1 with
 
323
                | Alias (mp1,_) -> check_modpath_equiv env mp mp1
 
324
                | Module msb -> 
 
325
                    let msb1 = 
 
326
                      {mod_expr = Some (SEBident mp);
 
327
                       mod_type = typ_opt;
 
328
                       mod_constraints = Constraint.empty;
 
329
                       mod_alias = (lookup_modtype mp env).typ_alias;
 
330
                       mod_retroknowledge = []} in
 
331
                        check_modules env msid1 l msb msb1
 
332
                | _ -> error_not_match l spec2
 
333
            end
 
334
        | SFBmodtype mtb2 ->
 
335
            let mtb1 = 
 
336
              match info1 with
 
337
                | Modtype mtb -> mtb
 
338
                | _ -> error_not_match l spec2
 
339
            in
 
340
              check_modtypes env mtb1 mtb2 true
 
341
  in
 
342
    List.iter check_one_body sig2
 
343
 
 
344
and check_modtypes env mtb1 mtb2 equiv = 
 
345
  if mtb1==mtb2 then () else (* just in case  :) *)
 
346
  let mtb1',mtb2'=
 
347
    (match mtb1.typ_strength with
 
348
         None -> eval_struct env mtb1.typ_expr,
 
349
           eval_struct env mtb2.typ_expr
 
350
       | Some mp -> strengthen  env mtb1.typ_expr mp,
 
351
           eval_struct env mtb2.typ_expr) in
 
352
      let rec check_structure env str1 str2 equiv = 
 
353
        match str1, str2 with
 
354
          | SEBstruct (msid1,list1), 
 
355
            SEBstruct (msid2,list2) -> 
 
356
              check_signatures env
 
357
                (msid1,list1) mtb1.typ_alias (msid2,list2);
 
358
              if equiv then
 
359
                check_signatures env 
 
360
                  (msid2,list2) mtb2.typ_alias  (msid1,list1) 
 
361
          | SEBfunctor (arg_id1,arg_t1,body_t1), 
 
362
              SEBfunctor (arg_id2,arg_t2,body_t2) ->
 
363
              check_modtypes env arg_t2 arg_t1 equiv;
 
364
                (* contravariant *)
 
365
              let env = 
 
366
                add_module (MPbound arg_id2) (module_body_of_type arg_t2) env 
 
367
              in
 
368
              let body_t1' = 
 
369
                (* since we are just checking well-typedness we do not need
 
370
                   to expand any constant. Hence the identity resolver. *)
 
371
                subst_struct_expr
 
372
                  (map_mbid arg_id1 (MPbound arg_id2))
 
373
                  body_t1
 
374
              in
 
375
                check_structure env (eval_struct env body_t1')
 
376
                  (eval_struct env body_t2) equiv
 
377
          | _ , _ -> error_incompatible_modtypes mtb1 mtb2
 
378
      in 
 
379
     if mtb1'== mtb2' then ()
 
380
     else check_structure env mtb1' mtb2' equiv
 
381
 
 
382
let check_subtypes env sup super = 
 
383
  (*if sup<>super then*)
 
384
  check_modtypes env sup super false
 
385
          
 
386
let check_equal env sup super = 
 
387
  (*if sup<>super then*)
 
388
  check_modtypes env sup super true