Files
mercury/tests/valid/gh98.m
Zoltan Somogyi 10da1dcdd0 Fix nonlocal typeclass_infos in rhs_lambda_goals.
This fixes github bug #98.

compiler/polymorphism.m:
    Compiling gh98.m used to cause a compiler crash when the compiler
    tried to look up info about a typeclass_info variable that was needed
    in a call inside a lambda goal, but was not created inside the lambda goal.
    It should therefore have been listed as a nonlocal of the lambda goal,
    but it was not, because none of the variables inside the lambda goal
    had the typeclass constraint represented by that typeclass_info var
    on their types. And since later invocations of quantification may
    reduce, but may not expand, the set of nonlocals in a rhs_lambda_goal
    (as opposed to the nonlocals set of the unification whose RHS consists
    of that rhs_lambda_goal), this problem stuck.

    Fix this underestimation of the final lambda nonlocals set by including
    in it all typeinfo and/or typeclass_info vars in the updated lambda goal.
    Since this may then result in an overestimation, set a flag to force
    a requantification of the whole procedure body once its polymorphism
    transformation has been completed.

compiler/polymorphism_info.m:
    Add a flag to force requantification.

compiler/goal_util.m:
    Fix a misleading predicate name.

compiler/hlds_goal.m:
    Fix documentation of rhs_lambda_goal.

compiler/hlds_out_goal.m:
    Fix a layout problem in HLDS dumps.

compiler/hlds_pred.m:
compiler/lambda.m:
    Fix misleading variable names.

tests/valid/gh98.m:
    Add the github test case.

tests/valid/Mmakefile:
    Enable the new test case.
2021-08-20 20:05:38 +10:00

96 lines
3.4 KiB
Mathematica

%---------------------------------------------------------------------------%
% vim: ts=4 sw=4 et ft=mercury
%---------------------------------------------------------------------------%
%
% Released by Transnat Games as public domain for testing purposes.
% Any copyright is dedicated to the Public Domain.
% https://creativecommons.org/publicdomain/zero/1.0/
%
% Crashes the following error when compiling:
% Uncaught Mercury exception:
% Software Error: map.lookup: key not found
% Key Type: term.var(parse_tree.prog_data.prog_var_type)
% Key Value: var(25)
% Value Type: hlds.hlds_goal.unify_mode
%
%---------------------------------------------------------------------------%
:- module gh98.
:- interface.
:- use_module array.
:- use_module stream.
:- pred crash(Stream::in, stream.result(array.array(int), string)::out,
State::di, State::uo) is det
<= (stream.reader(Stream, int, State, Error), stream.error(Error)).
%---------------------------------------------------------------------------%
:- implementation.
:- use_module string.
% Just using stream.get in crash/4 doesn't trigger the crash.
:- pred get(Stream::in, stream.result(int, string)::out,
State::di, State::uo) is det
<= (stream.reader(Stream, int, State, Error), stream.error(Error)).
get(Stream, Result, !State) :-
stream.get(Stream, NResult, !State),
(
NResult = stream.eof,
Result = stream.eof
;
NResult = stream.error(Error),
Result = stream.error(stream.error_message(Error))
;
NResult = stream.ok(N),
Result = stream.ok(N)
).
%---------------------------------------------------------------------------%
% Removing the typeclass constraint stops the crash.
:- pred crash_loop(Stream::in, int::in, int::out,
{stream.res(string), State}::di, {stream.res(string), State}::uo) is det
<= (stream.reader(Stream, int, State, Error), stream.error(Error)).
crash_loop(_Stream, _N, 0, {Result, !.State}, {Result, !:State}).
%---------------------------------------------------------------------------%
crash(Stream, Result, !State) :-
get(Stream, LenResult, !State),
(
LenResult = stream.eof,
Result = stream.eof
;
LenResult = stream.error(Error),
Result = stream.error(Error)
;
LenResult = stream.ok(Len),
% The crash_loop predicate has two typeclass constraints on it,
% so it takes two typeclass_info arguments. The polymorphism
% transformation, when it converted this implicit lambda expression
% into an explicit lambda expression, did add both typeclass_infos
% to the start of crash_loop's argument list. The bug was that
% it included only one of them in the rhs_lambda_goal's nonlocal set,
% and quantification is not allowed to add any variables to that set.
% Since the actual source of that typeclass_info is the clause head
% (i.e. the crash predicate's own input arguments), this meant that
% one of crash_loop's argument variables was not in the map that
% the compiler tried to look it up in.
Closure = crash_loop(Stream),
array.generate_foldl(Len, Closure, Array,
{stream.ok, !.State}, {LoopResult, !:State}),
(
LoopResult = stream.error(Error),
Result = stream.error(Error)
;
LoopResult = stream.ok,
Result = stream.ok(Array)
)
).