Skip to content

Bug: Module/functor arguments with "module type of" malformatted #2776

@JanBeh

Description

@JanBeh

Bug description:

Given a functor with three arguments of which the second has a module type denoted with a module type of statement referring to the previous functor argument, the resulting line-breaking and indentation seems to be wrong, at least in some cases.

Reproduction:

The bug should be reproducible as follows. Use ocamlformat version 0.28.1:

$ ocamlformat --version
0.28.1

Create a .ocamlformat file with:

ocaml-version=5.4

Create a file formatbug.ml with:

module M
    (Ord : Set.OrderedType)
    (SomeSet : module type of Set.Make (Ord))
    (SomeOtherFunctorArgument : Set.OrderedType) =
struct
  let f = SomeSet.singleton
end

Runing ocamlformat formatbug.ml gives:

module M
    (Ord : Set.OrderedType)
    (SomeSet :
      module type of Set.Make (Ord))
        (SomeOtherFunctorArgument : Set.OrderedType) =
struct
  let f = SomeSet.singleton
end

What I expect instead:

I would expect all functor arguments to be idented with the same level (as in the input). Also, I would not expect a line break after "SomeSet :".

Cases that work correctly:

Note that the following files result in identical output (i.e. the indentation remains correct):

module M
    (Ord : Set.OrderedType)
    (SomeSet : module type of Set.Make (Ord)) =
struct
  let f = SomeSet.singleton
end
module M
    (Ord : Set.OrderedType)
    (SomeSet : Set.S with type elt = Ord.t)
    (SomeOtherFunctorArgument : Set.OrderedType) =
struct
  let f = SomeSet.singleton
end
module M =
functor
  (Ord : Set.OrderedType)
  (SomeSet : module type of Set.Make (Ord))
  (SomeOtherFunctorArgument : Set.OrderedType)
  ->
  struct
    let f = SomeSet.singleton
  end

Used configuration:

Querying the configuration gives the following result:

$ ocamlformat --print-config
comment-check=true
debug=false
disable=false
margin-check=false
max-iters=10
ocaml-version=5.4 (file .ocamlformat:1)
quiet=false
disable-conf-attrs=false
version-check=true
assignment-operator=end-line
break-before-in=fit-or-vertical
break-cases=fit
break-collection-expressions=fit-or-vertical
break-colon=after
break-fun-decl=wrap
break-fun-sig=wrap
break-infix=wrap
break-infix-before-func=false
break-separators=after
break-sequences=true
break-string-literals=auto
break-struct=force
cases-exp-indent=4
cases-matching-exp-indent=normal
disambiguate-non-breaking-match=false
doc-comments=after-when-possible
doc-comments-padding=2
doc-comments-tag-only=default
dock-collection-brackets=true
exp-grouping=preserve
extension-indent=2
field-space=loose
function-indent=2
function-indent-nested=never
if-then-else=compact
indent-after-in=0
indicate-multiline-delimiters=no
indicate-nested-or-patterns=unsafe-no
infix-precedence=indent
leading-nested-match-parens=false
let-and=compact
let-binding-indent=2
let-binding-deindent-fun=true
let-binding-spacing=compact
let-module=compact
line-endings=lf
margin=80
match-indent=0
match-indent-nested=never
max-indent=68
module-indent=2
module-item-spacing=compact
nested-match=wrap
ocp-indent-compat=false
parens-ite=false
parens-tuple=always
parens-tuple-patterns=multi-line-only
parse-docstrings=true
parse-toplevel-phrases=false
sequence-blank-line=preserve-one
sequence-style=terminator
single-case=compact
space-around-arrays=true
space-around-lists=true
space-around-records=true
space-around-variants=true
stritem-extension-indent=0
type-decl=compact
type-decl-indent=2
wrap-comments=false
wrap-fun-args=true
profile=default

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions