Mercury Bugs - mercury
View Issue Details
0000356mercuryBugpublic2014-08-30 10:302014-08-31 11:11
ReporterC4Cypher 
Assigned To 
PrioritynormalSeveritycrashReproducibilityalways
StatusnewResolutionopen 
Platformx86_64-pc-linux-gnuOSUbuntuOS Version14.04 'Trusty'
Product Version 
Target VersionFixed in Version 
Summary0000356: mmc exception thrown from instmap.m line 600
DescriptionOkay, I'm still going through it all, I'm just floored that I got mmc to spit out a runtime error.

Making Mercury/asm_fast.gc.trseg.debug.stseg/x86_64-pc-linux-gnu/Mercury/cs/luaMR.state.c
Uncaught Mercury exception:
Software Error: hlds.instmap: predicate `hlds.instmap.instmapping_set_vars_corresponding'/4: Unexpected: not_reached

Here's a pastebin of the source I was working on: http://pastebin.com/Z6Fau9b3

The lines that I was editing (trying to get the switch to infer as det) when mmc started to throw exceptions are 682 - 684. The entire clause is pasted for convenience.

lua_pcall(L, A) = R :-
    impure Result = lua_pcall(L, A, 0),
    ( Result = returned(R) % line 682
    ; Result = returned_error(Error), throw(Error)
    ; unexpected($module, $pred, "Invalid result value. (WTF?)") % line 684
    ).

Using if-> calls rather than raw disjuncts originally triggered this. I'm going to be focusing on trying to re-arrange this clause in a manner that does not cause mmc to toss cookies.

I've located the exception I've triggered in the source, instmap.m line 600, although I don't know the inner workings of the compiler to begin knowing how to interpret it.

expect(negate(unify(Inst, not_reached)), $module, $pred, "not_reached"),


Note: I also compiled the same code under asm_fast.gc.trseg and got the same response.
Steps To ReproduceI've created a branch from my project with my code in the exact state it was in when I produced this issue:

https://github.com/C4Cypher/Apollo-lander/tree/mmc-exception-thrown-from-instmap.m-line-600

I was able to produce this with the line

mmc --make testluaMR

with both asm_fast.gc.trseg.debug.stseg and asm_fast.gc.trseg

emphasis placed on the options I'm using in Mercury.options
Additional InformationI'm at a loss. This library is in mid-development, and as such, it's very unstable ... I'm a long way from making a stable release. Please let me know if there's any kind of information that might help provide more light on this.
TagsNo tags attached.
Attached Files

Notes
(0000769)
C4Cypher   
2014-08-30 10:39   
I forgot to mention that this was all on mercury 14.01

These are the availible grades I have installed are:

asm_fast.gc asm_fast.gc.trseg.debug.stseg
asm_fast.gc.debug.stseg asm_fast.par.gc.stseg
asm_fast.gc.decldebug.stseg hlc.gc
asm_fast.gc.memprof hlc.gc.pregen
asm_fast.gc.prof hlc.gc.trseg
asm_fast.gc.profdeep hlc.par.gc
asm_fast.gc.trseg libgc.a
(0000770)
C4Cypher   
2014-08-30 11:23   
(Last edited: 2014-08-30 11:27)
I think I found my mistake in api.m

line 251: :- impure func lua_pcall(lua, int) = int.
should be: :- impure func lua_pcall(lua, int) = lua_result.

I'm not experienced with C ... but C's laziness as to true type safety is making me lazy as to casts between equivalent C types.

the actual lua.h's lua_pcall returns an int, and I've defined several DU types related to the output of lua_pcall:

:- type lua_result
    ---> returned(int)
    ; returned_error(lua_error).

:- type lua_error
    ---> lua_error(error_type, string).

:- type error_type
    ---> no_error
    ; runtime_error
    ; syntax_error
    ; memory_error
    ; unhandled_error.

:- pragma foreign_enum("C", error_type/0,
[
    no_error - "0",
    runtime_error - "LUA_ERRRUN",
    syntax_error - "LUA_ERRSYNTAX",
    memory_error - "LUA_ERRMEM",
    unhandled_error - "LUA_ERRERR"
]).

I'm still not sure what's exactly is causing the runtime error, but my code, in terms of what I've linked in the branch in the reproduction section, treats mercury code type safety as if it were C type safety (with certain implicit casts assumed).

To be specific, I beleive that the runtime error was produced by my inadvertant attempt to implicitly cast int.int to luaMR.api.lua_result.

(0000771)
C4Cypher   
2014-08-30 11:52   
Okay, I've corrected the type saftey issue I've found in api.m, but I'm still producing the same runtime error from mmc.

Here's the corrected branch: https://github.com/C4Cypher/Apollo-lander/tree/mmc_exception_thrown_instmap2
(0000772)
zs   
2014-08-30 12:16   
The compiler abort is actually coming when the compiler is mode checking trail_to_func in state.m; specifically, when it is mode checking the unification that binds F to the lambda goal on line 236 of state.m. As far as I can tell, it has nothing to do with the code in api.m.

The call that leads to the compiler abort is in modecheck_unify.m at line 440.
The not_reached inst belongs to R (var6), which is a nonlocal of the lambda expression.
(0000773)
wangp   
2014-08-30 12:20   
trail_to_func is the function causing the compiler to abort. Changing the code in any number of ways will work around the issue.
(0000774)
C4Cypher   
2014-08-30 12:59   
Interesting, and yeah, looking at this now, I failed at logic in a strange manner

trail_to_func(Trail) = Func :- % Trail := discriminated union
 ( wtf_goal(Trail, Func) ) -> Func = ( lambada_goal ) ; unexpected($module, $pred, "derp").

What I actually intended was to bind Func to lambada_goal, iff wtf_goal fails to bind Func to a ho value.

What my pred actually did was, on some branches, bind Func to a ho value of type impure func(lua::in) = (int::out), and then on success, unify Func again with another lambada of that same type.

I can correct this, thanks both of you for pointing out where things were going pear shaped. Thanks again for what has otherwise been an absolutely awsome compiler.
`
(0000775)
C4Cypher   
2014-08-31 11:09   
(Last edited: 2014-08-31 11:11)
I'd like to thank the team for the quick response and the assistance.

I'm not certain what caused the runtime error, but I was able to rewrite my code in a manner that the compiler likes.

trail_to_func(unique_state(L, _, T)) = F :-
    require_complete_switch [T] some [R]
    ( T = lua_func(F0) -> F = F0
    ; T = empty_trail ->
        F = ( impure func(_::in) = (0::out) is det :- true )
    ; T = c_function(C) ->
        impure lua_pushcfunction(L, C),
        semipure R = lua_toref(L, index(-1)),
        impure lua_pop(L, 1),
        F = ref_to_func(R)
    ; T = ref(R) ->
        F = ref_to_func(R)
    ; unexpected($module, $pred,
            "Unknown lua_trail value provided.")
    ).

Given that I've found something that works, from my end, I consider the matter closed, however, if there's any way I can assist, please let me know.


Issue History
2014-08-30 10:30C4CypherNew Issue
2014-08-30 10:39C4CypherNote Added: 0000769
2014-08-30 11:23C4CypherNote Added: 0000770
2014-08-30 11:27C4CypherNote Edited: 0000770bug_revision_view_page.php?bugnote_id=770#r31
2014-08-30 11:52C4CypherNote Added: 0000771
2014-08-30 12:16zsNote Added: 0000772
2014-08-30 12:20wangpNote Added: 0000773
2014-08-30 12:59C4CypherNote Added: 0000774
2014-08-31 11:09C4CypherNote Added: 0000775
2014-08-31 11:10C4CypherNote Edited: 0000775bug_revision_view_page.php?bugnote_id=775#r33
2014-08-31 11:11C4CypherNote Edited: 0000775bug_revision_view_page.php?bugnote_id=775#r34