Closed
Description
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