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

Broken toplevel printing for types and modules (rec/nonrec not shown correctly) #7453

Closed
vicuna opened this issue Jan 7, 2017 · 11 comments
Closed

Comments

@vicuna
Copy link

vicuna commented Jan 7, 2017

Original bug ID: 7453
Reporter: @yallop
Assigned to: @diml
Status: assigned (set by @diml on 2017-01-13T17:39:51Z)
Resolution: open
Priority: normal
Severity: minor
Category: toplevel
Monitored by: @gasche @hcarty

Bug description

Recursive type definitions are incorrectly displayed as explicitly non-recursive definitions:

# #show list;;
type nonrec 'a list = [] | (::) of 'a * 'a list
# type t = T of t;;
type t = T of t
# #show t;;
type nonrec t = T of t

And recursive module definitions are incorrectly displayed as implicitly non-recursive definitions:

# module rec M : sig type t val x : M.t end = struct type t = int let x = 0 end;;
module rec M : sig type t val x : M.t end
# #show_module M;;
module M : sig type t val x : M.t end
@vicuna
Copy link
Author

vicuna commented Jan 13, 2017

Comment author: @diml

I had a look at this. I wrote two small functions to check if a type/module is recursive and select the rec_status field in the implementation of "show_XXX" according to this. The branch is here:

https://github.com/diml/ocaml/tree/fix-toplevel-type-and-module-printing

It seems to work, there is just a bug when calling #show_module multiple times that I haven't fixed yet.

Another approach would be to record the recursive status inside the type/module declaration, so that the output of #show matches what the user wrote. Currently you get nonrec if the type is not in fact recursive:

# type t = int;;
type t = int
# #show t;;
type nonrec t = int

@vicuna
Copy link
Author

vicuna commented Jan 13, 2017

Comment author: @yallop

Thanks for looking at this.

I don't think that preserving what the user wrote is especially worthwhile; the important thing is that what is printed is as close to correct as possible. If it's not too difficult, I think the best scheme would be:

  • default to printing 'module' and switch to 'module rec' where the module type mentions the module name. I think this is what you've implemented already.

  • default to printing 'type' and switch to 'type nonrec' where necessary (i.e. where the type definition would mean something different if you left out the 'nonrec'). This is a bit different to your current scheme.

For actually-recursive types there's no difference between your current scheme and the proposal above. And there's no difference for types that actually need 'nonrec', either. The only difference is for non-recursive types that can be written equivalently either with or without 'nonrec', such as 'type t = int', and it's best if those are printed as simply as possible.

@vicuna
Copy link
Author

vicuna commented Nov 29, 2017

Comment author: voglerr

Is there something blocking this?
Had a bit of a problem explaining this to students...

default to printing 'type' and switch to 'type nonrec' where necessary
best if those are printed as simply as possible

Sounds perfect.

@vicuna vicuna assigned ghost Mar 14, 2019
@vicuna vicuna added the bug label Mar 20, 2019
@github-actions
Copy link

github-actions bot commented May 9, 2020

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.

@yallop
Copy link
Member

yallop commented May 9, 2020

The code in the problem report now works in trunk:

# #show list;;
type 'a list = [] | (::) of 'a * 'a list
# type t = T of t;;
type t = T of t
# #show t;;
type t = T of t

But printing types defined using nonrec doesn't use nonrec, so there's still a bug:

# type nonrec list = T of int list;;
type nonrec list = T of int list
# #show list;;
type list = T of int list

@gasche
Copy link
Member

gasche commented May 9, 2020

I added a known-bug test for these faulty (non)use of rec by the #show command in f7ec223.

One slightly strange behavior of the test, unrelated to the present discussion (it is not with #show but with standard toplevel printing) is the scoping-incorrect use of a M/2 stamp in the second declaration below (cc @Octachron ; I believe this is a known and tolerated misbehavior but I couldn't find an issue to reference).

# module M : sig end = struct end;;
module M : sig  end
# module rec M : sig type t = Loop of M.t end = struct type t = Loop of M.t end;;
module rec M : sig type t = Loop of M/2.t end

@gasche gasche removed the Stale label May 9, 2020
@Octachron
Copy link
Member

The printing issue is an instance of #8917. There is a fix for the bug, #8929, waiting for a review too.

@github-actions
Copy link

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.

@github-actions github-actions bot added the Stale label May 14, 2021
@yallop
Copy link
Member

yallop commented May 14, 2021

This is not quite fixed yet: @gasche's broken_rec_in_show.ml tests still fail in trunk.

@gasche gasche removed the Stale label May 14, 2021
@Octachron
Copy link
Member

All examples are fixed by #10416 (and this time without fatal errors when -short-paths is enabled). There are still some case that are not perfectly printed, when the displayed fragment of a group of mutually recursive definitions is not self-recursive. But that only happens for unprintable type definitions (e.g.

type t;;
type u = [ `U of t]
type t = A of [ u | `V ] | B of s
and s = C of t;;
#show t;;

) and recursive modules.

@yallop
Copy link
Member

yallop commented May 19, 2021

Thank you, @Octachron!

@yallop yallop closed this as completed May 19, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants