mirror of
https://github.com/Mercury-Language/mercury.git
synced 2026-04-18 19:03:45 +00:00
Implement modechecking of coerce in a direct and efficient way.
The old implementation worked by generating a 'bound' inst node for each
node in the type tree (recursively, as far as possible),
calling abstractly_unify_inst, then checking the resulting inst is valid
for the result type. The insts could explode in size for large types.
The new implementation works by simultaneously traversing the input inst
tree, the input type tree, and the result type tree, and producing the
result inst tree for a valid conversion or rejecting the coercion.
Where the input and result types are equal, the result inst can just be
'ground' instead of expanding to a 'bound' inst. Therefore the
result inst does not explode in size compared to the input inst.
While testing, I discovered a couple of cases where the old
implementation would accept coercions that it should not have,
which are rejected by the new implementation.
compiler/modecheck_coerce.m:
Implement the new algorithm.
compiler/mode_errors.m:
Change how we report coerce mode errors as we cannot generate the
same messages as before.
compiler/typecheck.m:
compiler/type_util.m:
Move get_supertype into type_util.m.
doc/reference_manual.texi:
Describe how coerce is mode checked now.
tests/invalid/Mmakefile:
tests/invalid/coerce_int.err_exp:
tests/invalid/coerce_int.m:
tests/invalid/coerce_recursive_inst.err_exp:
tests/invalid/coerce_recursive_inst.m:
tests/invalid/coerce_recursive_type.err_exp:
tests/invalid/coerce_recursive_type.m:
Add new test cases.
tests/invalid/coerce_mode_error.m:
tests/invalid/coerce_mode_error.err_exp:
tests/invalid/coerce_instvar.err_exp:
tests/invalid/coerce_uniq.err_exp:
tests/invalid/coerce_unreachable.err_exp:
Update expected error messages.
33 lines
756 B
Mathematica
33 lines
756 B
Mathematica
%---------------------------------------------------------------------------%
|
|
% vim: ts=4 sw=4 et ft=mercury
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- module coerce_int.
|
|
:- interface.
|
|
|
|
:- type wrap(T)
|
|
---> wrap(T).
|
|
|
|
:- inst wrap(I)
|
|
---> wrap(I).
|
|
|
|
:- implementation.
|
|
|
|
:- func ok(wrap(int)) = wrap(int).
|
|
:- mode ok(in(wrap(bound(1 ; 2 ; 3)))) = out(wrap(bound(3 ; 1 ; 2)))
|
|
is det.
|
|
|
|
ok(X) = coerce(X).
|
|
|
|
:- func bad(wrap(int)) = wrap(int).
|
|
:- mode bad(in(wrap(bound(1 ; 2)))) = out(wrap(bound(1 ; 3)))
|
|
is det.
|
|
|
|
bad(X) = coerce(X).
|
|
|
|
:- func bad_wrong_type(wrap(uint)) = wrap(uint).
|
|
:- mode bad_wrong_type(in(wrap(bound(1 ; 2)))) = out(wrap(bound(1 ; 2)))
|
|
is det.
|
|
|
|
bad_wrong_type(X) = coerce(X).
|