Skip to content

Commit

Permalink
astgen: forbid trailing whitespace in multiline strings
Browse files Browse the repository at this point in the history
Trailing whitespace in multiline strings is annoying for all the usual
reasons trailing whitespace is annoying (unrelated line changes).

However, in this case it even can leak into whatever the string literal
is used for. For example, in the previous commit there is trailing
whitespace leaking into the help messages.

So it makes sense to forbid this outright.

`zig fmt` intentionally doesn't try to clean up here --- if there's a
trailing whitespace in a multiline literal, it is _ambiguous_ whether
the user added that by accident, or whether they _intended_ to have a
space there.

If you need to have trailing whitespace, you can contatenate `\\` and
`"` strings with `++`:

    const S =
        \\hello
    ++ "  \n" ++
        \\world
        \\
    ;

Closes: ziglang#19299
  • Loading branch information
matklad committed Jul 10, 2024
1 parent d4d5da8 commit e3f8709
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 0 deletions.
15 changes: 15 additions & 0 deletions lib/std/zig/AstGen.zig
Original file line number Diff line number Diff line change
Expand Up @@ -11679,6 +11679,7 @@ fn strLitNodeAsString(astgen: *AstGen, node: Ast.Node.Index) !IndexSlice {
const slice = tree.tokenSlice(tok_i);
const carriage_return_ending: usize = if (slice[slice.len - 2] == '\r') 2 else 1;
const line_bytes = slice[2 .. slice.len - carriage_return_ending];
try astgen.strLitNodeCheckTrailingWhitespace(tok_i, line_bytes);
try string_bytes.appendSlice(gpa, line_bytes);
tok_i += 1;
}
Expand All @@ -11687,6 +11688,7 @@ fn strLitNodeAsString(astgen: *AstGen, node: Ast.Node.Index) !IndexSlice {
const slice = tree.tokenSlice(tok_i);
const carriage_return_ending: usize = if (slice[slice.len - 2] == '\r') 2 else 1;
const line_bytes = slice[2 .. slice.len - carriage_return_ending];
try astgen.strLitNodeCheckTrailingWhitespace(tok_i, line_bytes);
try string_bytes.ensureUnusedCapacity(gpa, line_bytes.len + 1);
string_bytes.appendAssumeCapacity('\n');
string_bytes.appendSliceAssumeCapacity(line_bytes);
Expand All @@ -11699,6 +11701,19 @@ fn strLitNodeAsString(astgen: *AstGen, node: Ast.Node.Index) !IndexSlice {
};
}

fn strLitNodeCheckTrailingWhitespace(
astgen: *AstGen,
tok: Ast.TokenIndex,
line_bytes: []const u8,
) !void {
switch (line_bytes[line_bytes.len - 1]) {
'\t', ' ' => {},
'\r', '\n' => unreachable,
else => return,
}
return astgen.failTok(tok, "multiline string cannot contain trailing whitespace", .{});
}

fn testNameString(astgen: *AstGen, str_lit_token: Ast.TokenIndex) !Zir.NullTerminatedString {
const gpa = astgen.gpa;
const string_bytes = &astgen.string_bytes;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
const S =
\\Hello, world
; // ^^^^^ trailing whitespace here
// error
// backend=stage2
// target=native
//
// :1:5: error: multiline string cannot contain trailing whitespac
//

0 comments on commit e3f8709

Please sign in to comment.