Skip to content

Refactor Printtyp: split it in three modules#13336

Merged
gasche merged 6 commits intoocaml:trunkfrom
Octachron:split_printtyp
Aug 1, 2024
Merged

Refactor Printtyp: split it in three modules#13336
gasche merged 6 commits intoocaml:trunkfrom
Octachron:split_printtyp

Conversation

@Octachron
Copy link
Member

This PR proposes to split the Printtyp module in three modules:

  • An Out_type module focused on generating outcome trees (aka close to source tree type expressions) from type expression digraphs. In particular, this is the module that contains the various naming and loop marking context
  • A smaller Printtyp module which only retains printing functions that are safe to use in all circumstances (with restored backward compatibility)
  • A Typerror_report module for generating reports for core-level type errors.

The first two commits in this PR splits the Printtyp module in two (with minimal code changes).

The third one restores backward compatibility with Format printers for the Printtyp printers. This my alternative proposition to #13319.

The fourth commit move a specialized function to its only user in Includemod_errorprinter

The fifth and last commit reorganizes the Out_type and Printtyp modules to provide better documentation and more
self-documenting names. In particular, the four naming contexts (for idents, type variables, internal names and aliases) are named more explicitly.

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.

I agree that the result is better than with my approach (which I suppose inspired commit three, "expose compatibility printers first"), thanks! I left a reasonable amount of review comments, especially on the documentation (moved or new).

.depend Outdated
utils/format_doc.cmi
typing/includeclass.cmo : \
typing/types.cmi \
typing/typerror_report.cmi \
Copy link
Member

Choose a reason for hiding this comment

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

Not fond of the name Typerror_report -- it's three words with two different word-break conventions, and unidiomatic punning of "type error" into "typerror". Maybe Type_error_report or even Report_type_error? I would also find Errortrace_report somewhat more natural (despite also being three words juxtaposed in two different ways), as an extension of the pre-existing module Errortrace. (the disambiguation error does not come from Errortrace, but oh well.) Or just Report_error?

Copy link
Member Author

Choose a reason for hiding this comment

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

I like Errortrace_report since the functions are mostly consumers of error traces, which suggests to move amniguous_type to Typecore.

have been passed to {!prepare_for_printing}. Unlike {!Printtyp.type_expr},
this function does no extra work before printing a type; in particular, this
means that any loops in the type expression may cause a stack overflow (see
#8860) since this function does not mark any loops. The benefit of this is
Copy link
Member

Choose a reason for hiding this comment

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

I now that this comment existed before, but on re-reading here in the context of the global Out_type documentation this is a bit confusing.

Out_type above explains that it tracks context for handling cycles/loops (note: maybe it would be nice to use 'loops' consistently, or 'cycles' consistently), and now we explain that loops are not handled by this function. A reader may naively assume that there is no way to call prepared_type_expr on a type expression that may contain loops, and that another printing function should be used instead. What I understand is that we don´t mean that, we want to point out that the expression should be prepared first.

I think that it should be possible to rephrase the current documentation commend to explain, more directly, that this expects a function that has already been prepared by using prepare_for_printing or add_type_to_preparation.

Copy link
Member Author

Choose a reason for hiding this comment

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

Indeed, I agree that the current formulation can be simplified now that prepared_type_expression is not in competition for reader attention in the same module as type_expression.

(** Add external type equalities*)
val add_subst: (type_expr * type_expr) list -> unit

(** [reserve ty] register the variable names appearing in [ty] *)
Copy link
Member

Choose a reason for hiding this comment

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

registers?

mark_loops x;
mark_loops y;
Aliases.mark_loops x;
Aliases.mark_loops y;
Copy link
Member

Choose a reason for hiding this comment

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

Naive question: why don't we just call List.iter add_type_to_preparation [x; y] here?

Copy link
Member Author

Choose a reason for hiding this comment

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

This should work, and should be enough to remove the Aliases module from the Out_types module.

(** {1 Printing type expressions} *)

(** [prepare_for_printing] resets the global naming environment, a la {!reset},
and prepares the types for printing by reserving names and marking loops.
Copy link
Member

Choose a reason for hiding this comment

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

variable names

type variables. *)

(** [type_expr_with_reserved_names ty] marks loop in [ty] but share names and
ident conflicts with the current variable names context. *)
Copy link
Member

Choose a reason for hiding this comment

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

I found the comment on half-preparation somewhere else useful, maybe it could be partially included here. (Before calling this function, you should reserve variable names and not mark loops; this can be deduced from the current documentation but it is not completely obvious and could be pointed out).

Copy link
Member Author

Choose a reason for hiding this comment

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

I added the comments, but I am starting to wonder if the function is still needed.

Calling this function on non-prepared types may cause a stack overflow (see
#8860) due to cycles in the printed types.

See {!Printtyp.type_expr} for a safer printer. *)
Copy link
Member

Choose a reason for hiding this comment

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

safer (less flexible) printer

@gasche
Copy link
Member

gasche commented Jul 30, 2024

I'm happy with the new batch of commits. I wonder if you have plans to cleanup the history. Except for the history, this is now good to merge.

@Octachron
Copy link
Member Author

I have cleanup the history, I propose to merge by the end of the week to give time for people to raise objections to the refactoring.

@gasche
Copy link
Member

gasche commented Jul 30, 2024

(My gut feeling is that the proposed interface change is a notable improvement, and that the compatibility-restoration part will help people building their code on top of trunk or doing release management as soon as it is merged, so I would go ahead. But you do you.)

@gasche gasche merged commit 3531f30 into ocaml:trunk Aug 1, 2024
punchagan added a commit to punchagan/sandmark that referenced this pull request Aug 2, 2024
This reverts commit e2fa976.

The ocaml/ocaml#13336 PR restored backward compatibility for the
`Printtyp` module and the patch to `base` is no longer required.
punchagan added a commit to ocaml-bench/sandmark that referenced this pull request Aug 2, 2024
This reverts commit e2fa976.

The ocaml/ocaml#13336 PR restored backward compatibility for the
`Printtyp` module and the patch to `base` is no longer required.
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.

2 participants