Closed C4Cypher closed 2 months ago
Thanks for the test case. It shows an oversight in the modechecker, which cannot coerce terms that include existential types.
Under the hood, each existentially quantified argument adds a hidden type_info argument, which aren't being accounted for when modechecking coerce
. But there is likely to be more to it.
It's likely the same set of issues (or very closely related) that occur with Mantis bug #89 for inst subtyping.
My pleasure. I want to help in any way I can, and while I haven't dug into the source enough to really grok the compiler yet, I hope, in the future, to help tackle things like fixing unique modes and run-time typeclass introspection. That and I know my way around a bug report. Please let me know if there's anything I can provide that can help further.
Interesting, I'm running into this issue again when passing existentially boxed values to modes that are sub-insts of, but not strictly 'ground'.
:- pragma promise_equivalent_clauses(value_term/1).
value_term(V::in) = ('new mr_value'(V)::out(mercury_value)).
value_term(V2::out) = (mr_value(V1)::in) :- dynamic_cast(V1, V2).
/*
$ mmc --make libmh_term
Making Mercury\int3s\mh_term.int3
Making Mercury\ints\mh_term.int
Making Mercury\cs\mh_term.c
mh_term.m:155: In clause for `value_term(in) = out((mh_term.mercury_value))':
mh_term.m:155: mode error: argument 3 had the wrong instantiatedness.
mh_term.m:155: Final instantiatedness of `HeadVar__2' was
mh_term.m:155: `unique(mr_value(ground, ground))',
mh_term.m:155: expected final instantiatedness was
mh_term.m:155: named inst mercury_value
mh_term.m:155: which expands to
mh_term.m:155: bound(
mh_term.m:155: mr_value(ground)
mh_term.m:155: ).
** Error making `Mercury\cs\mh_term.c'.
*/
I'm assuming that the mode checker is tripping up on the second argument in the inst of 'HeadVar_2', not the uniqueness
P.S. Moving the unification of the headvar and the existential constructor into the body of the clause results in the same error.
value_term(V::in) = (T::out(mercury_value)) :- T = 'new mr_value'(V).
Fixed in rotd-2024-07-11.
I am finding that I get a mode error if I attempt to construct a subtype with an existentially typed subterm and then coerce it to the supertype in the same clause. If I move the constructor to it's own call, the problem does not exhibit. Is this intended behavior and am I missing something about how a constructed existentially typed data type is instantiated?
Unit test example:
I understand the second part of the error message, given that mode analysis cannot ground Foobar if there is a mode error with the coerce expression. What I do not understand is the mode requirements for the coerce expression. Is it the uniqueness of the constructed data term that is causing the error?