Skip to content

Allow any statement in loop bodies #5731

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
ifreund opened this issue Jun 27, 2020 · 6 comments
Open

Allow any statement in loop bodies #5731

ifreund opened this issue Jun 27, 2020 · 6 comments
Labels
proposal This issue suggests modifications. If it also has the "accepted" label then it is planned.
Milestone

Comments

@ifreund
Copy link
Member

ifreund commented Jun 27, 2020

The following snippet gives a compile error while I think it should be valid Zig:

const std = @import("std");
pub fn main() void {
    var list = std.TailQueue(u32).init();
    var count: u32 = 0;
    var it = list.first;
    while (it) |node| : (it = node.next) if (true) count += 1;
}
<source>:7:42: error: invalid left-hand side to assignment
    while (it) |node| : (it = node.next) if (true) count += 1;
                                         ^

Removing the if (true) or using a {} block for the if/while makes the compile error go away.

@Vexu
Copy link
Member

Vexu commented Jun 27, 2020

According to the grammar this is parsed as:

    while (it) |node| : (it = node.next) ((if (true) count) += 1);

This could be fixed by making the loop statements accept any statement as their body like C does.

@Vexu Vexu added the proposal This issue suggests modifications. If it also has the "accepted" label then it is planned. label Jun 27, 2020
@Vexu Vexu added this to the 0.7.0 milestone Jun 27, 2020
@ifreund ifreund changed the title Incorrect "invalid left-hand side to assignment" error Allow any statement in loop bodies Jun 27, 2020
@ifreund
Copy link
Member Author

ifreund commented Jun 27, 2020

That makes sense. I find the current behavior to be surprising in this case, though I'd assume there is a good reason this was the grammar chosen.

@ifreund
Copy link
Member Author

ifreund commented Jul 5, 2020

This affects defer as well, the following won't compile with the same "invalid left-hand side to assignment" error:

    defer if (startup_process) |child| _ = child.kill() catch
        |e| log.err(.server, "failed to terminate startup process: {}", .{e});

wrapping the body of the if in a block fixes things, but is needlessly verbose:

    defer if (startup_process) |child| {
        _ = child.kill() catch
            |e| log.err(.server, "failed to terminate startup process: {}", .{e});
    };

@pascaldekloe
Copy link
Contributor

test case (won't compile):

test "double for on line" {
    var n: usize = 0;
    var in: []const []const u8 = &.{ "foo", "bar" };
    for (in) |s| for (s) |c| n += c;
}

@rohlem
Copy link
Contributor

rohlem commented Feb 4, 2025

I just ran into this with if (true) if (true) x = {}; saying if (true) x is an invalid left-hand side,
so it seems this isn't just about loop bodies but any single-statement control flow.
(Originally two optional-unwrapping if-s: if (a) |x| if (b) |y| z = ...;, so combining the conditions with and isn't as concise.)

@zigo101
Copy link

zigo101 commented Feb 9, 2025

Same?

fn foo() u32 {
	var n:u32 = 0;
	defer if (true) n = 8; // error: invalid left-hand side to assignment
	return n;
}

@andrewrk andrewrk modified the milestones: 0.14.0, 0.15.0 Feb 9, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
proposal This issue suggests modifications. If it also has the "accepted" label then it is planned.
Projects
None yet
Development

No branches or pull requests

6 participants