118
118
119
119
type projection_flags = {
120
120
pf_subclass : bool ;
121
+ pf_priority : int option ;
121
122
pf_canonical : bool ;
122
123
}
123
124
@@ -413,7 +414,7 @@ let build_proj env mib indsp primitive x rp lifted_fields ~poly paramdecls param
413
414
414
415
(* * [declare_projections] prepares the common context for all record
415
416
projections and then calls [build_proj] for each one. *)
416
- let declare_projections indsp univs ?( kind = Decls. StructureComponent ) inhabitant_id flags fieldimpls fields =
417
+ let declare_projections indsp univs ~ kind inhabitant_id flags fieldimpls fields =
417
418
let env = Global. env() in
418
419
let (mib,mip) = Global. lookup_inductive indsp in
419
420
let poly = Declareops. inductive_is_polymorphic mib in
@@ -528,7 +529,7 @@ let data_name id rdata =
528
529
The entry point is [definition_structure], which will match on the
529
530
declared [kind] and then either follow the regular record
530
531
declaration path to [declare_structure] or handle the record as a
531
- class declaration with [declare_class ].
532
+ definitional class declaration with [declare_class_constant ].
532
533
533
534
*)
534
535
@@ -538,8 +539,8 @@ let data_name id rdata =
538
539
- prepares and declares the corresponding record projections, mainly taken care of by
539
540
[declare_projections]
540
541
*)
541
- let declare_structure ~cumulative finite ~univs ~variances ~primitive_proj
542
- paramimpls params template ?( kind = Decls. StructureComponent ) ? name (record_data : Data.t list ) =
542
+ let declare_structure ~cumulative finite ~univs ~variances ~primitive_proj ~ proj_kind
543
+ paramimpls params template (record_data : Data.t list ) =
543
544
let nparams = List. length params in
544
545
let (univs, ubinders) = univs in
545
546
let poly, projunivs =
@@ -592,20 +593,34 @@ let declare_structure ~cumulative finite ~univs ~variances ~primitive_proj
592
593
let map i { Data. is_coercion; coers; rdata = { DataR. implfs; fields; _} ; inhabitant_id; id; _ } =
593
594
let rsp = (kn, i) in (* This is ind path of idstruc *)
594
595
let cstr = (rsp, 1 ) in
595
- let projections = declare_projections rsp (projunivs,ubinders) ~kind inhabitant_id coers implfs fields in
596
+ let projections = declare_projections rsp (projunivs,ubinders) ~kind: proj_kind inhabitant_id coers implfs fields in
596
597
let build = GlobRef. ConstructRef cstr in
597
598
let () = if is_coercion then ComCoercion. try_add_new_coercion build ~local: false ~poly in
598
599
let struc = Structure. make (Global. env () ) rsp projections in
599
600
let () = declare_structure_entry struc in
600
- rsp
601
+ GlobRef. IndRef rsp
601
602
in
602
- List. mapi map record_data
603
+ List. mapi map record_data, []
603
604
604
605
let implicits_of_context ctx =
605
606
List. map (fun name -> CAst. make (Some (name,true )))
606
607
(List. rev (Anonymous :: (List. map RelDecl. get_name ctx)))
607
608
608
- let build_class_constant ~univs ~rdata ~primitive_proj field implfs params paramimpls coers binder id proj_name =
609
+ (* declare definitional class (typeclasses that are not record) *)
610
+ let declare_class_constant ~univs paramimpls params data =
611
+ let id, rdata, coers, inhabitant_id = match data with
612
+ | [{ Data. id; rdata; is_coercion; coers; inhabitant_id }] ->
613
+ assert (not is_coercion); (* should be ensured by caller *)
614
+ let coers = List. map (fun { pf_subclass; pf_priority } -> if pf_subclass then Some { hint_priority = pf_priority; hint_pattern = None } else None ) coers in
615
+ id, rdata, coers, inhabitant_id
616
+ | _ -> assert false in (* should be ensured by caller *)
617
+ let implfs = rdata.DataR. implfs in
618
+ let field, binder, proj_name = match rdata.DataR. fields with
619
+ | [ LocalAssum ({binder_name= Name proj_name} as binder, field)
620
+ | LocalDef ({binder_name =Name proj_name } as binder , _ , field ) ] ->
621
+ let binder = {binder with binder_name= Name inhabitant_id} in
622
+ field, binder, proj_name
623
+ | _ -> assert false in (* should be ensured by caller *)
609
624
let class_body = it_mkLambda_or_LetIn field params in
610
625
let class_type = it_mkProd_or_LetIn rdata.DataR. arity params in
611
626
let class_entry =
@@ -641,44 +656,29 @@ let build_class_constant ~univs ~rdata ~primitive_proj field implfs params param
641
656
meth_info = sub;
642
657
meth_const = Some proj_cst;
643
658
} in
644
- [cref, [m]]
645
-
646
- let build_record_constant ~rdata ~univs ~variances ~cumulative ~template ~primitive_proj
647
- fields params paramimpls is_coercion coers id idbuild inhabitant_id =
648
- let record_data =
649
- { Data. id
650
- ; idbuild
651
- ; is_coercion = false
652
- (* to be replaced by the following line after deprecation phase
653
- (started in 8.16, c.f., https://github.com/coq/coq/pull/15802 ) *)
654
- (* ; is_coercion *)
655
- ; coers = List. map (fun _ -> { pf_subclass = false ; pf_canonical = true }) coers
656
- (* to be replaced by the following line after deprecation phase
657
- (started in 8.16, c.f., https://github.com/coq/coq/pull/15802 ) *)
658
- (* ; coers = List.map (fun c -> { pf_subclass = c <> None ; pf_canonical = true }) coers *)
659
- ; rdata
660
- ; inhabitant_id
661
- } in
662
- let inds = declare_structure ~cumulative Declarations. BiFinite ~univs ~variances ~primitive_proj paramimpls
663
- params template ~kind: Decls. Method ~name: [|inhabitant_id|] [record_data]
664
- in
665
- let map ind =
666
- let map decl b y = {
667
- meth_name = RelDecl. get_name decl;
668
- meth_info = b;
669
- meth_const = y;
670
- } in
671
- let l = List. map3 map (List. rev fields) coers (Structure. find_projections ind) in
672
- GlobRef. IndRef ind, l
673
- in
674
- List. map map inds
659
+ [cref], [m]
660
+
661
+ (* deprecated in 8.16, to be removed at the end of the deprecation phase
662
+ (c.f., https://github.com/coq/coq/pull/15802 ) *)
663
+ let warn_future_coercion_class_constructor =
664
+ CWarnings. create ~name: " future-coercion-class-constructor" ~category: " records"
665
+ ~default: CWarnings. AsError
666
+ Pp. (fun () -> str " 'Class >' currently does nothing. Use 'Class' instead." )
667
+
668
+ (* deprecated in 8.16, to be removed at the end of the deprecation phase
669
+ (c.f., https://github.com/coq/coq/pull/15802 ) *)
670
+ let warn_future_coercion_class_field =
671
+ CWarnings. create ~name: " future-coercion-class-field" ~category: " records" Pp. (fun () ->
672
+ str " A coercion will be introduced in future versions when using ':>' in 'Class' declarations. "
673
+ ++ str " Use '#[global] Existing Instance field.' instead if you don't want the coercion." )
675
674
676
675
(* * [declare_class] will prepare and declare a [Class]. This is done in
677
676
2 steps:
678
677
679
- 1. two markedly different paths are followed depending on whether the
680
- class declaration refers to a constant "definitional classes" or to
681
- a record, that is to say:
678
+ 1. two markedly different paths were followed depending on whether the
679
+ class declaration refers to a constant "definitional classes"
680
+ (with [declare_class_constant]) or to a record (with [declare_structure]),
681
+ that is to say:
682
682
683
683
Class foo := bar : T.
684
684
@@ -692,29 +692,34 @@ let build_record_constant ~rdata ~univs ~variances ~cumulative ~template ~primit
692
692
693
693
Class foo := { ... }.
694
694
695
- 2. declare the class, using the information from 1. in the form of [Classes.typeclass]
695
+ 2. now, declare the class, using the information ([inds] and [def]) from 1.
696
+ in the form of [Classes.typeclass]
696
697
697
698
*)
698
- let declare_class def ~cumulative ~univs ~variances ~primitive_proj id idbuild inhabitant_id paramimpls params
699
- rdata template ?(kind =Decls. StructureComponent ) is_coercion coers =
700
- let implfs =
701
- (* Make the class implicit in the projections, and the params if applicable. *)
702
- let impls = implicits_of_context params in
703
- List. map (fun x -> impls @ x) rdata.DataR. implfs
704
- in
705
- let rdata = { rdata with DataR. implfs } in
706
- let fields = rdata.DataR. fields in
707
- let data =
708
- match fields with
709
- | [ LocalAssum ({binder_name= Name proj_name} as binder, field)
710
- | LocalDef ({binder_name =Name proj_name } as binder , _ , field ) ] when def ->
711
- assert (not is_coercion); (* should be ensured by caller *)
712
- let binder = {binder with binder_name= Name inhabitant_id} in
713
- build_class_constant ~rdata ~univs ~primitive_proj field implfs params paramimpls coers binder id proj_name
699
+ let declare_class ~univs params inds def data =
700
+ let id, idbuild, rdata, is_coercion, coers, inhabitant_id = match data with
701
+ | [{ Data. id; idbuild; rdata; is_coercion; coers; inhabitant_id }] ->
702
+ if is_coercion then warn_future_coercion_class_constructor () ;
703
+ if List. exists (fun pf -> pf.pf_subclass) coers then
704
+ warn_future_coercion_class_field () ;
705
+ let coers = List. map (fun { pf_subclass; pf_priority } -> if pf_subclass then Some { hint_priority = pf_priority; hint_pattern = None } else None ) coers in
706
+ id, idbuild, rdata, is_coercion, coers, inhabitant_id
714
707
| _ ->
715
- build_record_constant ~rdata ~univs ~variances ~cumulative ~template ~primitive_proj
716
- fields params paramimpls is_coercion coers id idbuild inhabitant_id
708
+ CErrors. user_err (str " Mutual definitional classes are not handled." ) in
709
+ let fields = rdata.DataR. fields in
710
+ let map ind =
711
+ let map decl b y = {
712
+ meth_name = RelDecl. get_name decl;
713
+ meth_info = b;
714
+ meth_const = y;
715
+ } in
716
+ let l = match ind with
717
+ | GlobRef. IndRef ind ->
718
+ List. map3 map (List. rev fields) coers (Structure. find_projections ind)
719
+ | _ -> def in
720
+ ind, l
717
721
in
722
+ let data = List. map map inds in
718
723
let univs, params, fields =
719
724
match fst univs with
720
725
| UState. Polymorphic_entry uctx ->
@@ -739,9 +744,9 @@ let declare_class def ~cumulative ~univs ~variances ~primitive_proj id idbuild i
739
744
in
740
745
let env = Global. env () in
741
746
let sigma = Evd. from_env env in
742
- Classes. add_class env sigma k; impl
747
+ Classes. add_class env sigma k
743
748
in
744
- List. map map data
749
+ List. iter map data
745
750
746
751
let add_constant_class env sigma cst =
747
752
let ty, univs = Typeops. type_of_global_in_context env (GlobRef. ConstRef cst) in
@@ -855,69 +860,6 @@ let extract_record_data records =
855
860
in
856
861
ps, data
857
862
858
- (* deprecated in 8.16, to be removed at the end of the deprecation phase
859
- (c.f., https://github.com/coq/coq/pull/15802 ) *)
860
- let warn_future_coercion_class_constructor =
861
- CWarnings. create ~name: " future-coercion-class-constructor" ~category: " records"
862
- ~default: CWarnings. AsError
863
- Pp. (fun () -> str " 'Class >' currently does nothing. Use 'Class' instead." )
864
-
865
- (* deprecated in 8.16, to be removed at the end of the deprecation phase
866
- (c.f., https://github.com/coq/coq/pull/15802 ) *)
867
- let warn_future_coercion_class_field =
868
- CWarnings. create ~name: " future-coercion-class-field" ~category: " records" Pp. (fun () ->
869
- str " A coercion will be introduced in future versions when using ':>' in 'Class' declarations. "
870
- ++ str " Use '#[global] Existing Instance field.' instead if you don't want the coercion." )
871
-
872
- (* declaring structures, common data to refactor *)
873
- let class_structure ~cumulative ~template ~impargs ~univs ~params ~primitive_proj def records data =
874
- let { Ast. name; is_coercion; cfs; idbuild; default_inhabitant_id; _ }, rdata = match records, data with
875
- | [r], [d] -> r, d
876
- | _ , _ ->
877
- CErrors. user_err (str " Mutual definitional classes are not handled." )
878
- in
879
- if is_coercion then warn_future_coercion_class_constructor () ;
880
- if List. exists (function (_ , { rf_subclass = Vernacexpr. BackInstance ; _ } ) -> true | _ -> false ) cfs then
881
- warn_future_coercion_class_field () ;
882
- let coers = List. map (fun (_ , { rf_subclass; rf_priority } ) ->
883
- match rf_subclass with
884
- | Vernacexpr. BackInstance -> Some {hint_priority = rf_priority; hint_pattern = None }
885
- | Vernacexpr. NoInstance -> None )
886
- cfs
887
- in
888
- let inhabitant_id =
889
- match default_inhabitant_id with
890
- | None -> Namegen. next_ident_away name.CAst. v (Termops. vars_of_env (Global. env() ))
891
- | Some id -> id
892
- in
893
- declare_class def ~cumulative ~univs ~primitive_proj name.CAst. v idbuild inhabitant_id
894
- impargs params rdata template is_coercion coers
895
-
896
- let regular_structure ~cumulative ~template ~impargs ~univs ~variances ~params ~finite ~primitive_proj
897
- records data =
898
- let adjust_impls impls = impargs @ [CAst. make None ] @ impls in
899
- let data = List. map (fun ({ DataR. implfs; _ } as d ) -> { d with DataR. implfs = List. map adjust_impls implfs }) data in
900
- (* let map (min_univ, arity, fieldimpls, fields) { Ast.name; is_coercion; cfs; idbuild; _ } = *)
901
- let map rdata { Ast. name; is_coercion; cfs; idbuild; default_inhabitant_id; _ } =
902
- let coers = List. map (fun (_ , { rf_subclass ; rf_canonical } ) ->
903
- { pf_subclass =
904
- (match rf_subclass with Vernacexpr. BackInstance -> true | Vernacexpr. NoInstance -> false );
905
- pf_canonical = rf_canonical })
906
- cfs
907
- in
908
- let inhabitant_id =
909
- match default_inhabitant_id with
910
- | None -> data_name name.CAst. v rdata
911
- | Some n -> n
912
- in
913
- { Data. id = name.CAst. v; idbuild; rdata; is_coercion; coers; inhabitant_id }
914
- in
915
- let data = List. map2 map data records in
916
- let inds = declare_structure ~cumulative finite ~univs ~variances ~primitive_proj
917
- impargs params template data
918
- in
919
- List. map (fun ind -> GlobRef. IndRef ind) inds
920
-
921
863
(* * [fs] corresponds to fields and [ps] to parameters; [coers] is a
922
864
list telling if the corresponding fields must me declared as coercions
923
865
or subinstances. *)
@@ -936,17 +878,50 @@ let definition_structure udecl kind ~template ~cumulative ~poly ~primitive_proj
936
878
typecheck_params_and_fields (kind = Class true ) poly udecl ps data) ()
937
879
in
938
880
let template = template, auto_template in
939
- match kind with
940
- | Class def ->
941
- class_structure ~template ~impargs ~cumulative ~params ~univs ~variances ~primitive_proj
942
- def records data
943
- | Inductive_kw | CoInductive | Variant | Record | Structure ->
944
- regular_structure ~cumulative ~template ~impargs ~univs ~variances ~params ~finite ~primitive_proj
945
- records data
881
+ let is_class = match kind with Class def -> Some def
882
+ | Inductive_kw | CoInductive | Variant | Record | Structure -> None in
883
+ let adjust_impls impls = match is_class with
884
+ | None -> impargs @ [CAst. make None ] @ impls
885
+ | Some _ -> implicits_of_context params @ impls in
886
+ let data = List. map DataR. (fun d -> { d with implfs = List. map adjust_impls d.implfs }) data in
887
+ let map rdata { Ast. name; is_coercion; cfs; idbuild; default_inhabitant_id; _ } =
888
+ let coers = List. map (fun (_ , { rf_subclass; rf_priority; rf_canonical } ) ->
889
+ { pf_subclass = Vernacexpr. (match rf_subclass with BackInstance -> true | NoInstance -> false )
890
+ ; pf_priority = rf_priority; pf_canonical = rf_canonical })
891
+ cfs
892
+ in
893
+ let inhabitant_id =
894
+ match default_inhabitant_id, is_class with
895
+ | None , Some _ -> Namegen. next_ident_away name.CAst. v (Termops. vars_of_env (Global. env() ))
896
+ | None , None -> data_name name.CAst. v rdata
897
+ | Some id , _ -> id
898
+ in
899
+ { Data. id = name.CAst. v; idbuild; rdata; is_coercion; coers; inhabitant_id }
900
+ in
901
+ let data = List. map2 map data records in
902
+ let inds, def = match is_class with
903
+ | Some true -> declare_class_constant ~univs impargs params data
904
+ | Some false | None ->
905
+ let proj_kind =
906
+ Decls. (match is_class with None -> StructureComponent | _ -> Method ) in
907
+ (* remove the following block after deprecation phase
908
+ (started in 8.16, c.f., https://github.com/coq/coq/pull/15802 ) *)
909
+ let data' = if is_class = None then data else
910
+ List. map (fun d ->
911
+ { d with
912
+ Data. is_coercion = false
913
+ ; coers = List. map (fun _ -> { pf_subclass = false ; pf_priority = None ; pf_canonical = true }) d.Data. coers
914
+ }) data in
915
+ declare_structure ~cumulative finite ~univs ~variances ~primitive_proj
916
+ ~proj_kind impargs params template data'
917
+ in
918
+ if is_class <> None then declare_class ~univs params inds def data;
919
+ inds
946
920
947
921
module Internal = struct
948
922
type nonrec projection_flags = projection_flags = {
949
923
pf_subclass : bool ;
924
+ pf_priority : int option ;
950
925
pf_canonical : bool ;
951
926
}
952
927
let declare_projections = declare_projections
0 commit comments