Skip to content

Prohibit in-scope consts from use as variable names in binders, like nullary tags #1193

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

Closed
boggle opened this issue Nov 19, 2011 · 10 comments
Closed
Labels
A-frontend Area: Compiler frontend (errors, parsing and HIR) E-easy Call for participation: Easy difficulty. Experience needed to fix: Not much. Good first issue.
Milestone

Comments

@boggle
Copy link
Contributor

boggle commented Nov 19, 2011

The following minimal example fails with "unreachable pattern"

mod foo {
    type t = u8;

    const a = 0u8;
    const b = 1u8;

    fn bar(v: t) -> bool {
        alt v {
            a { ret true; }
            b { ret false; }
        }
    }
}
@brson
Copy link
Contributor

brson commented Nov 19, 2011

a and b are being interpreted as variable bindings, so what is happening here is the first branch is always matching and binding the value of v to a, making the second branch unreachable. It is not possible to refer to variables, consts, functions, etc. in a pattern. This is a frequent source of confusion.

const a can be referred to in the pattern guard:

alt v {
  x where x == a { ret true; }
  x where x == b { ret false; }
}

@boggle
Copy link
Contributor Author

boggle commented Nov 19, 2011

but it works with literals and this makes it confusing, will this change?

@marijnh
Copy link
Contributor

marijnh commented Nov 19, 2011

We could make constname. (with a period, similar to nullary tag names) work, but simply the name of the const will never work, as it is indistinguishable from a variable binding.

@lht
Copy link
Contributor

lht commented Nov 19, 2011

While, for reference, this is okay in Erlang.

-module(t).
-export([f/1]).

f(V) ->
   X = 1,
   case V of
      X -> true;
      0 -> false;
      Z -> new_binding
    end.

and, Haskell (and OCaml) generates a warning:

f d =
  let x = 0
  in let y = 1
     in case d of
        x -> True
        y -> False

main = putStrLn $ show (f 3)
Warning: Pattern match(es) are overlapped
             In a case alternative: y -> ...

@boggle
Copy link
Contributor Author

boggle commented Nov 19, 2011

I like the idea of using constname. for now as it solves the most frequent problem with this.

In general, I wonder if allowing variable names that are identical to consts in scope has any sensible use and wether consts should not simply take precedence instead.

I haven't checked but I guess this issue extends to pattern matches in let as well and maybe alternatively some syntax for explicitly splicing in expression values at match time needs to be introduced, e.g. let (a, :pi) = whatever() or something similiar.

@marijnh
Copy link
Contributor

marijnh commented Nov 19, 2011

In general, I wonder if allowing variable names that are identical to consts in scope has any sensible use and wether consts should not simply take precedence instead.

We decided against this, mostly for the reason that making the meaning of a piece of code depend on which identifiers are in scope seems dangerous -- you move it, or you add some unrelated definition somewhere, and suddenly it means something else.

@marijnh
Copy link
Contributor

marijnh commented Nov 22, 2011

What we could do is have the dot (or some other symbol) mean 'look this up in the outer namespace', rather than binding something new. That way, it'd allow one to match against consts, locals, nullary tags, and anything else that's comparable.

This makes exhaustiveness and overlap checking a bit less precise, but that seems an acceptable trade-off.

@graydon
Copy link
Contributor

graydon commented Feb 15, 2012

I've been trying to figure out a good "look this up in the outer namespace" disambiguator syntax for such cases for a while. About the best I can come up with is _::a which is pretty clunky. Any other thoughts? The trailing period was sufficiently random (and unpopular) that I don't think I want to reinstate it.

@graydon
Copy link
Contributor

graydon commented Feb 15, 2012

Eh, on further thought, I think we should just extend the analysis that prohibits colliding variable names and nullary tags to cover consts as well. A nullary tag is very similar in spirit to a const.

@ghost ghost assigned catamorphism Apr 12, 2012
@catamorphism
Copy link
Contributor

The fix for this also has the effect that you can no longer name-shadow a constant (for example, if a const epsilon is in scope, that means you can't say let mut epsilon..., which actually came up in the float library), unless I make the code more complicated by distinguishing between patterns in alts and patterns elsewhere. Personally I'd rather just rename things, but just pointing that out.

celinval pushed a commit to celinval/rust-dev that referenced this issue Jun 4, 2024
* Ensure cargo-kani setup is idempotent

* add test, flip print order for better errors
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-frontend Area: Compiler frontend (errors, parsing and HIR) E-easy Call for participation: Easy difficulty. Experience needed to fix: Not much. Good first issue.
Projects
None yet
Development

No branches or pull requests

6 participants