Rollup merge of #118026 - compiler-errors:deref-into-dyn-regions, r=lcnr
Don't consider regions in `deref_into_dyn_supertrait` lint I actually wonder if we should just warn on *any* deref impl with a target type that matches a supertrait by *def-id*. cc #89460 r? types
This commit is contained in:
commit
ca246d32e6
@ -50,7 +50,7 @@ declare_lint! {
|
|||||||
Warn,
|
Warn,
|
||||||
"`Deref` implementation usage with a supertrait trait object for output might be shadowed in the future",
|
"`Deref` implementation usage with a supertrait trait object for output might be shadowed in the future",
|
||||||
@future_incompatible = FutureIncompatibleInfo {
|
@future_incompatible = FutureIncompatibleInfo {
|
||||||
reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps,
|
reason: FutureIncompatibilityReason::FutureReleaseSemanticsChange,
|
||||||
reference: "issue #89460 <https://github.com/rust-lang/rust/issues/89460>",
|
reference: "issue #89460 <https://github.com/rust-lang/rust/issues/89460>",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -59,12 +59,13 @@ declare_lint_pass!(DerefIntoDynSupertrait => [DEREF_INTO_DYN_SUPERTRAIT]);
|
|||||||
|
|
||||||
impl<'tcx> LateLintPass<'tcx> for DerefIntoDynSupertrait {
|
impl<'tcx> LateLintPass<'tcx> for DerefIntoDynSupertrait {
|
||||||
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
|
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
|
||||||
|
let tcx = cx.tcx;
|
||||||
// `Deref` is being implemented for `t`
|
// `Deref` is being implemented for `t`
|
||||||
if let hir::ItemKind::Impl(impl_) = item.kind
|
if let hir::ItemKind::Impl(impl_) = item.kind
|
||||||
&& let Some(trait_) = &impl_.of_trait
|
&& 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()
|
&& 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`
|
// `t` is `dyn t_principal`
|
||||||
&& let ty::Dynamic(data, _, ty::Dyn) = t.kind()
|
&& let ty::Dynamic(data, _, ty::Dyn) = t.kind()
|
||||||
&& let Some(t_principal) = data.principal()
|
&& 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 ty::Dynamic(data, _, ty::Dyn) = target.kind()
|
||||||
&& let Some(target_principal) = data.principal()
|
&& let Some(target_principal) = data.principal()
|
||||||
// `target_principal` is a supertrait of `t_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))
|
&& supertraits(tcx, t_principal.with_self_ty(tcx, tcx.types.trait_object_dummy_self))
|
||||||
.any(|sup| sup.map_bound(|x| ty::ExistentialTraitRef::erase_self_ty(cx.tcx, x)) == target_principal)
|
.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_
|
let label = impl_
|
||||||
.items
|
.items
|
||||||
.iter()
|
.iter()
|
||||||
@ -83,7 +89,7 @@ impl<'tcx> LateLintPass<'tcx> for DerefIntoDynSupertrait {
|
|||||||
.map(|label| SupertraitAsDerefTargetLabel { label });
|
.map(|label| SupertraitAsDerefTargetLabel { label });
|
||||||
cx.emit_spanned_lint(
|
cx.emit_spanned_lint(
|
||||||
DEREF_INTO_DYN_SUPERTRAIT,
|
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 },
|
SupertraitAsDerefTarget { t, target_principal, label },
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,36 @@
|
|||||||
|
#![deny(deref_into_dyn_supertrait)]
|
||||||
|
#![feature(trait_upcasting)] // remove this and the test compiles
|
||||||
|
|
||||||
|
use std::ops::Deref;
|
||||||
|
|
||||||
|
trait Bar<T> {}
|
||||||
|
impl<T, U> Bar<U> for T {}
|
||||||
|
|
||||||
|
trait Foo: Bar<i32> {
|
||||||
|
fn as_dyn_bar_u32<'a>(&self) -> &(dyn Bar<u32> + 'a);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Foo for () {
|
||||||
|
fn as_dyn_bar_u32<'a>(&self) -> &(dyn Bar<u32> + 'a) {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Deref for dyn Foo + 'a {
|
||||||
|
type Target = dyn Bar<u32> + 'a;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
self.as_dyn_bar_u32()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn take_dyn<T>(x: &dyn Bar<T>) -> T {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let x: &dyn Foo = &();
|
||||||
|
let y = take_dyn(x);
|
||||||
|
let z: u32 = y;
|
||||||
|
//~^ ERROR mismatched types
|
||||||
|
}
|
@ -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`.
|
18
tests/ui/traits/trait-upcasting/migrate-lint-deny-regions.rs
Normal file
18
tests/ui/traits/trait-upcasting/migrate-lint-deny-regions.rs
Normal file
@ -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 will change its meaning in a future release!
|
||||||
|
type Target = dyn Bar<'a>;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
@ -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 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
|
||||||
|
|
|
||||||
|
LL | #![deny(deref_into_dyn_supertrait)]
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
@ -1,16 +1,14 @@
|
|||||||
#![deny(deref_into_dyn_supertrait)]
|
#![deny(deref_into_dyn_supertrait)]
|
||||||
|
|
||||||
extern crate core;
|
use std::ops::Deref;
|
||||||
|
|
||||||
use core::ops::Deref;
|
|
||||||
|
|
||||||
// issue 89190
|
// issue 89190
|
||||||
trait A {}
|
trait A {}
|
||||||
trait B: A {}
|
trait B: A {}
|
||||||
|
|
||||||
impl<'a> Deref for dyn 'a + B {
|
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;
|
//~| WARN this will change its meaning in a future release!
|
||||||
|
|
||||||
type Target = dyn A;
|
type Target = dyn A;
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
error: `(dyn B + 'a)` implements `Deref` with supertrait `A` as target
|
error: `dyn B` implements `Deref` with supertrait `A` as target
|
||||||
--> $DIR/migrate-lint-deny.rs:11:1
|
--> $DIR/migrate-lint-deny.rs:9:1
|
||||||
|
|
|
|
||||||
LL | impl<'a> Deref for dyn 'a + B {
|
LL | impl<'a> Deref for dyn 'a + B {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
@ -7,7 +7,7 @@ LL | impl<'a> Deref for dyn 'a + B {
|
|||||||
LL | type Target = dyn A;
|
LL | type Target = dyn A;
|
||||||
| -------------------- target type is set here
|
| -------------------- 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 <https://github.com/rust-lang/rust/issues/89460>
|
= note: for more information, see issue #89460 <https://github.com/rust-lang/rust/issues/89460>
|
||||||
note: the lint level is defined here
|
note: the lint level is defined here
|
||||||
--> $DIR/migrate-lint-deny.rs:1:9
|
--> $DIR/migrate-lint-deny.rs:1:9
|
||||||
|
Loading…
x
Reference in New Issue
Block a user