Skip to content
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

#9148 extension constructor printing discrepancy in REPL #9440

Merged
merged 1 commit into from
Sep 9, 2020

Conversation

progman1
Copy link

@progman1 progman1 commented Apr 10, 2020

for a type extension constructor with parameterised arguments,
REPL displayed <poly> for each as opposed to the concrete values used.
patch copies over code used for variant constructors.

@gasche
Copy link
Member

gasche commented Apr 10, 2020

Context for other people: the issue that details the problem is #9418.

Copy link
Member

@gasche gasche left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code looks sensible, thanks, but I would be reassured to see regression tests in the testsuite for this fix. Tests could be written as expect-style tests in a new file testsuite/tests/tool-toplevel/printval.ml -- see tests/tool-toplevel/use_command.ml for an example of expect-style test to reuse.

It would be nice to have first the case that is working well (non-extensible constructor), then the extensible version, and possibly an example with an extensible GADT (if you know how to write those) where there is a difference between the constructor's result type and the type declaration parameters.

List.map
(function ty ->
try Ctype.apply env type_params ty ty_list with
Ctype.Cannot_apply -> abstract_type)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could this logic, which is used in several different places in the module now, be moved to its own auxiliary function?

Changes Outdated
@@ -330,6 +330,9 @@ Working version
on Power and Z System
(Xavier Leroy, review by Nicolás Ojeda Bär)

- #9440: for a type extension constructor with parameterised arguments,
REPL displayed <poly> for each as opposed to the concrete values used.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you include a credit line with your preferred name (we have a preference for full names if you are fine with it), and potentially reviewer names?

@progman1
Copy link
Author

progman1 commented Apr 12, 2020

Ah, the marvel of testing! I hit a snag with the GADT:
type 'a t = ..
type 'a t += T : 'a -> int t

the constructor description of the extension has its cstr_res param set to 'int' rather than a tyvar that corresponds to that in cstr_args, so I don't see how a cstr_arg can get instantiated from a ty_list member (via Ctype.apply).
Indeed this is the variant constructor treatment:
type 'a t = T: 'a -> int t
and gets the same result:
T 'x' : int t = T <poly>
I had hoped that a tydecl.type_params would have the same tyvar as the constructor's cd_args but no! ...different ids which doesn't make sense to me.

@gasche
Copy link
Member

gasche commented Apr 12, 2020

I am not sure from your message whether there is a problem with the new implementation or not. In your example with the extensible GADT, getting T <poly> on T 'a', as in the non-extensible case, is perfectly correct, it is the expected behavior. If this is what you observe, the test is right and there is no issue. If you observe a failure instead, we have an issue to fix in the implementation.

Other tests you could use are

type 'a t += Char : char -> int t;;
Char 'a';;

type 'a t += P : 'a * bool -> 'a t;;
P (2, true);;

type 'a t += Q : 'a -> ('a * bool) t;;
Q 2;;

those should be printed without <poly>.

The reason why <poly> is expected with T : 'a -> int t is that GADTs precisely allow to express cases where there is no relation between the type parameters of the type constructor (t) and the types of the parameters of the variant constructor (T) -- we call those existential types. If one of the parameter has an existential type, there is no static information we can extract from the whole value type, so it must be printed <poly>.

@progman1
Copy link
Author

thanks for that explanation. then there is no problem after all.
I had imagined only

type 'a t = T: 'b -> int t

entailed an existential type in 'b

so are:

type 'a t = T: 'a -> int t
type 'a t = T: 'b -> int t
type _ t = T: 'b -> int t

equivalent?

@gasche
Copy link
Member

gasche commented Apr 12, 2020

Yes, in GADT constructors the type-declaration parameters are not in scope. This is why it is customary to use _ there when defining GADTs (at least when all constructors are GADT).

@gasche
Copy link
Member

gasche commented Apr 12, 2020

Actually, could you use type _ t += ... in the GADT-extension cases in the test?

Otherwise the code looks very nice to me now, this is good to merge if/when the CI agrees. Thanks!

@damiendoligez
Copy link
Member

ping @gasche

@gasche
Copy link
Member

gasche commented Sep 8, 2020

Ah, apologies for dropping the ball on this issue. I need to rebase the PR, but hopefully it is still good to merge.

fixes ocaml#9148

genprintval.tree_of_extension was missing instantiation of constructor argument types.
the Ctype.apply code is factorized out from a number of other places.
@gasche gasche merged commit 9c5a2ef into ocaml:trunk Sep 9, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants