Files
mercury/tests/valid/impure_lambda_bug.m
Julien Fischer 6ab4ec3980 Fix a bug reported by Peter Hawkins.
Estimated hours taken: 8
Branches: main, release

Fix a bug reported by Peter Hawkins.

compiler/superhomogeneous.m:
	When converting lambda expressions into superhomogeneous form,
	position the compiler created unifications that correspond to
	output arguments *after* the original body of the lambda.
	Placing them all before the body, leads to problems if the body
	is impure because mode analysis cannot reorder the unifications
	over the impure goal as it needs to in order for the lambda to
	be mode correct.

	XXX According to a comment, intermod.m:643, we allow head
	unifications to be reordered w.r.t impure goals, but this doesn't
	seem to extend to lambda expressions for some reason.  Actually,
	the rules for reordering over impure goals should be less
	strict then they currently are, at least for construction
	and assignment unifications.  (I'll look into this separately though).

compiler/arg_info.m:
	Mention how the predicates in this module diff from the newly
	introduced partition_args_and_lambda_vars in superhomogenous.m.
	(Because the former cannot handle undefined modes.)

compiler/state_var.m:
	Generalise the predicate finish_head_and_body/6 so that it works
	on an arbitrary number of conjoined goals.

compiler/mode_util.m:
	Add a predicate to test whether a mode is undefined.

compiler/add_aditi.m:
compiler/add_clause.m:
	Conform to the above changes.

tests/valid/Mmakefile:
tests/valid/impure_lambda_bug.m:
	Test case for the above bug.
2005-08-12 02:33:10 +00:00

58 lines
1.5 KiB
Mathematica

%
% This is a cut-down version of a bug reported by Peter Hawkins.
% Mercury rotd 2005-08-02 and before failed this because some of the
% extra unifications required to convert the lambda expression to
% superhomogenous form were put in the wrong spot if the body of the
% lambda expression was impure. In particular the unifications for the
% output arguments needed to be reordered by mode analysis so that they
% occurred after whatever goal produces their RHS; in the case where the
% body is impure so mode analysis could not do the necessary reordering.
%
:- module impure_lambda_bug.
:- interface.
:- type unit ---> unit.
:- type alpha ---> alpha.
:- type beta ---> beta.
% A cut down version of the original bug.
%
:- pred foo((impure pred(unit, unit))::out((pred(di, uo) is det))) is det.
% A couple of other tests.
%
:- pred baz((pred(alpha, beta, beta))::out(pred(out, di, uo) is det)) is det.
:- pred func_foo((impure func(unit) = unit)::out) is det.
:- pred with_unused((impure pred(unit, unit, unit))
::out((pred(unused, di, uo) is det))) is det.
:- implementation.
foo(Pred) :-
Pred = (impure pred(!.A::di, !:A::uo) is det :-
impure bar(!A)
).
:- impure pred bar(unit, unit).
:- mode bar(in, out) is det.
:- mode bar(di, uo) is det.
bar(!A) :- impure private_builtin.imp.
baz(Pred) :-
Pred = (pred(R::out, A::di, B::uo) is det :-
A = B,
R = alpha
).
func_foo(Func) :-
Func = (impure func(In) = Out :- impure bar(In, Out)).
with_unused(Pred) :-
Pred = (impure pred(_::unused, !.A::di, !:A::uo) is det :-
impure bar(!A)
).