Probably invalid compiler hint

Hi!

One of my projects reported the following fix proposition:

warning: unnecessary braces around block return value
--> src/codec/coder.rs:96:44
   |
96 |     fn serialize(&self) -> Result<Vec<u8>> {Ok(self.payload.clone())}
   |                                            ^                        ^
   |
= note: `#[warn(unused_braces)]` on by default
help: remove these braces
   |
96 -     fn serialize(&self) -> Result<Vec<u8>> {Ok(self.payload.clone())}
96 +     fn serialize(&self) -> Result<Vec<u8>> Ok(self.payload.clone())
   |

After the applying the fix it turned as error (which didn't actually surprise me). What's going on here? Compiler error?

Could you try to minimize the example so that it can be shared? If the error in post was literally compiled from output of cargo check, that seems to be an error indeed, but to debug it we have to know the reproduction steps.

I'll try the minimal. The hint is from compilation phase, not checker or linter.


A - ha! Got it. It is triggered, when #[tracing::instrument] is applied to one-liner.

use std::io::Result;

#[derive(Debug)]
struct Bad {
  payload: Vec<u8>,
}

impl Bad {
  fn new() -> Self { Self {payload: vec![0u8, 1, 2, 3]}}

  #[tracing::instrument]
  fn serialize(&self) -> Result<Vec<u8>> { Ok(self.payload.clone()) }
}

fn main() -> Result<()> {
  let bad = Bad::new();
  println!("X: {:x?}", bad.serialize()?);
  Ok(())
}

Gives:

> cargo build
warning: unnecessary braces around block return value
--> src/main.rs:16:44
|
16 |     fn serialize(&self) -> Result<Vec<u8>> { Ok(self.payload.clone()) }
|                                            ^^                        ^^
|
= note: `#[warn(unused_braces)]` on by default
help: remove these braces
|
16 -     fn serialize(&self) -> Result<Vec<u8>> { Ok(self.payload.clone()) }
16 +     fn serialize(&self) -> Result<Vec<u8>> Ok(self.payload.clone())
|

warning: `bad` (bin "bad") generated 1 warning (run `cargo fix --bin "bad"` to apply 1 suggestion)
Finished dev [unoptimized + debuginfo] target(s) in 0.03s

When serializer is broken into lines, there's no hint:

#[tracing::instrument]
fn serialize(&self) -> Result<Vec<u8>> {
   Ok(self.payload.clone())
}

I've thrown it into cargo expand and after expansion it seems to be a reasonable warning. But... multi-line version is expanded the same way...

fn serialize(&self) -> Result<Vec<u8>> {
 {}
 #[allow(clippy::suspicious_else_formatting)]
 {
  //  Yada yada yada
 }
 { Ok(self.payload.clone()) }
}

it's apparently a problem with the instrument attribute macro. it should add an #[allow(unused_braces)] attribute above the compound expression.

This would be correct for something that triggers on cargo build, but not on cargo check, I'd say.

Meanwhile, this code triggers the warning too (playground):

#[tracing::instrument]
fn bar() -> u8 { 42 }

And this do not:

#[tracing::instrument]
fn bar() -> u8 {
    42
}

And, yes, expansion for both seems to be identical. I'd file the bug for both tracing and rustc, in fact, since, yes, tracing can easily silence the lint (although I'm not sure whether they should, since it would be silenced for the whole former function body, and it may very well genuinely fire within it), the difference in behavior can be a hint on some deeper bug inside macro expansion logic and/or linting.

1 Like

that's a good point.

my guess is it has something to do with whether the token line number of the open and close braces being different. just a guess.

It is triggered even on cargo build --release.

It is triggered even on cargo check, i.e. on just metadata generation without codegen, that's what I was trying to say.

Filed an issue for rustc, will monitor it and probably add a followup for tracing too.

1 Like

Ok, I've subscribed for this issue, too. Thank you.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.