Skip to content

bsc -format changes string literals that contain line breaks, and is not idempotent on \r\r\n #9100

Closed

Description

@cristianoc

Found by a bug hunt over the 16 commits from eb087382 to cd641cbc.

Since #9042, formatting rewrites raw line breaks inside string literals, which changes the program. Here is a CRLF file whose string contains a raw LF:

printf 'let x = 1\r\nlet s = "a\nb"\r\n' > A.res
bsc A.res | grep 'let s'            # let s = "a\nb";
bsc -format A.res > B.res
bsc B.res | grep 'let s'            # let s = "a\r\nb";

The reverse case is an LF file whose string contains a raw CRLF (printf 'let x = 1\nlet s = "a\r\nb"\n'). Formatting turns the string "a\r\nb" into "a\nb".

Formatting is also not idempotent when a comment contains \r\r\n in an LF file:

printf 'let x = 1\n/* a\r\r\nb */\nlet y = 2\n' > C.res
bsc -format C.res > C1.res
bsc -format C1.res > C2.res
cmp C1.res C2.res                   # differ: C1 has "a\r\n", C2 has "a\n"

At b123b7c3 both cases keep the bytes unchanged.

Cause

Res_line_endings.to_lf and to_crlf rewrite the whole source text, string literals included. to_lf runs whenever the source contains a \r, and each run drops only the \r directly before a \n. They are called from res_multi_printer.ml (bsc -format), res_cli.ml, and the editor's format command (analysis/src/commands.ml).

🤖 Generated with Claude Code

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions