Match-ergonomics on `&&str` and type inferred on its branch

#![allow(clippy::match_single_binding)]
#![feature(type_name_of_val)]
use std::any::type_name_of_val;

// The comment at the end of line is the type inferred by Rust-Analyzer.
// And the `-> xx` is the output from `type_name_of_val`, which is different from the inferred one.
fn main() {
    match &&123 {
        x @ 123 => println!("1: {}", type_name_of_val(&x)), // &i32 -> &&i32
        x => println!("2: {}", type_name_of_val(&x)), // &&i32
    };
    match &&123 {
        x @ &123 => println!("1: {}", type_name_of_val(&x)), // &i32 -> &&i32
        x => println!("2: {}", type_name_of_val(&x)), // &&i32
    };
    match &&123 {
        x @ &&123 => println!("1: {}", type_name_of_val(&x)), // &&i32
        x => println!("2: {}", type_name_of_val(&x)), // &&i32
    };

    match &"123" {
        // x @ "123" => println!("1: {}", type_name_of_val(&x)), // expected &&str, found &str
        x => println!("2: {}", type_name_of_val(&x)), // &&str
    };
    match &"123" {
        &x @ "123" => println!("1: {}", type_name_of_val(&x)), // &str
        x => println!("2: {}", type_name_of_val(&x)), // &&str
    };
    match &"123" {
        x @ &"123" => println!("1: {}", type_name_of_val(&x)), // &&str
        x => println!("2: {}", type_name_of_val(&x)), // &&str
    };

    match &&[123, 456][..] {
        x @ [123, 456] => println!("1: {}", type_name_of_val(&x)), // &[i32] -> &&[i32]
        x => println!("2: {}", type_name_of_val(&x)), // &&[i32]
    };
    match &&[123, 456][..] {
        x @ &[123, 456] => println!("1: {}", type_name_of_val(&x)), // &[i32] -> &&[i32]
        x => println!("2: {}", type_name_of_val(&x)), // &&[i32]
    };
}

playground

There are two problems I notice:

  1. The following is not allowed, which seems an exception in 2005-match-ergonomics - The Rust RFC Book
    match &"123" {
        // x @ "123" => println!("1: {}", type_name_of_val(&x)), // expected &&str, found &str
        x => println!("2: {}", type_name_of_val(&x)), // &&str
    };
  1. Some types inferred by Rust-Analyzer is wrong (or type_name_of_val is wrong ?), which is shown in the code comments above.
2 Likes