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
unexpected weak type variable in GADT typing #7784
Comments
Comment author: @sliquister
Now, this example is obviously generalizable even if ident did arbitrary side effects, but the typer need to be spoonfed to understand it because the value restriction is restrictive (a smarter check would only prevent generalization of variables involved in the syntactically expansive parts): let ident x = x
let ident0 = ident 0
# Int ident0;; |
Comment author: @ivg Yep, you're right, I don't know why I've decided that Besides, while investigating this issue, I found a small caveat in the non-expansivness checker, that could be shown with the following interaction: type _ exp = Int : 'b -> 'a exp;;
# let f ~y x = x + y;;
val f : y:int -> int -> int = <fun>
let g x ~y = x + y;;
val g : int -> y:int -> int = <fun>
# Int (f ~y:1);;
- : '_a exp = Int <poly>
# Int (g ~y:1);;
- : 'a exp = Int <poly> Basically, the order of parameters matter, as | Texp_apply(e, (_,None)::el) ->
is_nonexpansive e && List.for_all is_nonexpansive_opt (List.map snd el) That basically requires that an application must be abstracted on the first argument only. A more complete check would be | Texp_apply(e, el) ->
is_nonexpansive e &&
List.exists (fun (_,None) -> true | _ -> false) el &&
List.for_all is_nonexpansive_opt (List.map snd el) |
Comment author: @sliquister f ~y:1 can do arbitrary side effects (depending on the definition of f), whereas g ~y:1 cannot (because the type of g says it takes ~x first) so that's why they are generalized differently. If the typer change you suggest generalizes [Int (f ~y:1)], then it's unsound. |
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. |
This is the expected behaviour. The confusion comes from the lack of variance inference for GADTs, which is tracked elsewhere. |
Original bug ID: 7784
Reporter: @ivg
Status: new
Resolution: open
Priority: normal
Severity: minor
Version: 4.02.3
Category: typing
Monitored by: @gasche
Bug description
Consider the following minimized example:
In the following, the type variable
'a
is generalizedHowever if we will substitute the constructor argument with a nonexpansive expression
ident 0
, whereident
isfun x -> x
, then the type variable is not generalized:Expected result - either both expressions should not be generalized or both generalized.
Steps to reproduce
the steps above are reproducible in all compilers starting with 4.02.3 till 4.06. I didn't test other versions.
Additional information
Of course, we can use variance annotations and everything will work as expected. But as always this is a simplified example, a less simplified example is the following:
Unfortunately, variance checker can't cope with the
[> rhs] exp
part.Even when I explicitly specify the variance of the
rhs
type constructor, withI'm still getting
The text was updated successfully, but these errors were encountered: