#[deprecated] does nothing if placed on an impl item.
Given the following two crates:
#![crate_name = "foo"]
pub struct Foo;
pub struct Bar;
pub trait IntoBar {
fn into_bar(self) -> Bar;
}
#[deprecated(note = "Just pass `Bar` instead")]
impl IntoBar for Foo {
fn into_bar(self) -> Bar {
Bar
}
}
extern crate foo;
use foo::*;
fn main() {
let _ = Foo.into_bar();
}
I would expect the second crate to see a deprecation warning on the use of Foo.into_bar(). Instead, both crates compile successfully with no errors. I think that allowing deprecations on impls is a useful option to provide to authors (one that I was looking to do, and found this while seeing if it would work). However, if we do not wish to provide that ability to library authors, placing the #[deprecated] attribute on an impl should result in a compiler error.
This is unfortunately a limitation of stability today, it just doesn't work at all with trait impls. (we run into this all the time in libstd as well)
Alex Crichton at 2017-02-21 15:03:24
@alexcrichton Do we want to support stability on trait impls or not? I remember this being discussed elsewhere but I don't remember the conclusion.
Austin Bonander at 2018-09-01 04:06:08
It'd be nice yeah! At this point everyone just assumes it doesn't work, so there's likely lots of misannotated impls or unintended fallout from a "bugfix" change like this, but it'd be good to implement if possible!
Alex Crichton at 2018-09-03 17:20:16
I still think we should at least make this a compiler error until we can make it work. I disagree with the "everyone assumes it doesn't work" take, I think folks do assume it works, and never verify if their users are receiving a warning or not.
Sage Griffin at 2018-09-10 22:39:34
I still think we should at least make this a compiler error until we can make it work.
A warning would be a gentler option. I agree that it's not good to let people put the deprecation attribute on and assume it will work.
Mikhail Zabaluev at 2018-11-26 20:46:20
I'm surprised this hasn't received more attention. It seems like a rather common occurrence that a library will have a type that implements a trait and you want to remove it but there is no way to direct users away from using the impl Trait. For instance, I have a type that implements
Iterator, but I want to change it to instead have anfn iter().Cameron Steffen at 2020-07-15 14:50:28
#78626 turned this into a compile error.
ordian at 2021-01-04 09:28:45
Given the current stable release:
cargo -V -v cargo 1.82.0 (8f40fc59f 2024-08-21) release: 1.82.0 commit-hash: 8f40fc59fb0c8df91c97405785197f3c630304ea commit-date: 2024-08-21 host: aarch64-apple-darwin libgit2: 1.8.1 (sys:0.19.0 vendored) libcurl: 8.7.1 (sys:0.4.74+curl-8.9.0 system ssl:(SecureTransport) LibreSSL/3.3.6) ssl: OpenSSL 1.1.1w 11 Sep 2023 os: Mac OS 15.0.1 [64-bit]
Then I am at least told that the deprecation is not going to work:
cargo build Compiling foo v0.1.0 (/Users/rod/code/rust/triage/deprec/foo) error: this
#[deprecated]annotation has no effect --> src/lib.rs:10:1 | 10 | #[deprecated(note = "Just passBarinstead")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove the unnecessary deprecation attribute | = note:#[deny(useless_deprecated)]on by defaulterror: could not compile
foo(lib) due to 1 previous errorRod at 2024-10-21 18:38:05