Mercury-Language / mercury

The Mercury logic programming system.
Other
906 stars 54 forks source link

Software Error: predicate `ll_backend.basic_block.extend_basic_blocks'/5: Unexpected: fall through m ismatch #133

Open C4Cypher opened 3 months ago

C4Cypher commented 3 months ago

In the process of trying to satisfy a mode transformation on a sum algebraic type, I've run into a curious compiler error. If I create a discriminated union with both existential and universally typed constructors (foo and barX respectively in the example provided) ... the MMC will not allow me to switch on the type if it has more than ten constructors, producing the error

Uncaught Mercury exception:
Software Error: predicate `ll_backend.basic_block.extend_basic_blocks'/5: Unexpected: fall through m
ismatch

I tested the limits of the error by 1. removing the existentially typed data constructor (in the example: some [T] foo(T) ) or 2. removing the barX constructors until I could compile without the error. I'm not exactly sure why the limit seems to be ten constructors. It's an odd corner case, because if the existentially typed constructor is not present, the universally typed constructors compile fine without apparent limit, and conversely if the number of universally typed constructors is less than ten, it also compiles fine.

Example module:

%-----------------------------------------------------------------------------%
% vim: ft=mercury
%-----------------------------------------------------------------------------%
% No Copyright or licence info, this is a testing snippet, no rights claimed.
%-----------------------------------------------------------------------------%

:- module fallthrough_mismatch_test.

:- interface.

:- import_module io.

:- type foo
    --->    /*some [T] foo(T)  % Compiles and runs successfully until coment block is removed
    ;       */bar1(int)
    ;       bar2(int)
    ;       bar3(int)
    ;       bar4(int)
    ;       bar5(int)
    ;       bar6(int)
    ;       bar7(int)
    ;       bar8(int)
    ;       bar9(int)
    ;       bar10(int)%. /* % Commented out comment block used to test number of constructors
    ;       bar11(int)
    ;       bar12(int).%*/

:- type bar =< foo
    --->    bar1(int)
    ;       bar2(int)
    ;       bar3(int)
    ;       bar4(int)
    ;       bar5(int)
    ;       bar6(int)
    ;       bar7(int)
    ;       bar8(int)
    ;       bar9(int)
    ;       bar10(int)%. /*
    ;       bar11(int)
    ;       bar12(int).%*/

:- inst bar
    --->    bar1(ground)
    ;       bar2(ground)
    ;       bar3(ground)
    ;       bar4(ground)
    ;       bar5(ground)
    ;       bar6(ground)
    ;       bar7(ground)
    ;       bar8(ground)
    ;       bar9(ground)
    ;       bar10(ground)%. /*
    ;       bar11(ground)
    ;       bar12(ground).%*/

:- pred is_bar(foo::(ground >> bar)) is semidet.

:- pred main(io::di, io::uo) is det.

%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%

:- implementation.

:- import_module string.

is_bar(T) :- 
    T = bar1(_); 
    T = bar2(_); 
    T = bar3(_); 
    T = bar4(_); 
    T = bar5(_); 
    T = bar6(_); 
    T = bar7(_); 
    T = bar8(_); 
    T = bar9(_); 
    T = bar10(_);%. /*; 
    T = bar11(_);
    T = bar12(_). %*/

main(!IO) :-
    ( if
        X:foo = bar1(5),
        is_bar(X),
        Y:bar = coerce(X)
    then
        write_line("Test succeeded. Y = " ++ string(Y), !IO)
    else
        write_line("Test failed.", !IO)
    ). 

I had been trying to create a discriminated union of every primitive mercury data type, including an existentially typed constructor for non primitive types when I ran into this issue. I can easily work around this by using the univ type ... if I end up needing class constraints I can be creative in finding alternatives.

Please let me know if there is any further information I can provide, or if anyone has problems reproducing the issue.

zsomogyi commented 3 months ago

I just committed a fix for this bug. It should be in the next release-of-the-day.

Thank you for the precise bug report.

C4Cypher commented 2 months ago

My pleasure. I currently stick to the major releases, for now, but the next time I build a newer version of the mmc I'll try to follow up and validate the fix action.