rust-lang / rust-lang/rust

Potential overflow in the calculation of complex trait bounds involving tuples

Open
#126,401 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

A-trait-system C-bug D-confusing T-types
Dominant language
Rust
Stars
119k
Forks
16.1k
PR merge metrics
PR metrics pending

Description

When using a trait which is constrained by some bounds, and is implanted automatically for types satisfying those bounds (seen often as the equivalent of type alias in traits), the compiler can run into overflow evaluating bound requirement, which only happen with the helper trait (and not the full bound),

I tried this code:

use std::marker::PhantomData;

trait Hello<'a> {
    type Value;
}

struct Wrapper<T>(PhantomData<T>);

impl<'a, T1, T2> Hello<'a> for Wrapper<(T1, T2)>
where
    Wrapper<T1>: Hello<'a, Value = T1>,
    Wrapper<T2>: Hello<'a, Value = T2>,
{
    type Value = (T1, T2);
}

impl<'a> Hello<'a> for Wrapper<u32> {
    type Value = u32;
}

/// The helper trait
trait Helloable: Sized
where
    Wrapper<Self>: for<'a> Hello<'a, Value = Self>,
{
}

impl<T> Helloable for T where Wrapper<T>: for<'a> Hello<'a, Value = Self> {}

// compiles
fn test1<T>()
where
    Wrapper<T>: for<'a> Hello<'a, Value = T>,
{
}

// overflow error
fn test2<T>()
where
    T: Helloable,
{
}

playground link

I expected to see this happen: This code should compile, with both test1 and test2 (or at the very least not compile with either one).

Instead, this happened: This code compiles with test1, but adding test2 causes an overflow in the tuple implementation and prevents the code from compiling (even though the two functions are practically with the same bounds).

Meta

This happens on all channels (as can be seen in the playground), but here is the local nightly compiler I tried debugging this with:

rustc --version --verbose:

rustc 1.80.0-nightly (032af18af 2024-06-02)                                                                                                                                                                                                                   
binary: rustc                                                                                                                                                                                                                                                 
commit-hash: 032af18af578f4283a2927fb43b90df2bbb72b67                                                                                                                                                                                                         
commit-date: 2024-06-02                                                                                                                                                                                                                                       
host: x86_64-unknown-linux-gnu                                                                                                                                                                                                                                
release: 1.80.0-nightly                                                                                                                                                                                                                                       
LLVM version: 18.1.6  

For the curious, this structure of code arose from trying to work with serde's DeserializeSeed, which in this example I replaced with the trait Hello.

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 issue with the provided minimal Rust example and compare the behavior of test1 and test2. Start by investigating rustc's trait-bound evaluation for the recursive tuple implementation and helper trait. Done means the equivalent bounds no longer produce an overflow and the example has consistent compilation behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
compilers
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.