rust-lang / rust

Empowering everyone to build reliable and efficient software.
https://www.rust-lang.org
Other
99.18k stars 12.81k forks source link

match &[first, ..more] leads down a suggestion garden path #130639

Open nabijaczleweli opened 2 months ago

nabijaczleweli commented 2 months ago

Code

struct Algorithms<'a>(&'a Vec<String>);
impl<'a> fmt::Display for Algorithms<'a> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match &self.0[..] {
            &[] => f.write_str("<default>"),
            &[one] => f.write_str(&one),
            &[first, ..more] => {
                f.write_str(&first)?;
                for rec in more {
                    write!(f, ", then {}", rec)?;
                }
                Ok(())
            },
        }
    }
}

Current output

   Compiling zram-generator v1.1.2 (/home/nabijaczleweli/code/systemd-zram-generator)
error[E0425]: cannot find value `more` in this scope
   --> src/config.rs:205:24
    |
205 |             &[first, ..more] => {
    |                        ^^^^ not found in this scope
    |
help: if you meant to collect the rest of the slice in `more`, use the at operator
    |
205 |             &[first, more @ ..] => {
    |                      ~~~~~~~~~

okay so I do that and get

   Compiling zram-generator v1.1.2 (/home/nabijaczleweli/code/systemd-zram-generator)
error[E0277]: the size for values of type `[String]` cannot be known at compilation time
   --> src/config.rs:205:22
    |
205 |             &[first, more @ ..] => {
    |                      ^^^^^^^^^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `[String]`
    = note: all local variables must have a statically known size
    = help: unsized locals are gated as an unstable feature

..? definitely sub-optimal; the first thing I tried was

error: `..` patterns are not allowed here
   --> src/config.rs:205:30
    |
205 |             &[first, &more @ ..] => {
    |                              ^^
    |
    = note: only allowed in tuple, tuple struct, and slice patterns

so I did &[first, ref more @ ..] which worked

Desired output

idk. probably suggest with the ref if appropriate?

Rationale and extra context

No response

Other cases

No response

Rust Version

rustc 1.80.1 (3f5fd8dd4 2024-08-06) binary: rustc commit-hash: 3f5fd8dd41153bc5fdca9427e9e05be2c767ba23 commit-date: 2024-08-06 host: x86_64-unknown-linux-gnu release: 1.80.1 LLVM version: 18.1.7

Anything else?

No response

nabijaczleweli commented 2 months ago

Actually [first, more @ ..] works if you remove the outermost & (this is also an error, but appeared at the end of the output). So idk.

5225225 commented 2 months ago

I couldn't get the code with the outermost & to compile, I get

error[E0508]: cannot move out of type `[String]`, a non-copy slice
 --> src/lib.rs:5:15
  |
5 |         match &self.0[..] {
  |               ^^^^^^^^^^^ cannot move out of here
6 |             &[] => f.write_str("<default>"),
7 |             &[one] => f.write_str(&one),
  |               --- data moved here
8 |             &[first, ref more @ ..] => {
  |               ----- ...and here

with this code:

use std::fmt;
struct Algorithms<'a>(&'a Vec<String>);
impl<'a> fmt::Display for Algorithms<'a> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match &self.0[..] {
            &[] => f.write_str("<default>"),
            &[one] => f.write_str(&one),
            &[first, ref more @ ..] => {
                f.write_str(&first)?;
                for rec in more {
                    write!(f, ", then {}", rec)?;
                }
                Ok(())
            },
        }
    }
}

The outer &'s just won't compile since it's trying to move out a String, even if it's only used as a reference, I guess?

If we told the user earlier "hey, if you just want a &String, then remove the outermost & and then remove the & in the code", and they did that first, then the suggestion here would be correct. But the user probably didn't mean &[] for a non-Copy slice type.

That might be hard since that's a borrow checker error while we are currently dealing with a missing variable error, so I don't know how easy it would be to notice that.