ppx_deriving icon indicating copy to clipboard operation
ppx_deriving copied to clipboard

type nonrec is ignored, causing an infinite loop

Open emillon opened this issue 7 years ago • 6 comments

Hi,

I'm trying to use is with type nonrec but it seems that this annotation is ignored.

Example:

type t = int
[@@deriving ord]

module M = struct
  type nonrec t = t
  [@@deriving ord]
end

let () = Printf.printf "%d\n" (M.compare 1 2)

This triggers an infinite loop instead of calling the top-level compare function.

Thanks for this great project!

emillon avatar Nov 07 '16 15:11 emillon

Please note that I do not have much time to maintain this library, and will not fix this bug. I can offer you assistance in writing a PR though.

whitequark avatar Nov 09 '16 21:11 whitequark

Sure, I'd be interested. Any pointers would be appreciated.

emillon avatar Dec 06 '16 13:12 emillon

@emillon Sure. First, try compiling your code using ocamlc -dsource. This will output the preprocessed source as currently used. I think you will quickly spot why implementing type nonrec is problematic; this messes rather badly with the hygiene mechanism. (Also try using [@@deriving] with a let..and phrase to see the source of additional complexity.)

whitequark avatar Dec 07 '16 16:12 whitequark

I think rewriting the output of ppx_deriving such that it works with type nonrec will already go a long way towards fixing this.

whitequark avatar Dec 07 '16 16:12 whitequark

This issue is mentioned in Facebook's Infer Contributors Guide.

XVilka avatar Nov 01 '19 07:11 XVilka

Recent versions of ppx_deriving (4.1.5 (released in November 2017) and later) show an error when nonrec is used, so at least there is no silent production of looping code anymore.

I had a look last week and my impression is that it is not an easy problem to solve. At first it looks like just not adding the rec keyword would make the resulting code sensible for a nonrec type (the name of the generated function would refer to the generated function of the previous type of the same name, which is what we want), but in fact the structure of the returned code is decided by the plugins, not by the API module (which mostly provide helpers to make plugin life easier), so (1) fixing this issue would require a change in each of the plugins and (2) we have to do some API design/changes if we want to push more logic into the API module. Then I ran out of time for the day, and I stopped looking at it.

Remark: some plugins have evolved in a way that uses the recursivity of the generator for convenience; for example show generates a show and pp function, the definition of show depends on pp, but there is no explicit sequencing of declarations as they are in a big mutually-recursive block. To stop being recursive by default, we have to break those mutual blocks in the plugins.

gasche avatar Nov 07 '19 12:11 gasche