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

Assertions don't change type of vars #564

Open
Timmmm opened this issue May 28, 2024 · 1 comment
Open

Assertions don't change type of vars #564

Timmmm opened this issue May 28, 2024 · 1 comment

Comments

@Timmmm
Copy link
Contributor

Timmmm commented May 28, 2024

This works:

function foo() -> unit = {
    var a : range(0, 1) = 0;
    let b = a;
    assert(b == 0);
    a = b + 1;
}

But this doesn't:

function foo() -> unit = {
    var a : range(0, 1) = 0;
    assert(a == 0);
    a = a + 1;
}

I assume this is because b gets the inferred type range(0, 1) and then the assert essentially creates a new variable with the inferred type int(0)... but you can't make a new variable for var since it's mutable? So the assert doesn't change its type?

Not a big deal tbh (var is quite uncommon); I'd probably only fix it if it's easy. Here's the motivating example:

val count_ones : forall 'n, 'n >= 0. (bits('n)) -> range(0, 'n)

function count_ones(x) = {
    var count : range(0, 'n) = 0;
    foreach (i from 0 to ('n - 1)) {
        if x[i] == bitone then {
            assert(count < 'n);
            count = count + 1;
        }
    };
    count
}

I think you could probably do that recursively with no assertions tbf.

@Alasdair
Copy link
Collaborator

Yes, flow typing doesn't affect the type of mutable variables, as you could have:

var a : range(0, 1) = 0;
assert(a == 0);
/* now we could have a : int(0) */
a = 1;
/* now the assertion wouldn't hold, so x would have to go back to it's original type */

to make it work we'd have to modify the type of a up until the assignment, but it's a bit tricky because in general the type checker does't check in evaluation order, and you could do some really ugly things like assign in a weird place like:

assert(a == 0);
f(g(arg1, arg2, a = 1));

It might be worth thinking about whether we want to do something smarter, because I have also noticed it makes loop variables quite awkward.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants