Skip to content

Commit a4baa03

Browse files
Rework supertrait lint once again
1 parent 2f8d81f commit a4baa03

9 files changed

+73
-21
lines changed

compiler/rustc_lint/messages.ftl

+2-1
Original file line numberDiff line numberDiff line change
@@ -490,8 +490,9 @@ lint_requested_level = requested on the command line with `{$level} {$lint_name}
490490
491491
lint_span_use_eq_ctxt = use `.eq_ctxt()` instead of `.ctxt() == .ctxt()`
492492
493-
lint_supertrait_as_deref_target = `{$t}` implements `Deref` with supertrait `{$target_principal}` as target
493+
lint_supertrait_as_deref_target = `{$self_ty}` implements `Deref<Target = dyn {$target_principal}>` which conflicts with supertrait `{$supertrait_principal}`
494494
.label = target type is set here
495+
.note = inference and runtime behavior may change after `#[feature(trait_upcasting)]` is enabled by default
495496
496497
lint_suspicious_double_ref_clone =
497498
using `.clone()` on a double reference, which returns `{$ty}` instead of cloning the inner type

compiler/rustc_lint/src/deref_into_dyn_supertrait.rs

+21-15
Original file line numberDiff line numberDiff line change
@@ -62,26 +62,25 @@ impl<'tcx> LateLintPass<'tcx> for DerefIntoDynSupertrait {
6262
let tcx = cx.tcx;
6363
// `Deref` is being implemented for `t`
6464
if let hir::ItemKind::Impl(impl_) = item.kind
65+
// the trait is a `Deref` implementation
6566
&& let Some(trait_) = &impl_.of_trait
66-
&& let t = tcx.type_of(item.owner_id).instantiate_identity()
67-
&& let opt_did @ Some(did) = trait_.trait_def_id()
68-
&& opt_did == tcx.lang_items().deref_trait()
69-
// `t` is `dyn t_principal`
70-
&& let ty::Dynamic(data, _, ty::Dyn) = t.kind()
71-
&& let Some(t_principal) = data.principal()
67+
&& let Some(did) = trait_.trait_def_id()
68+
&& Some(did) == tcx.lang_items().deref_trait()
69+
// the self type is `dyn t_principal`
70+
&& let self_ty = tcx.type_of(item.owner_id).instantiate_identity()
71+
&& let ty::Dynamic(data, _, ty::Dyn) = self_ty.kind()
72+
&& let Some(self_principal) = data.principal()
7273
// `<T as Deref>::Target` is `dyn target_principal`
73-
&& let Some(target) = cx.get_associated_type(t, did, "Target")
74+
&& let Some(target) = cx.get_associated_type(self_ty, did, "Target")
7475
&& let ty::Dynamic(data, _, ty::Dyn) = target.kind()
7576
&& let Some(target_principal) = data.principal()
7677
// `target_principal` is a supertrait of `t_principal`
77-
&& supertraits(tcx, t_principal.with_self_ty(tcx, tcx.types.trait_object_dummy_self))
78-
.any(|sup| {
79-
tcx.erase_regions(
80-
sup.map_bound(|x| ty::ExistentialTraitRef::erase_self_ty(tcx, x)),
81-
) == tcx.erase_regions(target_principal)
82-
})
78+
&& let Some(supertrait_principal) = supertraits(tcx, self_principal.with_self_ty(tcx, self_ty))
79+
.find(|supertrait| supertrait.def_id() == target_principal.def_id())
8380
{
84-
let t = tcx.erase_regions(t);
81+
// erase regions in self type for better diagnostic presentation
82+
let (self_ty, target_principal, supertrait_principal) =
83+
tcx.erase_regions((self_ty, target_principal, supertrait_principal));
8584
let label = impl_
8685
.items
8786
.iter()
@@ -90,7 +89,14 @@ impl<'tcx> LateLintPass<'tcx> for DerefIntoDynSupertrait {
9089
cx.emit_spanned_lint(
9190
DEREF_INTO_DYN_SUPERTRAIT,
9291
tcx.def_span(item.owner_id.def_id),
93-
SupertraitAsDerefTarget { t, target_principal, label },
92+
SupertraitAsDerefTarget {
93+
self_ty,
94+
supertrait_principal: supertrait_principal.map_bound(|trait_ref| {
95+
ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref)
96+
}),
97+
target_principal,
98+
label,
99+
},
94100
);
95101
}
96102
}

compiler/rustc_lint/src/lints.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -556,8 +556,10 @@ pub enum BuiltinSpecialModuleNameUsed {
556556
// deref_into_dyn_supertrait.rs
557557
#[derive(LintDiagnostic)]
558558
#[diag(lint_supertrait_as_deref_target)]
559+
#[note]
559560
pub struct SupertraitAsDerefTarget<'a> {
560-
pub t: Ty<'a>,
561+
pub self_ty: Ty<'a>,
562+
pub supertrait_principal: PolyExistentialTraitRef<'a>,
561563
pub target_principal: PolyExistentialTraitRef<'a>,
562564
#[subdiagnostic]
563565
pub label: Option<SupertraitAsDerefTargetLabel>,

tests/ui/traits/trait-upcasting/migrate-lint-deny-regions.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ trait Bar<'a> {}
66
trait Foo<'a>: Bar<'a> {}
77

88
impl<'a> Deref for dyn Foo<'a> {
9-
//~^ ERROR dyn Foo<'_>` implements `Deref` with supertrait `Bar<'_>` as target
9+
//~^ ERROR `dyn Foo<'_>` implements `Deref<Target = dyn Bar<'_>>` which conflicts with supertrait `Bar<'_>`
1010
//~| WARN this will change its meaning in a future release!
1111
type Target = dyn Bar<'a>;
1212

tests/ui/traits/trait-upcasting/migrate-lint-deny-regions.stderr

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error: `dyn Foo<'_>` implements `Deref` with supertrait `Bar<'_>` as target
1+
error: `dyn Foo<'_>` implements `Deref<Target = dyn Bar<'_>>` which conflicts with supertrait `Bar<'_>`
22
--> $DIR/migrate-lint-deny-regions.rs:8:1
33
|
44
LL | impl<'a> Deref for dyn Foo<'a> {
@@ -9,6 +9,7 @@ LL | type Target = dyn Bar<'a>;
99
|
1010
= warning: this will change its meaning in a future release!
1111
= note: for more information, see issue #89460 <https://github.com/rust-lang/rust/issues/89460>
12+
= note: inference and runtime behavior may change after `#[feature(trait_upcasting)]` is enabled by default
1213
note: the lint level is defined here
1314
--> $DIR/migrate-lint-deny-regions.rs:1:9
1415
|

tests/ui/traits/trait-upcasting/migrate-lint-deny.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ trait A {}
77
trait B: A {}
88

99
impl<'a> Deref for dyn 'a + B {
10-
//~^ ERROR `dyn B` implements `Deref` with supertrait `A` as target
10+
//~^ ERROR `dyn B` implements `Deref<Target = dyn A>` which conflicts with supertrait `A`
1111
//~| WARN this will change its meaning in a future release!
1212

1313
type Target = dyn A;

tests/ui/traits/trait-upcasting/migrate-lint-deny.stderr

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error: `dyn B` implements `Deref` with supertrait `A` as target
1+
error: `dyn B` implements `Deref<Target = dyn A>` which conflicts with supertrait `A`
22
--> $DIR/migrate-lint-deny.rs:9:1
33
|
44
LL | impl<'a> Deref for dyn 'a + B {
@@ -9,6 +9,7 @@ LL | type Target = dyn A;
99
|
1010
= warning: this will change its meaning in a future release!
1111
= note: for more information, see issue #89460 <https://github.com/rust-lang/rust/issues/89460>
12+
= note: inference and runtime behavior may change after `#[feature(trait_upcasting)]` is enabled by default
1213
note: the lint level is defined here
1314
--> $DIR/migrate-lint-deny.rs:1:9
1415
|
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#![deny(deref_into_dyn_supertrait)]
2+
3+
use std::ops::Deref;
4+
5+
trait Bar<T> {}
6+
7+
trait Foo: Bar<i32> {
8+
fn as_dyn_bar_u32<'a>(&self) -> &(dyn Bar<u32> + 'a);
9+
}
10+
11+
impl<'a> Deref for dyn Foo + 'a {
12+
//~^ ERROR `dyn Foo` implements `Deref<Target = dyn Bar<u32>>` which conflicts with supertrait `Bar<i32>`
13+
//~| WARN this was previously accepted by the compiler
14+
type Target = dyn Bar<u32> + 'a;
15+
16+
fn deref(&self) -> &Self::Target {
17+
self.as_dyn_bar_u32()
18+
}
19+
}
20+
21+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
error: `dyn Foo` implements `Deref<Target = dyn Bar<u32>>` which conflicts with supertrait `Bar<i32>`
2+
--> $DIR/migrate-lint-different-substs.rs:11:1
3+
|
4+
LL | impl<'a> Deref for dyn Foo + 'a {
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
...
7+
LL | type Target = dyn Bar<u32> + 'a;
8+
| -------------------------------- target type is set here
9+
|
10+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
11+
= note: for more information, see issue #89460 <https://github.com/rust-lang/rust/issues/89460>
12+
= note: inference and runtime behavior may change after `#[feature(trait_upcasting)]` is enabled by default
13+
note: the lint level is defined here
14+
--> $DIR/migrate-lint-different-substs.rs:1:9
15+
|
16+
LL | #![deny(deref_into_dyn_supertrait)]
17+
| ^^^^^^^^^^^^^^^^^^^^^^^^^
18+
19+
error: aborting due to previous error
20+

0 commit comments

Comments
 (0)