Skip to content

Commit

Permalink
Merge PR coq#20058: Ensure at runtime that the modpath is synced with…
Browse files Browse the repository at this point in the history
… module bodies and types

Reviewed-by: SkySkimmer
Co-authored-by: SkySkimmer <[email protected]>
  • Loading branch information
coqbot-app[bot] and SkySkimmer authored Jan 15, 2025
2 parents c788be7 + eaa8bc9 commit 1d1d239
Show file tree
Hide file tree
Showing 8 changed files with 85 additions and 58 deletions.
20 changes: 11 additions & 9 deletions checker/mod_checking.ml
Original file line number Diff line number Diff line change
Expand Up @@ -235,17 +235,18 @@ let rec check_mexpression env opac sign mbtyp mp_mse res = match sign with
let rec check_module env opac mp mb opacify =
Flags.if_verbose Feedback.msg_notice (str " checking module: " ++ str (ModPath.to_string mp));
let env = Modops.add_retroknowledge (mod_retroknowledge mb) env in
let () = assert (ModPath.equal (mod_mp mb) mp) in
let opac =
check_signature env opac (mod_type mb) (mod_mp mb) (mod_delta mb) opacify
check_signature env opac (mod_type mb) mp (mod_delta mb) opacify
in
let optsign, opac = match Mod_declarations.mod_expr mb with
| Struct sign_struct ->
let opacify = collect_constants_without_body (mod_type mb) (mod_mp mb) opacify in
let opacify = collect_constants_without_body (mod_type mb) mp opacify in
(* TODO: a bit wasteful, we recheck the types of parameters twice *)
let sign_struct = Modops.annotate_struct_body sign_struct (mod_type mb) in
let opac = check_signature env opac sign_struct (mod_mp mb) (mod_delta mb) opacify in
let opac = check_signature env opac sign_struct mp (mod_delta mb) opacify in
Some (sign_struct, mod_delta mb), opac
| Algebraic me -> Some (check_mexpression env opac me (mod_type mb) (mod_mp mb) (mod_delta mb)), opac
| Algebraic me -> Some (check_mexpression env opac me (mod_type mb) mp (mod_delta mb)), opac
| Abstract|FullStruct -> None, opac
in
let () = match optsign with
Expand All @@ -260,10 +261,11 @@ let rec check_module env opac mp mb opacify =
in
opac

and check_module_type env mty =
Flags.if_verbose Feedback.msg_notice (str " checking module type: " ++ str (ModPath.to_string @@ mod_mp mty));
and check_module_type env mp mty =
let () = assert (ModPath.equal (mod_mp mty) mp) in
Flags.if_verbose Feedback.msg_notice (str " checking module type: " ++ str (ModPath.to_string @@ mp));
let _ : _ Cmap.t =
check_signature env Cmap.empty (mod_type mty) (mod_mp mty) (mod_delta mty) Cset.empty in
check_signature env Cmap.empty (mod_type mty) mp (mod_delta mty) Cset.empty in
()

and check_structure_field env opac mp lab res opacify = function
Expand All @@ -278,15 +280,15 @@ and check_structure_field env opac mp lab res opacify = function
let opac = check_module env opac (MPdot(mp,lab)) msb opacify in
Modops.add_module msb env, opac
| SFBmodtype mty ->
check_module_type env mty;
let () = check_module_type env (MPdot (mp, lab)) mty in
add_modtype mty env, opac
| SFBrules rrb ->
check_rewrite_rules_body env lab rrb;
Environ.add_rewrite_rules rrb.rewrules_rules env, opac

and check_signature env opac sign mp_mse res opacify = match sign with
| MoreFunctor (arg_id, mtb, body) ->
check_module_type env mtb;
let () = check_module_type env (MPbound arg_id) mtb in
let env' = Modops.add_module_type (MPbound arg_id) mtb env in
let opac = check_signature env' opac body mp_mse res Cset.empty in
opac
Expand Down
1 change: 1 addition & 0 deletions kernel/mod_declarations.ml
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ let module_type_of_module mb =
mod_retroknowledge = ModTypeNul; }

let module_body_of_type mp mtb =
let () = assert (ModPath.equal mp mtb.mod_mp) in
{ mtb with mod_expr = ModBodyVal Abstract; mod_mp = mp;
mod_retroknowledge = ModBodyVal []; }

Expand Down
3 changes: 2 additions & 1 deletion kernel/mod_typing.ml
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,8 @@ let rec translate_mse (cst, ustate) (vm, vmstate) env mpo inl = function
| Some mp -> strengthen_and_subst_module_body (lookup_module mp1 env) mp false
| None ->
let mt = lookup_modtype mp1 env in
module_body_of_type (mod_mp mt) mt
let () = assert (ModPath.equal mp1 (mod_mp mt)) in
module_body_of_type mp1 mt
in
mod_type mb, me, mod_delta mb, cst, vm
| MEapply (fe,mp1) ->
Expand Down
31 changes: 18 additions & 13 deletions kernel/modops.ml
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,8 @@ let strengthen_const mp_from l cb resolver =
const_body_code = Some (Vmbytegen.compile_alias con) }

let rec strengthen_module mp_from mp_to mb =
if mp_in_delta (mod_mp mb) (mod_delta mb) then mb
let () = assert (ModPath.equal mp_from (mod_mp mb)) in
if mp_in_delta mp_from (mod_delta mb) then mb
else match mod_type mb with
| NoFunctor struc ->
let reso,struc' = strengthen_signature mp_from struc mp_to (mod_delta mb) in
Expand Down Expand Up @@ -250,21 +251,23 @@ and strengthen_signature mp_from struc mp_to reso = match struc with
reso',item::rest'

let strengthen mtb mp =
let () = assert (ModPath.equal mp (mod_mp mtb)) in
(* Has mtb already been strengthened ? *)
if mp_in_delta (mod_mp mtb) (mod_delta mtb) then mtb
if mp_in_delta mp (mod_delta mtb) then mtb
else match mod_type mtb with
| NoFunctor struc ->
let reso',struc' = strengthen_signature (mod_mp mtb) struc mp (mod_delta mtb) in
let reso' = add_delta_resolver (mod_delta mtb) (add_mp_delta_resolver (mod_mp mtb) mp reso') in
let reso',struc' = strengthen_signature mp struc mp (mod_delta mtb) in
let reso' = add_delta_resolver (mod_delta mtb) (add_mp_delta_resolver mp mp reso') in
strengthen_module_type struc' reso' mtb
| MoreFunctor _ -> mtb

(** {6 Strengthening a module for [Module M := M'] or [Include M] } *)

let rec strengthen_and_subst_module mb subst mp_from mp_to =
let () = assert (ModPath.equal mp_from (mod_mp mb)) in
match mod_type mb with
| NoFunctor struc ->
let mb_is_an_alias = mp_in_delta (mod_mp mb) (mod_delta mb) in
let mb_is_an_alias = mp_in_delta mp_from (mod_delta mb) in
if mb_is_an_alias then subst_module subst do_delta_dom mb
else
let reso',struc' =
Expand All @@ -274,7 +277,7 @@ let rec strengthen_and_subst_module mb subst mp_from mp_to =
let reso' = add_mp_delta_resolver mp_to mp_from reso' in
strengthen_module_body ~src:mp_from ~dst:(Some mp_to) (NoFunctor struc') reso' mb
| MoreFunctor _ ->
let subst = add_mp (mod_mp mb) mp_to empty_delta_resolver subst in
let subst = add_mp mp_from mp_to empty_delta_resolver subst in
subst_module subst do_delta_dom mb

and strengthen_and_subst_struct struc subst mp_from mp_to alias incl reso =
Expand Down Expand Up @@ -369,24 +372,26 @@ and strengthen_and_subst_struct struc subst mp_from mp_to alias incl reso =

let strengthen_and_subst_module_body mb mp include_b = match mod_type mb with
| NoFunctor struc ->
let mb_is_an_alias = mp_in_delta (mod_mp mb) (mod_delta mb) in
let mp_from = mod_mp mb in
let mb_is_an_alias = mp_in_delta mp_from (mod_delta mb) in
(* if mb.mod_mp is an alias then the strengthening is useless
(i.e. it is already done)*)
let mp_alias = mp_of_delta (mod_delta mb) (mod_mp mb) in
let subst_resolver = map_mp (mod_mp mb) mp empty_delta_resolver in
let mp_alias = mp_of_delta (mod_delta mb) mp_from in
let subst_resolver = map_mp mp_from mp empty_delta_resolver in
let new_resolver =
add_mp_delta_resolver mp mp_alias
(subst_dom_delta_resolver subst_resolver (mod_delta mb))
in
let subst = map_mp (mod_mp mb) mp new_resolver in
let subst = map_mp mp_from mp new_resolver in
let reso',struc' =
strengthen_and_subst_struct struc subst
(mod_mp mb) mp mb_is_an_alias include_b (mod_delta mb)
mp_from mp mb_is_an_alias include_b (mod_delta mb)
in
let reso' = if include_b then reso' else add_delta_resolver new_resolver reso' in
strengthen_module_body ~src:(mod_mp mb) ~dst:(Some mp) (NoFunctor struc') reso' mb
strengthen_module_body ~src:mp_from ~dst:(Some mp) (NoFunctor struc') reso' mb
| MoreFunctor _ ->
let subst = map_mp (mod_mp mb) mp empty_delta_resolver in
let mp_from = mod_mp mb in
let subst = map_mp mp_from mp empty_delta_resolver in
subst_module subst do_delta_dom_codom mb

let subst_modtype_signature_and_resolver mp_from mp_to sign reso =
Expand Down
6 changes: 4 additions & 2 deletions kernel/nativelibrary.ml
Original file line number Diff line number Diff line change
Expand Up @@ -45,15 +45,17 @@ and translate_field mp env acc (l,x) =
Pp.str msg));
compile_rewrite_rules env l acc rrb
| SFBmodule md ->
let mp = mod_mp md in
let mp = MPdot (mp, l) in
let () = assert (ModPath.equal mp (mod_mp md)) in
(debug_native_compiler (fun () ->
let msg =
Printf.sprintf "Compiling module %s..." (ModPath.to_string mp)
in
Pp.str msg));
translate_mod mp env (mod_type md) acc
| SFBmodtype mdtyp ->
let mp = mod_mp mdtyp in
let mp = MPdot (mp, l) in
let () = assert (ModPath.equal mp (mod_mp mdtyp)) in
(debug_native_compiler (fun () ->
let msg =
Printf.sprintf "Compiling module type %s..." (ModPath.to_string mp)
Expand Down
57 changes: 33 additions & 24 deletions kernel/subtyping.ml
Original file line number Diff line number Diff line change
Expand Up @@ -264,10 +264,12 @@ let check_constant (cst, ustate) trace env l info1 cb2 subst1 subst2 =
Anyway [check_conv] will handle that afterwards. *)
check_conv NotConvertibleBodyField cst poly CONV env c1 c2))

let rec check_modules state trace env msb1 msb2 subst1 subst2 =
let rec check_modules state trace env mp1 msb1 mp2 msb2 subst1 subst2 =
let () = assert (ModPath.equal mp1 (mod_mp msb1)) in
let () = assert (ModPath.equal mp2 (mod_mp msb2)) in
let mty1 = module_type_of_module msb1 in
let mty2 = module_type_of_module msb2 in
check_modtypes state trace env mty1 mty2 subst1 subst2 false
let mty2 = module_type_of_module msb2 in
check_modtypes state trace env mp1 mty1 mp2 mty2 subst1 subst2 false

and check_signatures (cst, ustate) trace env mp1 sig1 mp2 sig2 subst1 subst2 reso1 reso2 =
let map1 = make_labmap mp1 sig1 in
Expand All @@ -282,66 +284,73 @@ and check_signatures (cst, ustate) trace env mp1 sig1 mp2 sig2 subst1 subst2 res
| SFBrules _ ->
error_signature_mismatch trace l NoRewriteRulesSubtyping
| SFBmodule msb2 ->
let mp1' = MPdot (mp1, l) in
let mp2' = MPdot (mp2, l) in
begin match get_mod mp1 map1 l with
| Module msb -> check_modules (cst, ustate) (Submodule l :: trace) env msb msb2 subst1 subst2
| Module msb1 -> check_modules (cst, ustate) (Submodule l :: trace) env mp1' msb1 mp2' msb2 subst1 subst2
| _ -> error_signature_mismatch trace l ModuleFieldExpected
end
| SFBmodtype mtb2 ->
let mtb1 = match get_mod mp1 map1 l with
| Modtype mtb -> mtb
| _ -> error_signature_mismatch trace l ModuleTypeFieldExpected
in
let env =
add_module_type (mod_mp mtb2) mtb2
(add_module_type (mod_mp mtb1) mtb1 env)
in
check_modtypes (cst, ustate) (Submodule l :: trace) env mtb1 mtb2 subst1 subst2 true
let mp1' = MPdot (mp1, l) in
let mp2' = MPdot (mp2, l) in
let () = assert (ModPath.equal mp1' (mod_mp mtb1)) in
let () = assert (ModPath.equal mp2' (mod_mp mtb2)) in
let env = add_module_type mp2' mtb2 (add_module_type mp1' mtb1 env) in
check_modtypes (cst, ustate) (Submodule l :: trace) env mp1' mtb1 mp2' mtb2 subst1 subst2 true
in
List.fold_left check_one_body cst sig2

and check_modtypes (cst, ustate) trace env mtb1 mtb2 subst1 subst2 equiv =
and check_modtypes (cst, ustate) trace env mp1 mtb1 mp2 mtb2 subst1 subst2 equiv =
let () = assert (ModPath.equal mp1 (mod_mp mtb1)) in
let () = assert (ModPath.equal mp2 (mod_mp mtb2)) in
if mtb1==mtb2 || mod_type mtb1 == mod_type mtb2 then cst
else
let rec check_structure cst ~nargs env struc1 struc2 equiv subst1 subst2 =
match struc1,struc2 with
| NoFunctor list1,
NoFunctor list2 ->
if equiv then
let subst2 = add_mp (mod_mp mtb2) (mod_mp mtb1) (mod_delta mtb1) subst2 in
let subst2 = add_mp mp2 mp1 (mod_delta mtb1) subst2 in
let cst = check_signatures (cst, ustate) trace env
(mod_mp mtb1) list1 (mod_mp mtb2) list2 subst1 subst2
mp1 list1 mp2 list2 subst1 subst2
(mod_delta mtb1) (mod_delta mtb2)
in
let cst = check_signatures (cst, ustate) trace env
(mod_mp mtb2) list2 (mod_mp mtb1) list1 subst2 subst1
mp2 list2 mp1 list1 subst2 subst1
(mod_delta mtb2) (mod_delta mtb1)
in
cst
else
check_signatures (cst, ustate) trace env
(mod_mp mtb1) list1 (mod_mp mtb2) list2 subst1 subst2
mp1 list1 mp2 list2 subst1 subst2
(mod_delta mtb1) (mod_delta mtb2)
| MoreFunctor (arg_id1,arg_t1,body_t1),
MoreFunctor (arg_id2,arg_t2,body_t2) ->
let mp2 = MPbound arg_id2 in
let subst1 = join (map_mbid arg_id1 mp2 (mod_delta arg_t2)) subst1 in
let env = add_module_type mp2 arg_t2 env in
let cst = check_modtypes (cst, ustate) (FunctorArgument (nargs+1) :: trace) env arg_t2 arg_t1 subst2 subst1 equiv in
let mparg1 = MPbound arg_id1 in
let mparg2 = MPbound arg_id2 in
let subst1 = join (map_mbid arg_id1 mparg2 (mod_delta arg_t2)) subst1 in
let env = add_module_type mparg2 arg_t2 env in
let cst = check_modtypes (cst, ustate) (FunctorArgument (nargs+1) :: trace) env mparg2 arg_t2 mparg1 arg_t1 subst2 subst1 equiv in
(* contravariant *)
let env =
if Modops.is_functor body_t1 then env
else
let mtb = make_module_type (mod_mp mtb1) (subst_signature subst1 body_t1) (mod_delta mtb1) in
add_module (module_body_of_type (mod_mp mtb1) mtb) env
let mtb = make_module_type mp1 (subst_signature subst1 body_t1) (mod_delta mtb1) in
add_module (module_body_of_type mp1 mtb) env
in
check_structure cst ~nargs:(nargs + 1) env body_t1 body_t2 equiv subst1 subst2
| _ , _ -> error_incompatible_modtypes mtb1 mtb2
in
check_structure cst ~nargs:0 env (mod_type mtb1) (mod_type mtb2) equiv subst1 subst2

let check_subtypes state env sup super =
let env = add_module_type (mod_mp sup) sup env in
let mp_sup = mod_mp sup in
let mp_super = mod_mp super in
let env = add_module_type mp_sup sup env in
check_modtypes state [] env
(strengthen sup (mod_mp sup)) super empty_subst
(map_mp (mod_mp super) (mod_mp sup) (mod_delta sup)) false

mp_sup (strengthen sup mp_sup) mp_super super empty_subst
(map_mp mp_super mp_sup (mod_delta sup)) false
8 changes: 6 additions & 2 deletions plugins/extraction/extract_env.ml
Original file line number Diff line number Diff line change
Expand Up @@ -223,11 +223,15 @@ let rec extract_structure_spec env mp reso = function
specs
| (l,SFBmodule mb) :: msig ->
let specs = extract_structure_spec env mp reso msig in
let spec = extract_mbody_spec env (mod_mp mb) mb in
let mp = MPdot (mp, l) in
let () = assert (ModPath.equal mp (mod_mp mb)) in
let spec = extract_mbody_spec env mp mb in
(l,Smodule spec) :: specs
| (l,SFBmodtype mtb) :: msig ->
let specs = extract_structure_spec env mp reso msig in
let spec = extract_mbody_spec env (mod_mp mtb) mtb in
let mp = MPdot (mp, l) in
let () = assert (ModPath.equal mp (mod_mp mtb)) in
let spec = extract_mbody_spec env mp mtb in
(l,Smodtype spec) :: specs

(* From [module_expression] to specifications *)
Expand Down
17 changes: 10 additions & 7 deletions vernac/assumptions.ml
Original file line number Diff line number Diff line change
Expand Up @@ -84,19 +84,20 @@ and memoize_fields_of_mp mp =
and fields_of_mp mp =
let open Mod_subst in
let mb = lookup_module_in_impl mp in
let fields,inner_mp,subs = fields_of_mb empty_subst mb [] in
let () = assert (ModPath.equal mp (mod_mp mb)) in
let fields,inner_mp,subs = fields_of_mb empty_subst mp mb [] in
let subs =
if ModPath.equal inner_mp mp then subs
else add_mp inner_mp mp (mod_delta mb) subs
in
Modops.subst_structure subs fields

and fields_of_mb subs mb args = match Mod_declarations.mod_expr mb with
| Algebraic expr -> fields_of_expression subs (mod_mp mb) args (mod_type mb) expr
and fields_of_mb subs mp mb args = match Mod_declarations.mod_expr mb with
| Algebraic expr -> fields_of_expression subs mp args (mod_type mb) expr
| Struct sign ->
let sign = Modops.annotate_struct_body sign (mod_type mb) in
fields_of_signature subs (mod_mp mb) args sign
| Abstract|FullStruct -> fields_of_signature subs (mod_mp mb) args (mod_type mb)
fields_of_signature subs mp args sign
| Abstract|FullStruct -> fields_of_signature subs mp args (mod_type mb)

(** The Abstract case above corresponds to [Declare Module] *)

Expand All @@ -108,8 +109,10 @@ and fields_of_signature x =

and fields_of_expr subs mp0 args = function
| MEident mp ->
let mb = lookup_module_in_impl (Mod_subst.subst_mp subs mp) in
fields_of_mb subs mb args
let mp = Mod_subst.subst_mp subs mp in
let mb = lookup_module_in_impl mp in
let () = assert (ModPath.equal mp (mod_mp mb)) in
fields_of_mb subs mp mb args
| MEapply (me1,mp2) -> fields_of_expr subs mp0 (mp2::args) me1
| MEwith _ -> assert false (* no 'with' in [mod_expr] *)

Expand Down

0 comments on commit 1d1d239

Please sign in to comment.