1
Fork 0

allow+update deref_into_dyn_supertrait

this commit makes `deref_into_dyn_supertrait` lint allow-by-default,
removes future incompatibility (we finally live in a broken world), and
changes the wording in the documentation.

previously documentation erroneously said that it lints against *usage*
of the deref impl, while it actually (since 104742) lints on the impl
itself (oooops, my oversight, should have updated it 2+ years ago...)
This commit is contained in:
Waffle Lapkin 2025-02-06 21:57:50 +01:00
parent bc1d68e389
commit 491599569c
No known key found for this signature in database
9 changed files with 63 additions and 75 deletions

View file

@ -1,6 +1,5 @@
use rustc_hir::{self as hir, LangItem};
use rustc_middle::ty;
use rustc_session::lint::FutureIncompatibilityReason;
use rustc_session::{declare_lint, declare_lint_pass};
use rustc_span::sym;
use rustc_trait_selection::traits::supertraits;
@ -9,12 +8,12 @@ use crate::lints::{SupertraitAsDerefTarget, SupertraitAsDerefTargetLabel};
use crate::{LateContext, LateLintPass, LintContext};
declare_lint! {
/// The `deref_into_dyn_supertrait` lint is output whenever there is a use of the
/// `Deref` implementation with a `dyn SuperTrait` type as `Output`.
/// The `deref_into_dyn_supertrait` lint is emitted whenever there is a `Deref` implementation
/// for `dyn SubTrait` with a `dyn SuperTrait` type as the `Output` type.
///
/// These implementations are shadowed by the `trait_upcasting` feature (stabilized since
/// These implementations are "shadowed" by trait upcasting (stabilized since
/// CURRENT_RUSTC_VERSION). The `deref` functions is no longer called implicitly, which might
/// be behavior change compared to previous rustc versions.
/// change behavior compared to previous rustc versions.
///
/// ### Example
///
@ -44,15 +43,14 @@ declare_lint! {
///
/// ### Explanation
///
/// The dyn upcasting coercion feature added a new coercion rules, taking priority
/// over certain other coercion rules, which caused some behavior change.
/// The trait upcasting coercion added a new coercion rule, taking priority over certain other
/// coercion rules, which causes some behavior change compared to older `rustc` versions.
///
/// `deref` can be still called explicitly, it just isn't called as part of a deref coercion
/// (since trait upcasting coercion takes priority).
pub DEREF_INTO_DYN_SUPERTRAIT,
Warn,
"`Deref` implementation usage with a supertrait trait object for output is shadowed by trait upcasting",
@future_incompatible = FutureIncompatibleInfo {
reason: FutureIncompatibilityReason::FutureReleaseSemanticsChange,
reference: "issue #89460 <https://github.com/rust-lang/rust/issues/89460>",
};
Allow,
"`Deref` implementation with a supertrait trait object for output is shadowed by trait upcasting",
}
declare_lint_pass!(DerefIntoDynSupertrait => [DEREF_INTO_DYN_SUPERTRAIT]);

View file

@ -0,0 +1,17 @@
//@ check-pass
#![warn(deref_into_dyn_supertrait)]
use std::ops::Deref;
trait Bar<T> {}
trait Foo: Bar<i32> {}
impl<'a> Deref for dyn Foo + 'a {
//~^ warn: this `Deref` implementation is covered by an implicit supertrait coercion
type Target = dyn Bar<u32> + 'a;
fn deref(&self) -> &Self::Target {
todo!()
}
}
fn main() {}

View file

@ -0,0 +1,17 @@
warning: this `Deref` implementation is covered by an implicit supertrait coercion
--> $DIR/deref-upcast-shadowing-lint.rs:8:1
|
LL | impl<'a> Deref for dyn Foo + 'a {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `dyn Foo` implements `Deref<Target = dyn Bar<u32>>` which conflicts with supertrait `Bar<i32>`
LL |
LL | type Target = dyn Bar<u32> + 'a;
| -------------------------------- target type is a supertrait of `dyn Foo`
|
note: the lint level is defined here
--> $DIR/deref-upcast-shadowing-lint.rs:2:9
|
LL | #![warn(deref_into_dyn_supertrait)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
warning: 1 warning emitted

View file

@ -1,4 +1,5 @@
#![deny(deref_into_dyn_supertrait)]
//@ check-pass
#![warn(deref_into_dyn_supertrait)]
use std::ops::Deref;
@ -6,8 +7,7 @@ trait Bar<'a> {}
trait Foo<'a>: Bar<'a> {}
impl<'a> Deref for dyn Foo<'a> {
//~^ ERROR this `Deref` implementation is covered by an implicit supertrait coercion
//~| WARN this will change its meaning in a future release!
//~^ warn: this `Deref` implementation is covered by an implicit supertrait coercion
type Target = dyn Bar<'a>;
fn deref(&self) -> &Self::Target {

View file

@ -1,19 +1,17 @@
error: this `Deref` implementation is covered by an implicit supertrait coercion
--> $DIR/migrate-lint-deny-regions.rs:8:1
warning: this `Deref` implementation is covered by an implicit supertrait coercion
--> $DIR/migrate-lint-deny-regions.rs:9:1
|
LL | impl<'a> Deref for dyn Foo<'a> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `dyn Foo<'_>` implements `Deref<Target = dyn Bar<'_>>` which conflicts with supertrait `Bar<'_>`
...
LL |
LL | type Target = dyn Bar<'a>;
| -------------------------- target type is a supertrait of `dyn Foo<'_>`
|
= warning: this will change its meaning in a future release!
= note: for more information, see issue #89460 <https://github.com/rust-lang/rust/issues/89460>
note: the lint level is defined here
--> $DIR/migrate-lint-deny-regions.rs:1:9
--> $DIR/migrate-lint-deny-regions.rs:2:9
|
LL | #![deny(deref_into_dyn_supertrait)]
LL | #![warn(deref_into_dyn_supertrait)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 1 previous error
warning: 1 warning emitted

View file

@ -1,25 +0,0 @@
#![deny(deref_into_dyn_supertrait)]
use std::ops::Deref;
// issue 89190
trait A {}
trait B: A {}
impl<'a> Deref for dyn 'a + B {
//~^ ERROR this `Deref` implementation is covered by an implicit supertrait coercion
//~| WARN this will change its meaning in a future release!
type Target = dyn A;
fn deref(&self) -> &Self::Target {
todo!()
}
}
fn take_a(_: &dyn A) {}
fn whoops(b: &dyn B) {
take_a(b)
}
fn main() {}

View file

@ -1,19 +0,0 @@
error: this `Deref` implementation is covered by an implicit supertrait coercion
--> $DIR/migrate-lint-deny.rs:9:1
|
LL | impl<'a> Deref for dyn 'a + B {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `dyn B` implements `Deref<Target = dyn A>` which conflicts with supertrait `A`
...
LL | type Target = dyn A;
| -------------------- target type is a supertrait of `dyn B`
|
= warning: this will change its meaning in a future release!
= note: for more information, see issue #89460 <https://github.com/rust-lang/rust/issues/89460>
note: the lint level is defined here
--> $DIR/migrate-lint-deny.rs:1:9
|
LL | #![deny(deref_into_dyn_supertrait)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 1 previous error

View file

@ -1,4 +1,5 @@
//@ check-pass
#![warn(deref_into_dyn_supertrait)]
use std::ops::Deref;
@ -9,8 +10,7 @@ trait Foo: Bar<i32> {
}
impl<'a> Deref for dyn Foo + 'a {
//~^ WARN this `Deref` implementation is covered by an implicit supertrait coercion
//~| WARN this will change its meaning in a future release!
//~^ warn: this `Deref` implementation is covered by an implicit supertrait coercion
type Target = dyn Bar<u32> + 'a;
fn deref(&self) -> &Self::Target {

View file

@ -1,15 +1,17 @@
warning: this `Deref` implementation is covered by an implicit supertrait coercion
--> $DIR/migrate-lint-different-substs.rs:11:1
--> $DIR/migrate-lint-different-substs.rs:12:1
|
LL | impl<'a> Deref for dyn Foo + 'a {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `dyn Foo` implements `Deref<Target = dyn Bar<u32>>` which conflicts with supertrait `Bar<i32>`
...
LL |
LL | type Target = dyn Bar<u32> + 'a;
| -------------------------------- target type is a supertrait of `dyn Foo`
|
= warning: this will change its meaning in a future release!
= note: for more information, see issue #89460 <https://github.com/rust-lang/rust/issues/89460>
= note: `#[warn(deref_into_dyn_supertrait)]` on by default
note: the lint level is defined here
--> $DIR/migrate-lint-different-substs.rs:2:9
|
LL | #![warn(deref_into_dyn_supertrait)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
warning: 1 warning emitted