-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Univars can escape through polymorphic variants #6744
Comments
Comment author: @lpw25 In fact, unification of closed polymorphic variants containing univars behaves strangely even without an escaping univar:
|
Comment author: @lpw25 Here's a slightly clearer example of a univar escaping:
Note the |
Comment author: @garrigue Thanks for the report. I'm not 100% sure which is right: in theory, all your examples should be rejected, because a universal variable cannot appear inside a non-quantified flexible variant type. I.e., what you really want to write (and is accepted) is: Yet, in practice ocaml tries to do more than that, by allowing "known fields" to contain universal variables. I.e., the implementation uses row variables rather than kinded variables, so that these fields are not seen as being "under" the row variable, but rather as "siblings". This works as expected in normal mode, but , there are some problems in principal mode. Maybe it is better to follow the theory... |
Comment author: @garrigue Committed the patch in trunk, at revision 15780. |
I came to this code/patch while trying to understand how (* PR#6744 *)
let split_univars =
List.partition
(fun ty -> try occur_univar !env ty; true with Unify _ -> false) in
let (tl1',tlu1) = split_univars tl1'
and (tl2',tlu2) = split_univars tl2' in
begin match tlu1, tlu2 with
[], [] -> ()
| (tu1::tlu1), _ :: _ ->
(* Attempt to merge all the types containing univars *)
if not !passive_variants then
List.iter (unify env tu1) (tlu1@tlu2)
| (tu::_, []) | ([], tu::_) -> occur_univar !env tu
end; What I think the code does is that it tries to "remove" conjuncts that may contain an escaping univar. It first computes all those conjuncts on both side (this is
Obviously the first situation is correct (it makes sense to fail if there is an escaping univar). But why would the second situation be correct? @garrigue wrote the following:
I suppose that this is related: maybe "known field" means "a conjunct with at least one case". But I don't understand the relation to what happens in this case, because:
In which of the two situations do Leo's examples, or the examples Jacques added in the testsuite, fall into? If I understand correctly Leo's example, there is only one univar-conjunct on one side and none on the other, so it is in situation (1) which I understand. Do we have testsuite examples that correspond to situation (2)? |
The point is that More precisely, any scheme where each univar on one side is unified with a univar on the other side would be sound, but since there is no best choice in general, we end up unifying all the univars together. This case is supposed to be rare enough, and in meaningful cases the unification should succeed. |
#9612 adds a few extra examples, but due to other bugs or limitations, we cannot really exercise all cases in this code. |
This issue has been open one year with no activity. Consequently, it is being marked with the "stale" label. What this means is that the issue will be automatically closed in 30 days unless more comments are added or the "stale" label is removed. Comments that provide new information on the issue are especially welcome: is it still reproducible? did it appear in other contexts? how critical is it? etc. |
Looks safe to close this now, after the merging of #9612 last year. |
Original bug ID: 6744
Reporter: @lpw25
Assigned to: @garrigue
Status: assigned (set by @garrigue on 2015-01-16T15:37:54Z)
Resolution: open
Priority: normal
Severity: minor
Target version: later
Category: typing
Related to: #7741
Bug description
When a unifying closed polymorphic variant types (e.g. [< `Foo of int]) there is no equivalent of the occur_univars check. This can allow univars to escape, for example:
In this example, the escaped univar doesn't get very far because it triggers an module inclusion error of the
n
value with itself, and I have not been able to produce an example of genuine unsoundness because of this bug. However, it is clearly not correct to allow the variable to escape like this, and could potentially be unsound.File attachments
The text was updated successfully, but these errors were encountered: