Skip to content

False positive when requiring variants of the same trait with different const parameters #13476

Closed
@porky11

Description

@porky11

Summary

Having a trait bound, which requires the same type twice, but with different const generics casues the issue.

Basically this: V: Basis<0> + Basis<1>

Lint Name

clippy::trait_duplication_in_bounds

Reproducer

I tried this code:

use std::fmt::Debug;

trait Vector {
    type Scalar: Debug;
}

trait Basis<const DIMENSION: usize>: Vector {
    fn basis(&self) -> Self::Scalar;
}

fn basis<const DIMENSION: usize, B: Basis<DIMENSION>>(value: &B) -> B::Scalar {
    value.basis()
}

// Example type
struct Vector2 {
    x: f32,
    y: f32,
}

impl Vector for Vector2 {
    type Scalar = f32;
}

impl Basis<0> for Vector2 {
    fn basis(&self) -> f32 {
        self.x
    }
}

impl Basis<1> for Vector2 {
    fn basis(&self) -> f32 {
        self.y
    }
}

fn render_point<V: Basis<0> + Basis<1>>(point: V) {
    let x = basis::<0, _>(&point);
    let y = basis::<1, _>(&point);
    todo!("Render point at {x:?}, {y:?}")
}

fn main() {
    let point = Vector2 { x: 1.0, y: 2.0 };

    render_point(point);
}

I get this error:

warning: these bounds contain repeated elements
  --> src/main.rs:37:20
   |
37 | fn render_point<V: Basis<0> + Basis<1>>(point: V) {
   |                    ^^^^^^^^^^^^^^^^^^^ help: try: `Basis<0>`
   |
   = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#trait_duplication_in_bounds
   = note: `-W clippy::trait-duplication-in-bounds` implied by `-W clippy::nursery`
   = help: to override `-W clippy::nursery` add `#[allow(clippy::trait_duplication_in_bounds)]`

The problem is the duplicate requirement of Basis like this: V: Basis<0> + Basis<1>.
Clippy seems to assume both traits Basis<0> and Basis<1> to be the same type.

Must be an issue with const generics.
If I use generic types instead of const generics, no warning is shown:

use std::fmt::Debug;

trait Vector {
    type Scalar: Debug;
}

trait Basis<DIMENSION>: Vector {
    fn basis(&self) -> Self::Scalar;
}

fn basis<DIMENSION, B: Basis<DIMENSION>>(value: &B) -> B::Scalar {
    value.basis()
}

// Example type
struct Vector2 {
    x: f32,
    y: f32,
}

struct X;
struct Y;

impl Vector for Vector2 {
    type Scalar = f32;
}

impl Basis<X> for Vector2 {
    fn basis(&self) -> f32 {
        self.x
    }
}

impl Basis<Y> for Vector2 {
    fn basis(&self) -> f32 {
        self.y
    }
}

fn render_point<V: Basis<X> + Basis<Y>>(point: V) {
    let x = basis::<X, _>(&point);
    let y = basis::<Y, _>(&point);
    todo!("Render point at {x:?}, {y:?}")
}

fn main() {
    let point = Vector2 { x: 1.0, y: 2.0 };

    render_point(point);
}

Version

rustc 1.81.0 (eeb90cda1 2024-09-04)
binary: rustc
commit-hash: eeb90cda1969383f56a2637cbd3037bdf598841c
commit-date: 2024-09-04
host: x86_64-unknown-linux-gnu
release: 1.81.0
LLVM version: 18.1.7

Additional Labels

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-bugCategory: Clippy is not doing the correct thingI-false-positiveIssue: The lint was triggered on code it shouldn't have

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions