1

Is it possible to make this work? I originally wanted to see if true could be redefined, then I saw true is actually a keyword.

Is it possible to "fix" the patterns error and get the "you-can't-assign-to-a-keyword-error"?

fn main() {
    let true = false;
}

I get:

error[E0005]: refutable pattern in local binding: `false` not covered
 --> src/main.rs:2:9
  |
2 |     let true = false;
  |         ^^^^ pattern `false` not covered

Playground

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Armando Pérez Marqués
  • 5,661
  • 4
  • 28
  • 45
  • 3
    No. Just don't. – trent Sep 10 '18 at 18:21
  • 1
    @trentcl Agree. But there's no harm in testing the limits of a language to see what it will or won't let you do, and try to understand why. – Peter Hall Sep 10 '18 at 18:33
  • @trentcl Like @PeterHall says, I'm just pushing the limits, to see how the language/platform behaves in those weird cases, trying to fully understand what I'm trying to learn. Of course this is plain wrong, stupid, etc in real-life code, this is just for educational purposes. As important is to communicate "Don't", also important to communicate "Why not". The initial motivation of why I was trying to do that is because in Go `true := false` works (see https://play.golang.org/p/IYePvGlA1w0) – Armando Pérez Marqués Sep 10 '18 at 18:52
  • 1
    It seems to me you know the answer. You can't do it because `true` is a keyword. Go is a different language and it can permit whatever, but Rust doesn't. What do you hope to learn from the answers that you didn't know already? – trent Sep 10 '18 at 18:56
  • Since I later found out that `true` is a keyword, the question is really about pattern matching, and the true answer lies in the link provided by @yorodm answer. – Armando Pérez Marqués Sep 10 '18 at 19:00
  • Possible duplicate of [What are the use cases of raw identifiers besides new keywords?](https://stackoverflow.com/questions/51000263/what-are-the-use-cases-of-raw-identifiers-besides-new-keywords) => [easy](https://play.rust-lang.org/?gist=33698417766c4b3b3a18429f27a3fc30&version=nightly&mode=debug&edition=2015) – Stargateur Sep 10 '18 at 19:01

2 Answers2

5

There's nothing wrong with the error message. You're using an refutable pattern in a let binding and let only allows for irrefutable patterns.

In other words, when you do this:

let variable = value

You are not assigning a value to the variable. You're creating a binding where the left side matches something on the right side. It should be an irrefutable pattern because the match must always succeed.

yorodm
  • 4,359
  • 24
  • 32
  • 1
    Thanks for the documentation link, that's exactly what I needed. Fun fact, using `if let` compiles, and even better, the condition is only executed if the variants on both sides are the same (`if let true = true` or `if let false = false`) so apparently there's no way to shoot myself in the foot even when directly aiming at it. – Armando Pérez Marqués Sep 10 '18 at 18:57
3

I'm not sure what you're trying to do or why you'd want to do it! Most people would consider it a design flaw if a language permitted you to redefine true and false and I'm sure this has been the topic of at least one installment of The Daily WTF.

Is it possible to "fix" the patterns error and get the "you-can't-assign-to-a-keyword-error"?

Constant definitions don't allow patterns, so you can get a different error by attempting to redefine true as a const:

const true: bool = false;

Which produces an error more similar to what you were after:

error: expected identifier, found keyword `true`
  --> src/main.rs:1:7 
  | 
1 | const true: bool = false;
  | ^^^^ expected identifier, found keyword 
Peter Hall
  • 53,120
  • 14
  • 139
  • 204
  • When I was learning Rust and learned about `enum`, I actually expected `bool` to be a regular `enum`, so rebinding `true` would have been perfectly fine. This would in my opinion have been a little neater. Also python is perfectly fine with redefining `True` for example: `True = 42; print(True)`, this doesn't change the truethiness of the built-in `True` value, as shown by a subsequent `print([] == [])`. – mcarton Sep 10 '18 at 18:33
  • You can't rebind enum variants either though? And in Python 2, `True = 42` doesn't rebind `True`, it just shadows it with a local variable definition. (In Python 3 `True` and `False` have been made keywords, so `True = 42` is just a `SyntaxError`.) – trent Sep 10 '18 at 18:43
  • @mcarton Other than the variants being keywords, what about `bool` tells you that it's not an `enum`? Maybe that you can coerce to integer types with `as`? – Peter Hall Sep 10 '18 at 18:49
  • I guess maybe I'm being unnecessarily pedantic about the meaning of "rebind". If you consider shadowing a variable to be rebinding the name, then I guess `True = 42` does rebind `True`. – trent Sep 10 '18 at 18:50
  • 1
    @trentcl I _think_ Haskell's built-in `Bool` actually is just an ordinary `data` type with two constructors. – Peter Hall Sep 10 '18 at 19:22
  • TIL `let None = 42;` is an error. I imagined this would have worked, because the actual variant is `Option::::None` just imported as `None`. But hey, as long as I can `type bool = u32`, everything is fine – mcarton Sep 10 '18 at 20:06