%-----------------------------------------------------------------------------% % vim: ft=mercury ts=4 sw=4 et %-----------------------------------------------------------------------------% % % This is a test for a bug in the interaction of the direct arg optimization % with partially instantiated data structures. % % The bug arises in the call to the type-specific unification predicate % for the maybe_reviewed type that the compiler generates to unify % the first element of S with R, but ONLY when that call is not inlined. % % In the inlined version, when we fill in the argument of R, we update R. % In the non-inlined version, when we fill in the argument of HeadVar__1, % for which main passes R, we update HeadVar__1, but do NOT update R in main. % Normally, this is not a problem: the filled in argument is normally % on the heap, and the caller's pointer also points to it, so the caller % also sees the field as being filled in. However, with the direct arg % optimization, the field being filled in is NOT on the heap; it is % in the pointer, next to the primary tag. It is the lack of any update % to this field in the caller's R that leaves the value of R as a % tagged NULL pointer, whose dereferencing leads to the crash. % :- module gh72a. :- interface. :- import_module io. :- pred main(io::di, io::uo) is det. :- implementation. :- import_module list. :- import_module string. :- type maybe_reviewed ---> reviewed(package) ; unreviewed(package). :- type package ---> package(string, string). main(!IO) :- ( if R = unreviewed(_), sols(S), S = [R] then io.write_string(dump_maybe_reviewed(R), !IO), io.nl(!IO) else true ). :- pred sols(list(maybe_reviewed)::out) is det. sols([unreviewed(package("a", "b"))]). :- func dump_maybe_reviewed(maybe_reviewed) = string. :- pragma no_inline(dump_maybe_reviewed/1). dump_maybe_reviewed(reviewed(P)) = "reviewed " ++ dump_package(P). dump_maybe_reviewed(unreviewed(P)) = "unreviewed " ++ dump_package(P). :- func dump_package(package) = string. :- pragma no_inline(func(dump_package/1)). dump_package(package(A, B)) = A ++ B.