Mantis Bug Tracker

View Issue Details Jump to Notes ] Issue History ] Print ]
IDProjectCategoryView StatusDate SubmittedLast Update
0006330OCamltypingpublic2014-02-18 17:442017-03-14 09:11
Assigned Togarrigue 
PlatformOSOS Version
Product Version4.01.0 
Target VersionlaterFixed in Version 
Summary0006330: Wrong location for error with polymorphic variant patterns
DescriptionThe following error should really be located at the second case:

   # let f (x: [< `Foo of int | `Bar of float]) =
       match x with
        `Foo x -> x
      | `Baz -> 1
      | _ -> 0;;
   Characters 65-71:
        `Foo x -> x
    Error: This pattern matches values of type [> `Baz | `Foo of 'a ]
           but a pattern was expected which matches values of type
           [< `Bar of float | `Foo of int ]
           The second variant type does not allow tag(s) `Baz
TagsNo tags attached.
Attached Files

- Relationships

-  Notes
gasche (administrator)
2014-02-23 19:00
edited on: 2014-02-23 19:03

I did a bit of work to understand where the issue comes from -- and found out that it was not easily fixable. This will probably be obvious to Leo and Jacques, but I'll still summarize the issue in case anyone is interested.

The error location comes from the way pattern-matching of polymorphic variants are type-checked. First, the type of all the branches are unified together -- and passed through a bit of variant-pressuring magic I don't understand. Then, they are unified with the type of the pattern scrutinee. In this example, unifying both patterns together gives them *both* a type of the form [> `Foo of '_a | `Baz ]. When the `Foo pattern is then unified with the type [< `Foo of int | `Bar of float], you get an error (located at `Foo) about the type `Baz not being possible.

For someone like me that is not familiar with type inference of polymorphic variants, it's not obvious why it wouldn't work to first unify each branch with (an instance of) the scrutinee's type, and then unify the branch together -- a clash between one of the branch and the scrutinee would then be reported where expected. However, doing this does not work (and the implementation is very clear about the fact that the existing order is intended) on some other examples; for example,

  fun x -> match (x : [< `A ]) with `A | `B -> ();;

is accepted by the current type-checking technique (with a warning about the `B being dead code), but would be rejected by trying to unify `B's type with [< `A ].

TL;DR: it's not a silly typo in the location-handling code, it's something subtle about type-checking of polymorphic variants, that is probably not going to change soon - or it needs an expert.

- Issue History
Date Modified Username Field Change
2014-02-18 17:44 lpw25 New Issue
2014-02-23 19:00 gasche Note Added: 0010970
2014-02-23 19:02 gasche Note Edited: 0010970 View Revisions
2014-02-23 19:02 gasche Status new => acknowledged
2014-02-23 19:03 gasche Note Edited: 0010970 View Revisions
2014-07-16 18:26 doligez Target Version => 4.02.1+dev
2014-09-04 00:25 doligez Target Version 4.02.1+dev => undecided
2014-09-15 21:55 doligez Target Version undecided => 4.02.2+dev / +rc1
2015-01-20 22:03 doligez Target Version 4.02.2+dev / +rc1 => 4.02.3+dev
2015-07-10 18:52 doligez Target Version 4.02.3+dev => 4.03.0+dev / +beta1
2016-04-05 15:14 doligez Target Version 4.03.0+dev / +beta1 => 4.03.1+dev
2017-02-16 14:01 doligez Target Version 4.03.1+dev => undecided
2017-02-23 16:45 doligez Category OCaml typing => typing
2017-03-14 09:11 garrigue Assigned To => garrigue
2017-03-14 09:11 garrigue Target Version undecided => later

Copyright © 2000 - 2011 MantisBT Group
Powered by Mantis Bugtracker