#[do_not_recommend] for traits themselves

Currently you can only use #[do_not_recommend] with trait impls:

#[diagnostic::do_not_recommend]
impl Trait for i32 {}

and this will not work:

#[diagnostic::do_not_recommend]
//~^WARN `#[diagnostic::do_not_recommend]` can only be placed
trait Trait {}

I wonder if we could expand the places in which you can use this attribute. For example, today I ran into this error:

error[E0599]: no method named `as_ptr` found for reference `&DmaBuf` in the current scope
   --> /proc/self/cwd/common/rust/kernel/dma_buf/buf.rs:54:38
    |
 54 |         ptr::eq(self.as_ptr(), other.as_ptr())
    |                                      ^^^^^^ method not found in `&DmaBuf`
    |
    = help: items from traits can only be used if the trait is implemented and in scope
note: `device_id::IdTable` defines an item `as_ptr`, perhaps you need to implement it
   --> /proc/self/cwd/common/rust/kernel/device_id.rs:165:1
    |
165 | pub trait IdTable<T: RawDeviceId, U> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

However, suggesting this random IdTable trait is not really useful.

/// A device id table.
///
/// This trait is only implemented by `IdArray`.
///
/// The purpose of this trait is to allow `&'static dyn IdArray<T, U>` to be in context when `N` in
/// `IdArray` doesn't matter.
pub trait IdTable<T: RawDeviceId, U> {
    /// Obtain the pointer to the ID table.
    fn as_ptr(&self) -> *const T::RawType;

    /// Obtain the pointer to the bus specific device ID from an index.
    fn id(&self, index: usize) -> &T::RawType;

    /// Obtain the pointer to the driver-specific information from an index.
    fn info(&self, index: usize) -> &U;
}

For now, I think the way to improve the diagnostics here is to use a less generic name for IdTable::as_ptr(), but I think it would be interesting if you could annotate the trait:

#[diagnostic::do_not_recommend]
pub trait IdTable<T: RawDeviceId, U> {
    fn as_ptr(&self) -> *const T::RawType;
    fn id(&self, index: usize) -> &T::RawType;
    fn info(&self, index: usize) -> &U;
}

or even the method:

pub trait IdTable<T: RawDeviceId, U> {
    #[diagnostic::do_not_recommend]
    fn as_ptr(&self) -> *const T::RawType;
    fn id(&self, index: usize) -> &T::RawType;
    fn info(&self, index: usize) -> &U;
}

to silence this suggestion.

Thoughts?

10 Likes

I second this. This is actually a blocker for this PR: Generalize `impl<T> Clone for Box<T>` to unsized types by a1phyr · Pull Request #146381 · rust-lang/rust · GitHub

I'm fully supportive of this addition. The hardest part would be finding all of the places where the do_not_recommend should be followed.

2 Likes

I had an experiment similar in spirit to this: [WIP] Support `#[rustc_on_unimplemented]` on methods by estebank · Pull Request #156400 · rust-lang/rust · GitHub

I think it would be better to just update this diagnostic to not say this if a) the trait isn't implemented and cannot be implemented or b) the name is really generic.