rust-lang / rust-lang/rust

Inference failure triggered by null proc macro application to totally unused and irrelevant struct

Open
#130,480 4 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

A-inference A-macros C-bug E-needs-mcve
Dominant language
Rust
Stars
119k
Forks
16.1k
PR merge metrics
PR metrics pending

Description

Steps to reproduce
git clone https://gitlab.torproject.org/Diziet/arti -b report-inference-failure
cd arti
cargo +nightly check --locked  -p tor-socksproto --all-features --all-targets

I'm afraid I haven't minimised this, for reasons that will become obvious.

Expected behaviour

It compiles.

Actual behaviour:
error[E0282]: type annotations needed
   --> crates/tor-socksproto/src/handshake/client.rs:332:9
    |
332 |         assert_eq!(action.reply, &[]);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type
    |
    = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
Why is this surprising

This works:

git checkout report-inference-failure~
cargo +nightly check --locked  -p tor-socksproto --all-features --all-targets

The commit that makes things break, 778c2753469c020bf2fde9d43f182c8b1b02d0af, applies amplify::Getters to an unused struct - one which is therefore not related to the one where inference is failing. Indeed, deleting the whole struct definition leaves a tree that compiles.

I looked at the output of cargo expand. As expected, the diff is trivial and not a plausible cause of the inference failure: with the specified attributes, the maro generates no methods - just one empty impl block. Adding that emply impl block by hand compiles.

This is all extremely mysterious. I feel I must be missing something but I struggle to guess what.

Source diff that makes it break
diff --git a/crates/tor-socksproto/src/handshake/framework.rs b/crates/tor-socksproto/src/handshake/framework.rs
index 58318bbcf..a451d7e69 100644
--- a/crates/tor-socksproto/src/handshake/framework.rs
+++ b/crates/tor-socksproto/src/handshake/framework.rs
@@ -64,9 +64,10 @@ pub struct Done<'b, O> {
 ///     dispose of the [`RecvStep`] (which mutably borrows the `Buffer`)
 ///     while reading,
 ///     at the cost of slightly less correctness checking by the compiler.
-#[derive(Debug)]
+#[derive(Debug, amplify::Getters)]
 pub struct RecvStep<'b> {
     /// The buffer
+    #[getter(skip)]
     buffer: &'b mut Buffer,
 
     /// Lower bound on the number of bytes that the handshake needs to read to complete.
@@ -78,6 +79,7 @@ pub struct RecvStep<'b> {
     /// [`tor_bytes::IncompleteMessage.deficit`.
     // XXXX should this be NonZeroUsize instead?  Or maybe even usize?
     // Note that the getter exposes the type.
+    #[getter(skip)]
     deficit: Sensitive<NonZeroUsize>,
 }
Diff in the output of cargo expand --locked -p tor-socksproto
--- a   2024-09-17 18:43:13.903354184 +0100
+++ b   2024-09-17 18:43:58.655551951 +0100
@@ -413,6 +413,7 @@
         ///     at the cost of slightly less correctness checking by the compiler.
         pub struct RecvStep<'b> {
             /// The buffer
+            #[getter(skip)]
             buffer: &'b mut Buffer,
             /// Lower bound on the number of bytes that the handshake needs to read to complete.
             ///
@@ -421,6 +422,7 @@
             ///
             /// The returned value has the same semantics as
             /// [`tor_bytes::IncompleteMessage.deficit`.
+            #[getter(skip)]
             deficit: Sensitive<NonZeroUsize>,
         }
         #[automatically_derived]
@@ -437,6 +439,8 @@
                 )
             }
         }
+        #[automatically_derived]
+        impl<'b> RecvStep<'b> {}
         /// `Handshake` structs that have a state that can be `Failed`
         ///
         /// Derive this with

Meta

rustc --version --verbose:

rustcargo@zealot:/volatile/rustcargo/d/arti$ rustc +nightly -vV
rustc 1.83.0-nightly (c52c23b6f 2024-09-16)
binary: rustc
commit-hash: c52c23b6f44cd19718721a5e3b2eeb169e9c96ff
commit-date: 2024-09-16
host: x86_64-unknown-linux-gnu
release: 1.83.0-nightly
LLVM version: 19.1.0
rustcargo@zealot:/volatile/rustcargo/d/arti$ 

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Reproduce the failure with cargo +nightly check --locked -p tor-socksproto --all-features --all-targets, then compare crates/tor-socksproto/src/handshake/framework.rs and handshake/client.rs before and after commit 778c2753469c020bf2fde9d43f182c8b1b02d0af. Use the reported cargo expand output to investigate why the empty derived impl affects inference; done means the command compiles without E0282.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.