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

Match with functions: first arm always triggered #44333

Closed
MageSlayer opened this issue Sep 5, 2017 · 7 comments · Fixed by #50505
Closed

Match with functions: first arm always triggered #44333

MageSlayer opened this issue Sep 5, 2017 · 7 comments · Fixed by #50505
Labels
E-needs-test Call for participation: An issue has been fixed and does not reproduce, but no test has been added. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@MageSlayer
Copy link

MageSlayer commented Sep 5, 2017

Hi all

Following code produces always the same output in console and emits

warning: unreachable pattern
  --> src/main.rs:31:5
   |
31 |     plus => println!("plus"),
   |     ^^^^ this is an unreachable pattern
   |
   = note: #[warn(unreachable_patterns)] on by default
note: this pattern matches any value

... in compilation.

type 
  TFunc = fn (i64,i64)->i64;
  
fn plus(a:i64, b:i64)->i64 {
  a+b
}

fn minus(a:i64, b:i64)->i64 {
  a-b
}

fn other(a:i64, b:i64)->i64 {
  0
}

fn test(c:i64) -> TFunc {
  match c {
    0 => plus,
    1 => minus,
    _ => other
  }
}

extern crate rand;
use rand::Rng;
fn main() {
  let mut rng = rand::thread_rng();
  for i in 0..10 {
  match test( rng.gen() ) {
    minus => println!("minus"),
    plus => println!("plus"),
    _ => println!("other"),
  }
  }
}

Tested in Rust playground in nightly.
Any comments?

@tirr-c
Copy link
Contributor

tirr-c commented Sep 5, 2017

In your code, minus, plus in match patterns are treated as variable names. Try pattern guards:

match test(rng.gen()) {
    f if f == minus => println!("minus"),
    f if f == plus => println!("plus"),
    _ => println!("other"),
}

Note that the return value of rng.gen() ranges from i64::MIN to i64::MAX, because test accepts an argument of type i64. You will rarely see minus and plus, because most of the case the control flow will fall into the placeholder arm and print other.


Pattern matching is different from comparing with ==. You can implement your custom logic of == by implementing PartialEq, but it lacks ability of destructuring structs, enums, and tuples. On the other hand, pattern matching can match against literals or destructure values, but you can't define your own pattern matching logic. They just have different purposes.

TFunc in your code (fn (i64, i64) -> i64) implements PartialEq to compare function pointers. However, functions are not literals, so they can't be matched directly.

@MageSlayer
Copy link
Author

Yes with guards it works, but I suspect it changes the semantics of match (less optimizations I guess).
Is it possible to make "minus" and "plus" constants instead? I mean it's just pointers under the hood, right?
And yes "rng" is just to give an idea.

@oli-obk
Copy link
Contributor

oli-obk commented Sep 6, 2017

You can normally use constants, but these currently fail: https://play.rust-lang.org/?gist=ad06b52140cf452e1e442153f0ac95f9&version=stable

I guess noone thought that functions would be used in patterns:

error: internal compiler error: /checkout/src/librustc_const_eval/pattern.rs:572: impossible case reached

note: the compiler unexpectedly panicked. this is a bug.

note: we would appreciate a bug report: https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md#bug-reports

note: rustc 1.20.0 (f3d6973f4 2017-08-27) running on x86_64-unknown-linux-gnu

thread 'rustc' panicked at 'Box<Any>', /checkout/src/librustc_errors/lib.rs:489:8
note: Run with `RUST_BACKTRACE=1` for a backtrace.

@MageSlayer
Copy link
Author

That's much getter, imho. Thanks for hint.

I guess noone thought that functions would be used in patterns.

Functions as values? Never heard of heresy like that :)

@tirr-c
Copy link
Contributor

tirr-c commented Sep 6, 2017

@TimNN TimNN added C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. I-ICE Issue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️ labels Sep 17, 2017
@varkor
Copy link
Member

varkor commented May 3, 2018

The test cases here no longer ICE on beta or nightly.

@oli-obk oli-obk closed this as completed May 4, 2018
@oli-obk
Copy link
Contributor

oli-obk commented May 4, 2018

Needs a regression test

@oli-obk oli-obk reopened this May 4, 2018
@oli-obk oli-obk added E-needs-test Call for participation: An issue has been fixed and does not reproduce, but no test has been added. and removed C-bug Category: This is a bug. I-ICE Issue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️ labels May 4, 2018
XAMPPRocky pushed a commit to XAMPPRocky/rust that referenced this issue May 7, 2018
kennytm added a commit to kennytm/rust that referenced this issue May 9, 2018
Added regression function match value test

closes rust-lang#44333
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
E-needs-test Call for participation: An issue has been fixed and does not reproduce, but no test has been added. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants