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
Wrong error: "The type constructor X.t would escape its scope" #6150
Comments
Comment author: @damiendoligez I'm lowering the severity from "block" to "major" because, unless I'm mistaken, you can work around the bug by specifying a more precise type instead of 'a -> 'b. |
Comment author: @damiendoligez Also, I'll let the typing specialists give a better answer, but it seems to me that the error message is correct. The problem is in the binding of the type variables ('a and 'b): they have no syntactic binder, so in OCaml they are implicitly bound at the top-level let (in this case, your "let f () =..."). Hence, the X.t does escape its scope, even if in this case you don't use it ouside its scope. Now I agree this is annoying and maybe there is something that can be done about it. |
Comment author: pw374 Sorry I didn't quite know what "block" meant, I picked it while I was actually searching for one less severe than "major" but more severe than "minor". (I did work around the bug by removing the type constraint but it made me lose quite some time while I was trying to figure out whether I was insane or if the compiler was "probably wrong", since I almost never find bugs.) I don't (want to) see why an 'a would be bound to the top-level let, since at the end g is monomorphic (hence 'a should "disappear"), and even f is monomorphic as well. |
Comment author: @garrigue The standard way to write a skeleton is to use anonymous type variables _ . |
Comment author: pw374 Thanks for the _ -> _. In the following example, you might not want to write _ -> _ but 'a -> 'a to ensure that both left and right parts of the arrow are the same. If there are special cases where it would be wrong to accept such a program, then I'd be ok with it, as for the value restriction. But I really don't see any. Can't we remove binding at the top-level LET for types that actually bind nothing? |
Comment author: @garrigue There is a confusion here. There are some ways around this limitation, such as anonymous type variables, or explicit polymorphism Now you could discuss whether this is expressive enough. Yet, this is not the only problem type definition scope. let r = ref [] |
Comment author: pw374 Ok, thanks. So the problem is that by writing that 'a, the type X.t is "seen" above its definition, hence the escaping error. In your example, in my opinion, the error message given by the compiler is a bug (not that there's not an error, but the formulation of the message is very wrong). In the following example, the error message is also very disturbing. I get the error message with 4.01.0+dev or 4.02.0+dev, with previous versions it asserts false. class type t = t;;Error: The class type t is not yet completely defined Sometimes, it would be better for the message to be something like "Error: sorry I can't (yet) explain." or just "Error." instead of some insane phrases. Would it be worth proposing patches for such things? (or should I wait until it gets better, or abandon?) |
Comment author: @garrigue Ah, error messages! I try to fix them when I can, but the problem is that an error message which makes sense in one context doesn't make sense in another, and it is very hard to see all the cases in advance (and to avoid making the core overly complicated). For instance,
For the scoping messages, this is even harder, as the cause is hard to track. Proposing patches is not going to help much, except if you also provide a big test suite to ensure that all cases were taken into account. Otherwise the situation might be worse than before. |
Comment author: @edwintorok I just had one of those "head scratching" moments on the code below, and I only realized what is wrong when moving the 'type foo' above the 'global' fixed the compiler error (I encountered the error before but only with first class modules). Would it be possible for the compiler to report the scope of the variable even if the cause of the escape is not easy to determine? For example add the info marked with ++: File "x.ml", line 13, characters 26-31: This has the advantage that it tells you where the code you need to fix probably is (type annotations, or moving declarations), i.e. the negation of the scope (line 10, character 6 and EOF). module M :sig let global = M.v () (* line 9 ) |
Original bug ID: 6150
Reporter: pw374
Assigned to: @garrigue
Status: closed (set by @xavierleroy on 2016-12-07T10:49:25Z)
Resolution: not a bug
Priority: normal
Severity: major
Version: 4.00.1
Target version: 4.01.1+dev
Category: typing
Has duplicate: #6264
Related to: #8391
Monitored by: pw374 @gasche
Bug description
"The type constructor X.t would escape its scope" while it wouldn't.
This error is likely caused by the use of a simple (potentially polymorphic) type annotation, such as in (foo:'a).
Proving why it actually is a bug:
Steps to reproduce
let f () =
let module X = struct type t = O end in
let open X in
let g : 'a -> 'b = function O -> () in
g(O)
Additional information
In "let g : 'a -> 'b = function O -> () in", the type constraint "'a -> 'b" is the only way that I can think of to constrain g to be an arrow (without having to precisely specify the left and right parts of the arrow).
I met this bug by accident in a small piece of software (4 kloc), I didn't mean to find it, and it was pretty annoying :(
The text was updated successfully, but these errors were encountered: