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.
51 lines
1.1 KiB
Mathematica
51 lines
1.1 KiB
Mathematica
%---------------------------------------------------------------------------%
|
|
% vim: ts=4 sw=4 et ft=mercury
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- module coerce_recursive_inst.
|
|
:- interface.
|
|
|
|
:- type rec(T)
|
|
---> nil
|
|
; cons(T, rec(T)).
|
|
|
|
:- inst rec for rec/1
|
|
---> nil
|
|
; cons(ground, rec).
|
|
|
|
:- inst cons for rec/1
|
|
---> cons(ground, rec).
|
|
|
|
:- type fruit
|
|
---> apple
|
|
; orange
|
|
; lemon.
|
|
|
|
:- type citrus =< fruit
|
|
---> orange
|
|
; lemon.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- implementation.
|
|
|
|
% convert subtype to supertype
|
|
:- func good(rec(citrus)) = rec(fruit).
|
|
:- mode good(in(cons)) = out(cons) is det.
|
|
|
|
good(X) = coerce(X).
|
|
|
|
% cannot convert supertype to subtype
|
|
:- func bad1(rec(fruit)) = rec(citrus).
|
|
:- mode bad1(in(cons)) = out(cons) is det.
|
|
|
|
bad1(X) = coerce(X).
|
|
|
|
% cannot convert supertype to subtype
|
|
:- func bad2(rec(fruit)) = rec(citrus).
|
|
:- mode bad2(in(cons)) = out is det.
|
|
|
|
bad2(X) = coerce(X).
|
|
|
|
%---------------------------------------------------------------------------%
|