Freeze(_, Goal) ignores Goal

Hi, freeze/2 and when/2 seem to have the same problem, with _ (an anonymous variable):

In SWI-Prolog (threaded, 64 bits, version 9.0.3), running in Void Linux:

?- freeze(F, N=1).
freeze(F, N=1).  % As expected

?- freeze(_, N=1).
true.  % Bad - ignores Goal
?- when(nonvar(F), N=1).
when(nonvar(F), N=1).  % As expected

?- when(nonvar(_), N=1).
true.  % Bad - ignores goal

My use-case is:

max_member_freeze(Max, [H|T]) :-
    (   T == []
        % Only 1 element
    ->  Max = H
        % Start with Upto unknown
    ;   freeze(H, max_member_freeze_([H|T], _, Max))
    ).

max_member_freeze_([], Max, Max). 
max_member_freeze_([H|T], Upto, Max) :-
    (var(Upto) -> Upto = H ; true),
    when((nonvar(H), nonvar(Upto)),
        (   (nonvar(Max) -> Max @>= H ; true),
            max(H, Upto, Upto1),
            freeze(T, max_member_freeze_(T, Upto1, Max))
        )
    ).

max(X, Y, Max) :-
    (   X @< Y
    ->  Max = Y
    ;   Max = X
    ).  

… which gives:

?- max_member_freeze(1, [1, N]).
when(nonvar(N), ((nonvar(1)->1@>=N;true), max(N, 1, _A), freeze([], max_member_freeze_([], _A, 1)))).
% As expected
?- max_member_freeze(1, [1, _]).
true. % Wrongly ignores the potential value of the 2nd element in the list

Is this a bug? Shouldn’t _ be converted by the system into a variable such as _A?

Perhaps this is a useful trick, to “prevent” an anonymous variable:

?- _ = f(F), freeze(F, N=1).
freeze(F, N=1).

… or is there some workaround?

I suspect that this is a “feature” (or “bug”) of how results are printed (after all, the output freeze(F,N=1) is a kind of true; it’s just printed with some extra context). If you query freeze(_A,N=1), you get the expected result, similarly with max_member_freeze(1, [1, _N]).

Thanks, yes that looks likely - this shows the fuller picture:

?- call_residue_vars(max_member_freeze(1, [1, _]), Vs).
Vs = [_A],
when(nonvar(_A), ((nonvar(1)->1@>=_A;true), max(_A, 1, _B), freeze([], max_member_freeze_([], _B, 1)))).