1/*  Part of Extended Tools for SWI-Prolog
    2
    3    Author:        Edison Mera Menendez
    4    E-mail:        efmera@gmail.com
    5    WWW:           https://github.com/edisonm/xtools
    6    Copyright (C): 2019, Process Design Center, Breda, The Netherlands.
    7    All rights reserved.
    8
    9    Redistribution and use in source and binary forms, with or without
   10    modification, are permitted provided that the following conditions
   11    are met:
   12
   13    1. Redistributions of source code must retain the above copyright
   14       notice, this list of conditions and the following disclaimer.
   15
   16    2. Redistributions in binary form must reproduce the above copyright
   17       notice, this list of conditions and the following disclaimer in
   18       the documentation and/or other materials provided with the
   19       distribution.
   20
   21    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   22    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   23    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
   24    FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
   25    COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
   26    INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
   27    BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   28    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
   29    CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   30    LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
   31    ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   32    POSSIBILITY OF SUCH DAMAGE.
   33*/
   34
   35:- module(check_useless_cuts, []).   36
   37:- use_module(library(lists)).   38:- use_module(library(solution_sequences)).   39:- use_module(library(assertions)).   40:- use_module(library(neck)).   41:- use_module(library(abstract_interpreter), []).   42:- use_module(library(gcu)).   43:- use_module(library(location_utils)).   44:- use_module(library(option_utils)).   45:- use_module(library(qualify_meta_goal)).   46:- use_module(library(safe_prolog_cut_to)).   47:- use_module(library(checkable_predicate)).   48:- use_module(library(checkers/checker)).   49:- use_module(library(check), []).   50
   51:- multifile
   52    prolog:message//1,
   53    walk_body_hook/9,
   54    has_body_hook/2.   55
   56:- dynamic
   57    cut_info/3,
   58    inferred_det_db/3,
   59    det_checking/1,
   60    det_checking/2,
   61    det_clause_db/2.   62
   63prolog:message(acheck(useless_cuts)) -->
   64    ['Check useless cuts',nl,
   65     '------------------',nl,
   66     'The predicates contain cuts that are actually not needed.', nl,
   67     'That could happen when the analysis determined that all', nl,
   68     'the calls before the cut and the clause itself where', nl,
   69     'deterministic or they have one of the next properties:', nl,
   70     'det, semidet, is_det or fails.  Note that in recursive', nl,
   71     'predicates the cut would look as needed, but it is not', nl,
   72     'since it can be removed or avoided via refactoring.', nl, nl].
   73prolog:message(acheck(useless_cuts, Issue)) -->
   74    issue_type_message(Issue).
   75
   76issue_type_message(useless_cut(Loc, CI)-CutPosL) -->
   77    Loc,
   78    {length(CutPosL, N)},
   79    ['~q has ~w useless cut(s) (~q)'-[CI, N, CutPosL], nl].
   80
   81checker:check(useless_cuts, Result, Options) :-
   82    check_useless_cuts(Options, Result).
   83
   84check_useless_cuts(Options, Pairs) :-
   85    option_module_files(Options, MFileD),
   86    cuts_check(MFileD, Pairs),
   87    cleanup_useless_cuts.
   88
   89cleanup_useless_cuts :-
   90    retractall(det_checking(_)),
   91    retractall(det_checking(_, _)),
   92    retractall(det_clause_db(_, _)),
   93    retractall(inferred_det_db(_, _, _)).
   94
   95cuts_check(MFileD, Pairs) :-
   96    forall(current_det_check(MFileD),
   97           true),
   98    retractall(cut_info(_, _, needed)),
   99    findall(warning-Issue,
  100            collect_issues(Issue, MFileD), Pairs).
  101
  102collect_issues(useless_cut(Loc, M:F/A-I)-CutPos, MFileD) :-
  103    retract(cut_info(Ref, RCutPos, unused)),
  104    nth_clause(M:H, I, Ref),
  105    get_dict(M, MFileD, FileD),
  106    clause_property(Ref, file(File)),
  107    get_dict(File, FileD, _), % Avoid warnings from out there
  108    functor(H, F, A),
  109    reverse(RCutPos, CutPos), % reverse is more human-readable
  110    from_location(clause(Ref), Loc).
  111
  112% 1. A cut is useless, if is located at the last clause, and the literals above
  113% are semidet
  114
  115current_det_check(MFileD) :-
  116    order_by([asc(M:F/A)],
  117             ( get_dict(M, MFileD, FileD),
  118               current_predicate(M:F/A),
  119               functor(H, F, A),
  120               MH = M:H,
  121               % Start analyzing exported predicates, ancillary predicates will
  122               % be analyzed by det_check/3 if the argument instantiation can
  123               % not be determined, or by walk_lit/5 for specific
  124               % instantiations.
  125               predicate_property(MH, exported),
  126               \+ predicate_property(MH, imported_from(_)),
  127               \+ \+ ( catch(clause(MH, _, Ref), _, fail),
  128                       clause_property(Ref, file(File)),
  129                       get_dict(File, FileD, _)
  130                     )
  131             )),
  132    check_det(H, M, _).
  133
  134clauses_accessible(MH) :-
  135    \+ is_built_in(MH),
  136    \+ predicate_property(MH, foreign).
  137
  138check_det(H, M, Det) :-
  139    ( inferred_det_db(H, M, Det)
  140    ->true
  141    ; do_check_det(H, M, Det)
  142    ->assertz(inferred_det_db(H, M, Det))
  143    ; print_message(error,
  144                    format("unexpected failure of infer_det/3 or predef_det/3 ~q",
  145                           [M:H]))
  146    ).
  147
  148do_check_det(H, M, Det) :-
  149    ( predef_det(H, M, Det)
  150    ->true
  151    ; % format(user_error, "? ~q~n", [M:H]),
  152      with_det_checking_pr(
  153          H, M, catch(forall(walk_call(H, M, info), true),
  154                      Error,
  155                      print_message(
  156                          error,
  157                          Error))),
  158      infer_det(H, M, Det)
  159      % format(user_error, "! ~q: ~w~n", [M:H, Det])
  160    ).
  161
  162inferred_det(C, M, Det) :-
  163    functor(C, F, A),
  164    functor(H, F, A),
  165    predicate_property(M:H, implementation_module(I)),
  166    check_det(H, I, Det1),
  167    Det1 = Det.
 predef_det(-DetInfo, +Head, +Module) is semidet
Get Determinism information for a given predicate, that comes from user-defined assertions (which has priority) or predicate properties. If the predicate is being analyzed, assumes nondet, which is the value used when there is no determinism information (yet).
  176predef_det(H, M, Det) :-
  177    once(det_predef(Det, H, M)).
  178
  179valid_prop_asr(Lit, M, Asr) :-
  180    prop_asr(Lit, M, Status, Type, _, _, Asr),
  181    valid_status(Status),
  182    valid_type(Type).
  183
  184valid_status(true).
  185valid_status(check).
  186
  187valid_type(pred).
  188valid_type(prop).
  189
  190valid_glob_asr(GL, A) :-
  191    member(G, GL),
  192    prop_asr(glob, globprops:G, _, A).
  193
  194:- public
  195    det_props/2.  196
  197det_props(fails, [fails(_), failure(_)]).
  198det_props(isdet, [det(_), semidet(_), is_det(_), no_choicepoints(_)]).
  199det_props(nodet, [multi(_), non_det(_), nondet(_)]).
  200
  201det_predef_asr(Det, H, M) :-
  202    det_props(Det, GL),
  203    neck,
  204    collect_valid_glob_asr(Det, GL, H, M).
  205
  206collect_valid_glob_asr(Det, GL, H, M) :-
  207    member(Det, [fails, isdet]),
  208    neck,
  209    \+ \+ valid_prop_asr(H, M, _),
  210    forall(valid_prop_asr(H, M, A),
  211           valid_glob_asr(GL, A)).
  212collect_valid_glob_asr(Det, GL, H, M) :-
  213    member(Det, [nodet]),
  214    neck,
  215    valid_prop_asr(H, M, A),
  216    valid_glob_asr(GL, A).
  217
  218det_predef(Det,   H, M) :- inferred_det_db(H, M, Det).
  219det_predef(Det,   H, M) :- det_predef_asr(Det, H, M).
  220det_predef(nodet, H, M) :- det_checking(H, M).
  221det_predef(nodet, H, M) :- \+ clauses_accessible(M:H).
  222det_predef(fails, H, M) :-
  223    \+ predicate_property(M:H, dynamic),
  224    \+ predicate_property(M:H, multifile),
  225    predicate_property(M:H, number_of_clauses(0 )).
  226
  227infer_det(H, M, Det) :-
  228    member(Det1, [multi, isdet, fails]),
  229    \+ \+ ( current_clause(M:H, _, Ref),
  230            det_clause(Ref, Det1)
  231          ),
  232    !,
  233    Det = Det1.
  234
  235add_cp.
  236add_cp :- fail.
  237
  238:- meta_predicate
  239    with_det_checking_pr(+, +, 0 ),
  240    with_det_checking_cl(+, +, 0 ).
 with_det_checking_pr(+Head, +Module, :Call)
 with_det_checking_cl(+Head, +Module, :Call)
  246%   with_det_checking ensures decidability by not analyzing if there is a
  247%   recursion that requires to analyze the same call again (abstraction step)
  248
  249with_det_checking_pr(H, M, Call) :-
  250    ( det_checking(H, M)
  251    ->true
  252    ; functor(H, F, A),
  253      functor(P, F, A),
  254      setup_call_cleanup(
  255          assertz(det_checking(P, M), DCRef),
  256          ( Call,
  257            erase(DCRef)
  258          ),
  259          erase_nf(DCRef))
  260    ).
  261
  262with_det_checking_cl(info, _,      Call) :- call(Call).
  263with_det_checking_cl(noop, Clause, Call) :-
  264    ( det_checking(Clause)
  265    ->add_cp
  266    ; setup_call_cleanup(
  267          assert_det_checking(Clause, Ref),
  268          ( call(Call),
  269            erase(Ref)
  270          ),
  271          erase_nf(Ref))
  272    ).
  273
  274erase_nf(Ref) :- ignore(erase(Ref)).
  275
  276assert_det_checking(Clause, Ref) :-
  277    assertz(det_checking(Clause), Ref).
  278
  279:- meta_predicate current_clause(0, -, -).  280
  281current_clause(MH, Body, Ref) :-
  282    \+ predicate_property(MH, dynamic),
  283    \+ predicate_property(MH, multifile),
  284    !,
  285    clause(MH, Body, Ref).
  286current_clause(MH, Body, Ref) :-
  287    % for dynamic and multifile, add a choicepoint at the end of the clause
  288    ( clause(MH, Body, Ref)
  289    ; Body = true,
  290      Ref = null,
  291      add_cp
  292    ).
  293
  294current_clause(MH, Body, Ref, CP1, CP2) :-
  295    prolog_current_choice(CP1),
  296    current_clause(MH, Body, Ref),
  297    prolog_current_choice(CP2).
  298
  299:- meta_predicate call_with_location(0, +).  300
  301call_with_location(Call, Ref) :-
  302    catch(Call, Error, throw(at_location(clause(Ref), Error))).
  303
  304walk_call(H, M, CA) :-
  305    current_clause(M:H, Body, Ref, CP1, CP2),
  306    ( Ref = null
  307    ->add_det_clause(CA, Ref, CP1, CP2)
  308    ; Body = true
  309    ->true
  310    ; add_neg_clause(CA, Ref),
  311      clause_property(Ref, module(CM)),
  312      call_with_location(
  313          with_det_checking_cl(
  314              CA, Ref,
  315              do_walk_body(Body, CM, Ref, CA, CP1, CP2)),
  316          Ref)
  317    ),
  318    remove_new_cp(CA, CP2).
  319
  320cut_to(CP) :- catch(safe_prolog_cut_to(CP), _, true).
  321
  322remove_new_cp(noop, _).
  323remove_new_cp(info, CP) :- cut_to(CP).
  324
  325do_walk_body(Body, CM, Ref, CA, CP1, CP2) :-
  326    % We can not cut CP1, since we are analyzing clause by clause, so if there
  327    % is a choice point at clause level, we insert a choicepoint with add_cp to
  328    % detect any cut in the clause
  329    prolog_current_choice(CP3),
  330    ( CP1 == CP2
  331    ->true
  332    ; add_cp
  333    ),
  334    prolog_current_choice(CP4),
  335    walk_body(Body, CM, [], Ref, CA, CP3, CP4, _),
  336    prolog_current_choice(CP5),
  337    add_det_clause(CA, Ref, CP3, CP5).
  338
  339add_cut_info(unused, LitPos, Ref) :-
  340    ( cut_info(Ref, LitPos, _)
  341    ->true
  342    ; assertz(cut_info(Ref, LitPos, unused))
  343    ).
  344add_cut_info(needed, LitPos, Ref) :-
  345    retractall(cut_info(Ref, LitPos, _)),
  346    assertz(cut_info(Ref, LitPos, needed)).
  347
  348det_clause(Ref, Det) :-
  349    det_clause_db(Ref, Det1),
  350    !,
  351    Det = Det1.
  352det_clause(Ref, Det) :-
  353    nth_clause(Pred, Idx, Ref),
  354    clause(_, Body, Ref),
  355    Body = true,
  356    !,
  357    ( predicate_property(Pred, number_of_clauses(Idx))
  358    ->Det = isdet
  359    ; Det = multi
  360    ).
  361det_clause(_, multi).
  362
  363add_det_clause(info, Ref, CP2, CP3) :-
  364    ( CP2 == CP3
  365    ->DetInfo = isdet
  366    ; DetInfo = multi
  367    ),
  368    retractall(det_clause_db(Ref, _)),
  369    assertz(det_clause_db(Ref, DetInfo)).
  370add_det_clause(noop, _, _, _).
  371
  372add_neg_clause(info, Ref) :-
  373    assertz(det_clause_db(Ref, fails)).
  374add_neg_clause(noop, _).
  375
  376add_pos([], Pos, [Pos]).
  377add_pos([Pos1|LitPos1], Pos, LitPos) :-
  378    ( Pos1 = Pos
  379    ->LitPos = [Pos-2|LitPos1]
  380    ; Pos1 = Pos-N1
  381    ->succ(N1, N),
  382      LitPos = [Pos-N|LitPos1]
  383    ; LitPos = [Pos, Pos1|LitPos1]
  384    ).
  385
  386:- discontiguous walk_body/8.  387
  388walk_body(V, M, _, _, _, _, CP, CP) :-
  389    ( var(V)
  390    ; var(M)
  391    ),
  392    !,
  393    add_cp.
  394walk_body(!, _, LitPos, Ref, _, CP1, _, CP1) :-
  395    !,
  396    prolog_current_choice(CP),
  397    ( CP1 \= CP
  398    ->Info = needed,
  399      cut_to(CP1)
  400    ; Info = unused
  401    ),
  402    add_cut_info(Info, LitPos, Ref).
  403walk_body(M:A, _, LitPos, Ref, CA, CP1, CP2, CP) :-
  404    !,
  405    add_pos(LitPos, 2, LitPosA),
  406    walk_body(A, M, LitPosA, Ref, CA, CP1, CP2, CP).
  407walk_body((A, B), M, LitPos, Ref, CA, CP1, CP2, CP) :-
  408    !,
  409    add_pos(LitPos, 1, LitPosA),
  410    add_pos(LitPos, 2, LitPosB),
  411    walk_body(A, M, LitPosA, Ref, CA, CP1, CP2, CP3),
  412    walk_body(B, M, LitPosB, Ref, CA, CP1, CP3, CP).
  413walk_body((A; B), M, LitPos, Ref, CA, CP1, CP2, CP) :-
  414    !,
  415    ( member(A, [(_->_), (_*->_)])
  416    ->prolog_current_choice(CP3),
  417      SFlag = s([]),
  418      findall((A; B),
  419              ( member(Branch-Pos, [A-1, B-2]),
  420                walk_body_if_branch(Branch, M, [Pos|LitPos], Ref, CA, SFlag, CP1, CP3)
  421              ), [Term|TermL]),
  422      foldl(greatest_common_unifier, TermL, Term, (A; B)),
  423      SFlag = s(FlagL),
  424      ( member(leave_cp1, FlagL)
  425      ->CP = CP2
  426      ; cut_to(CP1),
  427        CP = CP1
  428      ),
  429      ( member(insert_cp, FlagL)
  430      ->add_cp
  431      ; true
  432      )
  433    ; ( prolog_current_choice(CP3),
  434        % add_cp will mark a cut as needed, since it can cut the internal
  435        % choicepoint of :/2
  436        add_cp,
  437        prolog_current_choice(CP4),
  438        add_pos(LitPos, 1, LitPosA),
  439        walk_body(A, M, LitPosA, Ref, CA, CP3, CP4, CP)
  440      ; add_pos(LitPos, 2, LitPosB),
  441        walk_body(B, M, LitPosB, Ref, CA, CP1, CP2, CP)
  442      )
  443    ).
  444
  445walk_body_if_branch(C, M, LitPos, Ref, CA, SFlag, CP1, CP2) :-
  446    ( CP1 == CP2
  447    ->prolog_current_choice(CP3)
  448    ; prolog_current_choice(CP3),
  449      ( true
  450      ; SFlag = s(FlagL),
  451        nb_setarg(1, SFlag, [leave_cp1|FlagL]),
  452        fail
  453      )
  454    ),
  455    prolog_current_choice(CP4),
  456    walk_body(C, M, LitPos, Ref, CA, CP3, CP4, _),
  457    prolog_current_choice(CP5),
  458    ( CP3 == CP5
  459    ->true
  460    ; CP4 == CP5
  461    ->true
  462    ; cut_to(CP4),
  463      SFlag = s(FlagL),
  464      nb_setarg(1, SFlag, [insert_cp|FlagL])
  465    ).
  466
  467walk_body((A->B), M, LitPos, Ref, CA, CP1, CP2, CP) :-
  468    !,
  469    ( prolog_current_choice(CP3),
  470      add_pos(LitPos, 1, LitPosA),
  471      walk_body(A, M, LitPosA, Ref, CA, CP3, CP2, CP4)
  472    ->add_pos(LitPos, 2, LitPosB),
  473      walk_body(B, M, LitPosB, Ref, CA, CP1, CP4, CP)
  474    ).
  475walk_body((A*->B), M, LitPos, Ref, CA, CP1, CP2, CP) :-
  476    !,
  477    ( prolog_current_choice(CP3),
  478      add_pos(LitPos, 1, LitPosA),
  479      walk_body(A, M, LitPosA, Ref, CA, CP3, CP2, CP4),
  480      add_pos(LitPos, 2, LitPosB),
  481      walk_body(B, M, LitPosB, Ref, CA, CP1, CP4, CP)
  482    ).
  483walk_body(call(A), M, LitPos, Ref, CA, _, CP2, CP) :-
  484    !,
  485    prolog_current_choice(CP3),
  486    add_pos(LitPos, 1, LitPosA),
  487    walk_body(A, M, LitPosA, Ref, CA, CP3, CP2, CP).
  488walk_body(\+ (A), M, LitPos, Ref, CA, _, CP2, CP2) :-
  489    !,
  490    \+ ( prolog_current_choice(CP),
  491         add_pos(LitPos, 1, LitPosA),
  492         walk_body(A, M, LitPosA, Ref, CA, CP, CP, _),
  493         fail
  494       ).
  495walk_body(true, _, _, _, _, _, CP, CP) :- !.
  496walk_body(fail, _, _, _, _, _, CP, _) :-
  497    !,
  498    catch(safe_prolog_cut_to(CP), _, true),
  499    fail.
  500walk_body(false, _, _, _, _, _, CP, _) :-
  501    !,
  502    catch(safe_prolog_cut_to(CP), _, true),
  503    fail.
  504walk_body(A=B, _, _, _, _, _, CP, CP) :-
  505    !,
  506    ( A = B
  507    ->true
  508    ; cut_to(CP),
  509      fail
  510    ).
  511walk_body(A\=B, _, _, _, _, _, CP, CP) :-
  512    !,
  513    ( A \= B
  514    ->true
  515    ; A \== B
  516    ->true
  517    ; A == B
  518    ->cut_to(CP),
  519      fail
  520    ).
  521walk_body(C, M, LitPos, Ref, CA, CP1, CP2, CP3) :-
  522    predicate_property(M:C, implementation_module(I)),
  523    has_body_hook(C, I),
  524    !,
  525    walk_body_hook(C, I, M, LitPos, Ref, CA, CP1, CP2, CP3).
  526
  527:- public
  528    curr_wrapper/3.  529
  530curr_wrapper(start_tabling(_, C), '$tabling', C).
  531
  532has_body_hook(W, M) :-
  533    curr_wrapper(W, M, _),
  534    neck.
  535
  536walk_body_hook(W, I, M, LitPos, Ref, CA, CP1, CP2, CP3) :-
  537    curr_wrapper(W, I, A),
  538    neck,
  539    walk_body(call(A), M, LitPos, Ref, CA, CP1, CP2, CP3).
  540
  541walk_body(A, M, _, Ref, _, _, CP, CP) :-
  542    abstract_interpreter:evaluable_body_hook(A, M, Condition),
  543    call(Condition),
  544    !,
  545    ( \+ \+ call_with_location(M:A, Ref)
  546    ->call(M:A)
  547    ; cut_to(CP),
  548      fail
  549    ).
  550
  551walk_body(atom_concat(_, B, _), _, _, _, _, _, CP, CP) :-
  552    atomic(B),
  553    !.
  554walk_body(atom_concat(A, B, C), _, _, _, _, _, CP, CP) :-
  555    atomic(C),
  556    !,
  557    atom_concat(A, B, C).
  558walk_body(atom_length(A, B), _, _, _, _, _, CP, CP) :-
  559    atomic(A),
  560    !,
  561    atom_length(A, B).
  562walk_body(atom_length(_, _), _, _, _, _, _, CP, CP) :- !.
  563walk_body(nb_getval(A, B), _, _, _, _, _, CP, CP) :-
  564    ignore((nonvar(A), nb_current(A, B))).
  565walk_body(@(M:H, C), _, _, Ref, _, _, CP, CP) :-
  566    walk_lit(H, M, C, Ref, CP).
  567walk_body(H, M, _, Ref, _, _, CP, CP) :-
  568    walk_lit(H, M, M, Ref, CP).
  569
  570walk_lit(V, M, _, _, _) :-
  571    ( var(V)
  572    ; var(M)
  573    ),
  574    !,
  575    add_cp.
  576walk_lit(H, M, CM, Ref, CP) :-
  577    ( predicate_property(M:H, meta_predicate(Meta))
  578    ->qualify_meta_goal(CM:H, Meta, C)
  579    ; C = H
  580    ),
  581    ( \+ predicate_property(M:C, defined)
  582    ->print_message(
  583          error,
  584          at_location(clause(Ref),
  585          format("Undefined predicate found: ~q", [M:C]))),
  586      fail
  587    ; true
  588    ),
  589    ( inferred_det(C, M, nodet)
  590      % We have to check for nodet, instead of multi, since all predicates that
  591      % don't have det properties inferred yet are marked as multi.
  592    ->add_cp
  593    ; % We can check multi only if all arguments of C are independent
  594      % variables, meaning that we can reuse the result of the determinism
  595      % analysis:
  596      functor(C, F, A),
  597      functor(P, F, A),
  598      C =@= P,
  599      inferred_det(C, M, multi)
  600    ->add_cp
  601    ; inferred_det(C, M, isdet)
  602    ->true
  603    ; inferred_det(C, M, fails)
  604    ->cut_to(CP),
  605      fail
  606    ; catch(findall(-, current_clause(M:C, _, _), ClauseL),
  607            _,
  608            AddCP = true),
  609      ( ClauseL = []
  610      ->cut_to(CP),
  611        fail
  612      ; AddCP == true
  613      ->add_cp
  614      ; walk_call(C, M, noop)
  615      )
  616    )