Skip to content

Commit 9b272a8

Browse files
committed
Tentative fix for the commutative cut subterm rule.
Some fixpoints are now rejected in the standard library, but that's probably because we compare trees for equality instead of intersecting them.
1 parent ccd7546 commit 9b272a8

1 file changed

Lines changed: 35 additions & 7 deletions

File tree

kernel/inductive.ml

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -611,16 +611,14 @@ let check_inductive_codomain env p =
611611
isInd i
612612

613613
let get_codomain_tree env p =
614-
let absctx, ar = dest_lam_assum env p in
615-
let arctx, s = dest_prod_assum env ar in
614+
let absctx, ar = dest_lam_assum env p in (* TODO: reduce or preserve lets? *)
615+
let arctx, s = dest_prod_assum env ar in (* TODO: check number of prods *)
616616
let i,l' = decompose_app (whd_betadeltaiota env s) in
617617
match kind_of_term i with
618618
| Ind i ->
619619
let (_,mip) = lookup_mind_specif env i in Subterm(Strict,mip.mind_recargs)
620620
| _ -> Not_subterm
621621

622-
623-
624622
(* [subterm_specif renv t] computes the recursive structure of [t] and
625623
compare its size with the size of the initial recursive argument of
626624
the fixpoint we are checking. [renv] collects such information
@@ -650,6 +648,7 @@ let rec subterm_specif renv stack t =
650648
furthermore when f is applied to a term which is strictly less than
651649
n, one may assume that x itself is strictly less than n
652650
*)
651+
(* TODO: is this necessary? *)
653652
if not (check_inductive_codomain renv.env typarray.(i)) then Not_subterm
654653
else
655654
let (ctxt,clfix) = dest_prod renv.env typarray.(i) in
@@ -686,7 +685,7 @@ let rec subterm_specif renv stack t =
686685

687686
| Lambda (x,a,b) ->
688687
let () = assert (List.is_empty l) in
689-
let spec,stack' = extract_stack renv a stack in
688+
let spec,stack' = extract_stack stack in
690689
subterm_specif (push_var renv (x,a,spec)) stack' b
691690

692691
(* Metas and evars are considered OK *)
@@ -702,7 +701,7 @@ and stack_element_specif = function
702701
|SClosure (h_renv,h) -> lazy_subterm_specif h_renv [] h
703702
|SArg x -> x
704703

705-
and extract_stack renv a = function
704+
and extract_stack = function
706705
| [] -> Lazy.lazy_from_val Not_subterm , []
707706
| h::t -> stack_element_specif h, t
708707

@@ -732,6 +731,34 @@ let error_illegal_rec_call renv fx (arg_renv,arg) =
732731
let error_partial_apply renv fx =
733732
raise (FixGuardError (renv.env,NotEnoughArgumentsForFixCall fx))
734733

734+
let filter_stack_domain env ci p stack =
735+
let absctx, ar = dest_lam_assum env p in
736+
let env = push_rel_context absctx env in
737+
let rec filter_stack env ar stack =
738+
let t = whd_betadeltaiota env ar in
739+
match stack, kind_of_term t with
740+
| elt :: stack', Prod (n,a,c0) ->
741+
let d = (n,None,a) in
742+
let ty, _ = decompose_app a in (* TODO: reduce a? *)
743+
let elt = match kind_of_term ty with
744+
| Ind i ->
745+
let (_,mip) = lookup_mind_specif env i in
746+
let spec' = stack_element_specif elt in (* TODO: this is recomputed
747+
each time*)
748+
(match (Lazy.force spec') with (* TODO: are we forcing too much? *)
749+
| Not_subterm -> elt
750+
| Subterm(_,path) ->
751+
if eq_wf_paths path mip.mind_recargs then elt
752+
else (SArg (lazy Not_subterm))) (* TODO: intersection *)
753+
(* TODO: not really an SArg *)
754+
| _ -> (SArg (lazy Not_subterm))
755+
in
756+
elt :: filter_stack (push_rel d env) c0 stack'
757+
| _,_ -> List.fold_right (fun _ l -> SArg (lazy Not_subterm) :: l) stack []
758+
(* TODO: is it correct to empty the stack instead? *)
759+
in
760+
filter_stack env ar stack
761+
735762
(* Check if [def] is a guarded fixpoint body with decreasing arg.
736763
given [recpos], the decreasing arguments of each mutually defined
737764
fixpoint. *)
@@ -786,6 +813,7 @@ let check_one_fix renv recpos def =
786813
let case_spec = branches_specif renv
787814
(lazy_subterm_specif renv [] c_0) ci in
788815
let stack' = push_stack_closures renv l stack in
816+
let stack' = filter_stack_domain renv.env ci p stack' in
789817
Array.iteri (fun k br' ->
790818
let stack_br = push_stack_args case_spec.(k) stack' in
791819
check_rec_call renv stack_br br') lrest
@@ -828,7 +856,7 @@ let check_one_fix renv recpos def =
828856
| Lambda (x,a,b) ->
829857
let () = assert (List.is_empty l) in
830858
check_rec_call renv [] a ;
831-
let spec, stack' = extract_stack renv a stack in
859+
let spec, stack' = extract_stack stack in
832860
check_rec_call (push_var renv (x,a,spec)) stack' b
833861

834862
| Prod (x,a,b) ->

0 commit comments

Comments
 (0)