rust-lang/rust

Tracking issue for `const fn` integration with pattern matching

Centril opened this issue · 6 comments

Sub-tracking issue for rust-lang/rfcs#911.

This issue tracks integration of const fn with pattern matching... For example:

#[derive(PartialEq, Eq)]
struct Foo { f: usize, g: usize }

const fn ZERO(x: usize) -> Foo { Foo { f: x, g: x } }

fn main() {
    let f = Foo { f: 0, g: 1 };
    match f {
        ZERO(22) => println!("hi"),
        _ => println!("1"),
    }
}

This is currently not implemented:

error[E0532]: expected tuple struct/variant, found function `ZERO`
  --> src/main.rs:11:9
   |
11 |         ZERO(22) => println!("hi"),
   |         ^^^^ not a tuple struct/variant

error: aborting due to previous error

rust-lang/rfcs#2920 by @ecstatic-morse suggests an alternative way of dealing with const in patterns.

rust-lang/rfcs#2920 would allow you to write the example in the OP with a few extra tokens.

fn main() {
    let f = Foo { f: 0, g: 1 };
    match f {
        const { ZERO(22) } => println!("hi"), // <-
        _ => println!("1"),
    }
}

The explicit requirement of a const { } block seems to help clarify the intent (syntax bike-shedding):

  • Just having ZERO(22) in the match arm suggests that we're trying to match a 1-tuple with an integer value 22, but really we're trying to match on the result of a CTFE.
  • By having the const {} block, it indicates to the reader that we're trying to force a CTFE.

Another use case, which doesn't compile(error E0532) as of 1.47.0:

const Q: u8 = b'q';
const fn ctrl_key(key: u8) -> u8 {
	key & 0x1f
}
const CTRL_Q: u8 = ctrl_key(Q);

fn main() {
	let result: Option<u8> = read_byte_from_somewhere();
	match result {
		Some(Q) | Some(ctrl_key(Q)) => return,
		Some(i) if i > 0 => println!("Read {} from somewhere", i),
		_ => return,
	}
}

Although, if Some(ctrl_key(Q)) is replaced with Some(CTRL_Q) this example works as expected.

Given that RFC2920 has been accepted (tracked at #76001)—giving a plan for how to resolve this integration—and that afaict RFC911 did not specify any kind of integration with patterns; should this issue be closed?

Closed in favor of RFC 2920 and const { ... } blocks, tracked in #76001 .