Skip to content
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

Peer type resolution should only happen when result type is unspecified #2749

Closed
hryx opened this issue Jun 25, 2019 · 1 comment
Closed
Labels
accepted This proposal is planned. proposal This issue suggests modifications. If it also has the "accepted" label then it is planned.
Milestone

Comments

@hryx
Copy link
Sponsor Contributor

hryx commented Jun 25, 2019

Peer type resolution is useful and convenient, but currently it takes precedence over other forms of type resolution when it shouldn't. Peer type resolution should only occur when the result type (see #2602) is unspecified. For function returns, the result type is always known because return types are a mandatory part of the function.

Here are two examples which currently fail due to this eager resolution, but which should succeed given implicit casting rules. The error is error: incompatible types: '[]u8' and '[1]u8'.


In this example, the compiler should attempt to cast each prong expression to []const u8 because the result type is predetermined by the function's return type. No peer type resolution should occur.

test "peer type resolution blocks implicit cast to return type" {
    for ("hello") |c| _ = f(c);
}

fn f(c: u8) []const u8 {
    return switch (c) {
        'h', 'e' => [_]u8{c}, // should cast to slice
        'l', ' ' => [_]u8{ c, '.' }, // should cast to slice
        else => ([_]u8{c})[0..], // is a slice
    };
}

In this example, the compiler should attempt to cast each prong expression to []const u8 because the result type is predetermined by the explicit variable type. No peer type resolution should occur.

test "peer type resolution blocks implicit cast to variable type" {
    var x: []const u8 = undefined;
    for ("hello") |c| x = switch (c) {
        'h', 'e' => [_]u8{c}, // should cast to slice
        'l', ' ' => [_]u8{ c, '.' }, // should cast to slice
        else => ([_]u8{c})[0..], // is a slice
    };
}
@andrewrk
Copy link
Member

andrewrk commented Sep 5, 2019

Progress. This test passes now:

test "if prongs cast to expected type instead of peer type resolution" {
    const S = struct {
        fn doTheTest(f: bool) void {
            var x: i32 = 0;
            x = if (f) 1 else 2;
            expect(x == 2);
        }
    };
    S.doTheTest(false);
    comptime S.doTheTest(false);
}

However the examples from this issue still do not pass, and there is also this problem that I want to resolve:

test "variable initialization does not use result locations properly with regards to the type" {
    var b = true;
    const x: i32 = if (b) 1 else 2;
}
/home/andy/dev/zig/build/test.zig:3:27: error: cannot store runtime value in type 'comptime_int'
    const x: i32 = if (b) 1 else 2;
                          ^

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
accepted This proposal is planned. 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

2 participants