Skip to content

Implied bounds don't work for traits on &Self #47670

@jpetkau

Description

@jpetkau

If a trait has a bound on &Self, it doesn't seem to work as an implied bound.

For example (also https://gist.github.com/671c7746b96c86f9eb0e39176325157a):

use std::ops::Add;

pub trait Numoid where
  Self: Sized,
  for<'a> &'a Self: Add<Self, Output = Self>
{}

impl<N> Numoid for N where
  for<'a> &'a N: Add<N, Output = N>
{}

pub fn compute<N: Numoid>(a: N, b: N) -> N
    // where for<'a> &'a N: Add<N, Output = N> // redundant bound is required
{ &a + b }

This produces:

error[E0277]: the trait bound `for<'a> &'a N: std::ops::Add<N>` is not satisfied
  --> src/main.rs:20:1
   |
20 | / pub fn compute<N>(a: N, b: N) -> N
21 | | where
22 | |     N: Numoid,
23 | |     // for<'a> &'a N: Add<N, Output = N>, // redundant bound is required
...  |
27 | |     b + d
28 | | }
   | |_^ no implementation for `&'a N + N`
   |
   = help: the trait `for<'a> std::ops::Add<N>` is not implemented for `&'a N`
   = help: consider adding a `where for<'a> &'a N: std::ops::Add<N>` bound
   = note: required by `Numoid`

It works if the 'where' on fn compute is uncommented. Other implicit bounds in the same trait also work (e.g. for<'a> Self: Add<&'a Self> is fine).

This comes up when trying to write generic numeric code. I want to be explicit about using moves/refs to avoid unnecessary clones of things like BigInt, which requires binary operators to have the full set of overloads (i.e. a+b, &a+b, a+&b, &a+&b). BigInt and other numeric types support all these, and they work as explicit bounds, but repeating them on every function gets unwieldy quickly.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-trait-systemArea: Trait systemC-enhancementCategory: An issue proposing an enhancement or a PR with one.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions