From 63b34cf48046ee4cbea866be82eba02fdd063b0c Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 17 Nov 2023 22:05:42 +0000 Subject: [PATCH 1/2] Don't consider regions in deref_into_dyn_supertrait lint --- .../src/deref_into_dyn_supertrait.rs | 16 ++++++--- .../inference-behavior-change-deref.rs | 36 +++++++++++++++++++ .../inference-behavior-change-deref.stderr | 16 +++++++++ .../migrate-lint-deny-regions.rs | 18 ++++++++++ .../migrate-lint-deny-regions.stderr | 19 ++++++++++ .../trait-upcasting/migrate-lint-deny.rs | 6 ++-- .../trait-upcasting/migrate-lint-deny.stderr | 4 +-- 7 files changed, 104 insertions(+), 11 deletions(-) create mode 100644 tests/ui/traits/trait-upcasting/inference-behavior-change-deref.rs create mode 100644 tests/ui/traits/trait-upcasting/inference-behavior-change-deref.stderr create mode 100644 tests/ui/traits/trait-upcasting/migrate-lint-deny-regions.rs create mode 100644 tests/ui/traits/trait-upcasting/migrate-lint-deny-regions.stderr diff --git a/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs b/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs index d2d99bc0da87d..41a70bfcc5936 100644 --- a/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs +++ b/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs @@ -59,12 +59,13 @@ declare_lint_pass!(DerefIntoDynSupertrait => [DEREF_INTO_DYN_SUPERTRAIT]); impl<'tcx> LateLintPass<'tcx> for DerefIntoDynSupertrait { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) { + let tcx = cx.tcx; // `Deref` is being implemented for `t` if let hir::ItemKind::Impl(impl_) = item.kind && let Some(trait_) = &impl_.of_trait - && let t = cx.tcx.type_of(item.owner_id).instantiate_identity() + && let t = tcx.type_of(item.owner_id).instantiate_identity() && let opt_did @ Some(did) = trait_.trait_def_id() - && opt_did == cx.tcx.lang_items().deref_trait() + && opt_did == tcx.lang_items().deref_trait() // `t` is `dyn t_principal` && let ty::Dynamic(data, _, ty::Dyn) = t.kind() && let Some(t_principal) = data.principal() @@ -73,9 +74,14 @@ impl<'tcx> LateLintPass<'tcx> for DerefIntoDynSupertrait { && let ty::Dynamic(data, _, ty::Dyn) = target.kind() && let Some(target_principal) = data.principal() // `target_principal` is a supertrait of `t_principal` - && supertraits(cx.tcx, t_principal.with_self_ty(cx.tcx, cx.tcx.types.trait_object_dummy_self)) - .any(|sup| sup.map_bound(|x| ty::ExistentialTraitRef::erase_self_ty(cx.tcx, x)) == target_principal) + && supertraits(tcx, t_principal.with_self_ty(tcx, tcx.types.trait_object_dummy_self)) + .any(|sup| { + tcx.erase_regions( + sup.map_bound(|x| ty::ExistentialTraitRef::erase_self_ty(tcx, x)), + ) == tcx.erase_regions(target_principal) + }) { + let t = tcx.erase_regions(t); let label = impl_ .items .iter() @@ -83,7 +89,7 @@ impl<'tcx> LateLintPass<'tcx> for DerefIntoDynSupertrait { .map(|label| SupertraitAsDerefTargetLabel { label }); cx.emit_spanned_lint( DEREF_INTO_DYN_SUPERTRAIT, - cx.tcx.def_span(item.owner_id.def_id), + tcx.def_span(item.owner_id.def_id), SupertraitAsDerefTarget { t, target_principal, label }, ); } diff --git a/tests/ui/traits/trait-upcasting/inference-behavior-change-deref.rs b/tests/ui/traits/trait-upcasting/inference-behavior-change-deref.rs new file mode 100644 index 0000000000000..79fb643eacd01 --- /dev/null +++ b/tests/ui/traits/trait-upcasting/inference-behavior-change-deref.rs @@ -0,0 +1,36 @@ +#![deny(deref_into_dyn_supertrait)] +#![feature(trait_upcasting)] // remove this and the test compiles + +use std::ops::Deref; + +trait Bar {} +impl Bar for T {} + +trait Foo: Bar { + fn as_dyn_bar_u32<'a>(&self) -> &(dyn Bar + 'a); +} + +impl Foo for () { + fn as_dyn_bar_u32<'a>(&self) -> &(dyn Bar + 'a) { + self + } +} + +impl<'a> Deref for dyn Foo + 'a { + type Target = dyn Bar + 'a; + + fn deref(&self) -> &Self::Target { + self.as_dyn_bar_u32() + } +} + +fn take_dyn(x: &dyn Bar) -> T { + todo!() +} + +fn main() { + let x: &dyn Foo = &(); + let y = take_dyn(x); + let z: u32 = y; + //~^ ERROR mismatched types +} diff --git a/tests/ui/traits/trait-upcasting/inference-behavior-change-deref.stderr b/tests/ui/traits/trait-upcasting/inference-behavior-change-deref.stderr new file mode 100644 index 0000000000000..cfd6f7f175ff1 --- /dev/null +++ b/tests/ui/traits/trait-upcasting/inference-behavior-change-deref.stderr @@ -0,0 +1,16 @@ +error[E0308]: mismatched types + --> $DIR/inference-behavior-change-deref.rs:34:18 + | +LL | let z: u32 = y; + | --- ^ expected `u32`, found `i32` + | | + | expected due to this + | +help: you can convert an `i32` to a `u32` and panic if the converted value doesn't fit + | +LL | let z: u32 = y.try_into().unwrap(); + | ++++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/traits/trait-upcasting/migrate-lint-deny-regions.rs b/tests/ui/traits/trait-upcasting/migrate-lint-deny-regions.rs new file mode 100644 index 0000000000000..e743eb0ecd385 --- /dev/null +++ b/tests/ui/traits/trait-upcasting/migrate-lint-deny-regions.rs @@ -0,0 +1,18 @@ +#![deny(deref_into_dyn_supertrait)] + +use std::ops::Deref; + +trait Bar<'a> {} +trait Foo<'a>: Bar<'a> {} + +impl<'a> Deref for dyn Foo<'a> { + //~^ ERROR dyn Foo<'_>` implements `Deref` with supertrait `Bar<'_>` as target + //~| WARN this was previously accepted by the compiler + type Target = dyn Bar<'a>; + + fn deref(&self) -> &Self::Target { + todo!() + } +} + +fn main() {} diff --git a/tests/ui/traits/trait-upcasting/migrate-lint-deny-regions.stderr b/tests/ui/traits/trait-upcasting/migrate-lint-deny-regions.stderr new file mode 100644 index 0000000000000..d6480bcc66bb6 --- /dev/null +++ b/tests/ui/traits/trait-upcasting/migrate-lint-deny-regions.stderr @@ -0,0 +1,19 @@ +error: `dyn Foo<'_>` implements `Deref` with supertrait `Bar<'_>` as target + --> $DIR/migrate-lint-deny-regions.rs:8:1 + | +LL | impl<'a> Deref for dyn Foo<'a> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | type Target = dyn Bar<'a>; + | -------------------------- target type is set here + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #89460 +note: the lint level is defined here + --> $DIR/migrate-lint-deny-regions.rs:1:9 + | +LL | #![deny(deref_into_dyn_supertrait)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/traits/trait-upcasting/migrate-lint-deny.rs b/tests/ui/traits/trait-upcasting/migrate-lint-deny.rs index d624187561ed7..828aaec79ab08 100644 --- a/tests/ui/traits/trait-upcasting/migrate-lint-deny.rs +++ b/tests/ui/traits/trait-upcasting/migrate-lint-deny.rs @@ -1,15 +1,13 @@ #![deny(deref_into_dyn_supertrait)] -extern crate core; - -use core::ops::Deref; +use std::ops::Deref; // issue 89190 trait A {} trait B: A {} impl<'a> Deref for dyn 'a + B { - //~^ ERROR `(dyn B + 'a)` implements `Deref` with supertrait `A` as target + //~^ ERROR `dyn B` implements `Deref` with supertrait `A` as target //~| WARN this was previously accepted by the compiler but is being phased out; type Target = dyn A; diff --git a/tests/ui/traits/trait-upcasting/migrate-lint-deny.stderr b/tests/ui/traits/trait-upcasting/migrate-lint-deny.stderr index 4533b1163425c..522b35299e9a0 100644 --- a/tests/ui/traits/trait-upcasting/migrate-lint-deny.stderr +++ b/tests/ui/traits/trait-upcasting/migrate-lint-deny.stderr @@ -1,5 +1,5 @@ -error: `(dyn B + 'a)` implements `Deref` with supertrait `A` as target - --> $DIR/migrate-lint-deny.rs:11:1 +error: `dyn B` implements `Deref` with supertrait `A` as target + --> $DIR/migrate-lint-deny.rs:9:1 | LL | impl<'a> Deref for dyn 'a + B { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ From e6ca8e1d184a9af84eecd3733262bf62a5e8c0de Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 20 Nov 2023 19:03:40 +0000 Subject: [PATCH 2/2] Bump future release warning mode --- compiler/rustc_lint/src/deref_into_dyn_supertrait.rs | 2 +- tests/ui/traits/trait-upcasting/migrate-lint-deny-regions.rs | 2 +- .../ui/traits/trait-upcasting/migrate-lint-deny-regions.stderr | 2 +- tests/ui/traits/trait-upcasting/migrate-lint-deny.rs | 2 +- tests/ui/traits/trait-upcasting/migrate-lint-deny.stderr | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs b/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs index 41a70bfcc5936..d3e2d5c764652 100644 --- a/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs +++ b/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs @@ -50,7 +50,7 @@ declare_lint! { Warn, "`Deref` implementation usage with a supertrait trait object for output might be shadowed in the future", @future_incompatible = FutureIncompatibleInfo { - reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps, + reason: FutureIncompatibilityReason::FutureReleaseSemanticsChange, reference: "issue #89460 ", }; } diff --git a/tests/ui/traits/trait-upcasting/migrate-lint-deny-regions.rs b/tests/ui/traits/trait-upcasting/migrate-lint-deny-regions.rs index e743eb0ecd385..b3f14a5f256e5 100644 --- a/tests/ui/traits/trait-upcasting/migrate-lint-deny-regions.rs +++ b/tests/ui/traits/trait-upcasting/migrate-lint-deny-regions.rs @@ -7,7 +7,7 @@ trait Foo<'a>: Bar<'a> {} impl<'a> Deref for dyn Foo<'a> { //~^ ERROR dyn Foo<'_>` implements `Deref` with supertrait `Bar<'_>` as target - //~| WARN this was previously accepted by the compiler + //~| WARN this will change its meaning in a future release! type Target = dyn Bar<'a>; fn deref(&self) -> &Self::Target { diff --git a/tests/ui/traits/trait-upcasting/migrate-lint-deny-regions.stderr b/tests/ui/traits/trait-upcasting/migrate-lint-deny-regions.stderr index d6480bcc66bb6..250bcabc69820 100644 --- a/tests/ui/traits/trait-upcasting/migrate-lint-deny-regions.stderr +++ b/tests/ui/traits/trait-upcasting/migrate-lint-deny-regions.stderr @@ -7,7 +7,7 @@ LL | impl<'a> Deref for dyn Foo<'a> { LL | type Target = dyn Bar<'a>; | -------------------------- target type is set here | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = warning: this will change its meaning in a future release! = note: for more information, see issue #89460 note: the lint level is defined here --> $DIR/migrate-lint-deny-regions.rs:1:9 diff --git a/tests/ui/traits/trait-upcasting/migrate-lint-deny.rs b/tests/ui/traits/trait-upcasting/migrate-lint-deny.rs index 828aaec79ab08..114d2c249da06 100644 --- a/tests/ui/traits/trait-upcasting/migrate-lint-deny.rs +++ b/tests/ui/traits/trait-upcasting/migrate-lint-deny.rs @@ -8,7 +8,7 @@ trait B: A {} impl<'a> Deref for dyn 'a + B { //~^ ERROR `dyn B` implements `Deref` with supertrait `A` as target - //~| WARN this was previously accepted by the compiler but is being phased out; + //~| WARN this will change its meaning in a future release! type Target = dyn A; fn deref(&self) -> &Self::Target { diff --git a/tests/ui/traits/trait-upcasting/migrate-lint-deny.stderr b/tests/ui/traits/trait-upcasting/migrate-lint-deny.stderr index 522b35299e9a0..c8b683c23c183 100644 --- a/tests/ui/traits/trait-upcasting/migrate-lint-deny.stderr +++ b/tests/ui/traits/trait-upcasting/migrate-lint-deny.stderr @@ -7,7 +7,7 @@ LL | impl<'a> Deref for dyn 'a + B { LL | type Target = dyn A; | -------------------- target type is set here | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = warning: this will change its meaning in a future release! = note: for more information, see issue #89460 note: the lint level is defined here --> $DIR/migrate-lint-deny.rs:1:9