Skip to content

Commit a508f61

Browse files
authored
Rollup merge of #147994 - jdonszelmann:duplicate-warning-struct, r=petrochenkov
Deduplicate deprecation warning when using unit or tuple structs First commit adds a test that's broken currently, 2nd commit fixes it. Created with `@WaffleLapkin`
2 parents 1ef7943 + 1b00911 commit a508f61

File tree

3 files changed

+156
-2
lines changed

3 files changed

+156
-2
lines changed

compiler/rustc_passes/src/stability.rs

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ use rustc_hir::def::{DefKind, Res};
1212
use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE, LocalDefId, LocalModDefId};
1313
use rustc_hir::intravisit::{self, Visitor, VisitorExt};
1414
use rustc_hir::{
15-
self as hir, AmbigArg, ConstStability, DefaultBodyStability, FieldDef, Item, ItemKind,
16-
Stability, StabilityLevel, StableSince, TraitRef, Ty, TyKind, UnstableReason,
15+
self as hir, AmbigArg, ConstStability, DefaultBodyStability, FieldDef, HirId, Item, ItemKind,
16+
Path, Stability, StabilityLevel, StableSince, TraitRef, Ty, TyKind, UnstableReason, UsePath,
1717
VERSION_PLACEHOLDER, Variant, find_attr,
1818
};
1919
use rustc_middle::hir::nested_filter;
@@ -739,6 +739,35 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> {
739739
intravisit::walk_poly_trait_ref(self, t);
740740
}
741741

742+
fn visit_use(&mut self, path: &'tcx UsePath<'tcx>, hir_id: HirId) {
743+
let res = path.res;
744+
745+
// A use item can import something from two namespaces at the same time.
746+
// For deprecation/stability we don't want to warn twice.
747+
// This specifically happens with constructors for unit/tuple structs.
748+
if let Some(ty_ns_res) = res.type_ns
749+
&& let Some(value_ns_res) = res.value_ns
750+
&& let Some(type_ns_did) = ty_ns_res.opt_def_id()
751+
&& let Some(value_ns_did) = value_ns_res.opt_def_id()
752+
&& let DefKind::Ctor(.., _) = self.tcx.def_kind(value_ns_did)
753+
&& self.tcx.parent(value_ns_did) == type_ns_did
754+
{
755+
// Only visit the value namespace path when we've detected a duplicate,
756+
// not the type namespace path.
757+
let UsePath { segments, res: _, span } = *path;
758+
self.visit_path(&Path { segments, res: value_ns_res, span }, hir_id);
759+
760+
// Though, visit the macro namespace if it exists,
761+
// regardless of the checks above relating to constructors.
762+
if let Some(res) = res.macro_ns {
763+
self.visit_path(&Path { segments, res, span }, hir_id);
764+
}
765+
} else {
766+
// if there's no duplicate, just walk as normal
767+
intravisit::walk_use(self, path, hir_id)
768+
}
769+
}
770+
742771
fn visit_path(&mut self, path: &hir::Path<'tcx>, id: hir::HirId) {
743772
if let Some(def_id) = path.res.opt_def_id() {
744773
let method_span = path.segments.last().map(|s| s.ident.span);
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
#![deny(deprecated)]
2+
3+
#[deprecated]
4+
pub mod a {
5+
pub struct Foo;
6+
pub struct Bar();
7+
pub struct Baz {}
8+
9+
pub enum Enum {
10+
VFoo,
11+
VBar(),
12+
VBaz {},
13+
}
14+
}
15+
16+
17+
use a::Foo;
18+
//~^ ERROR use of deprecated unit struct `a::Foo`
19+
use a::Bar;
20+
//~^ ERROR use of deprecated tuple struct `a::Bar`
21+
use a::Baz;
22+
//~^ ERROR use of deprecated struct `a::Baz`
23+
24+
use a::Enum::VFoo;
25+
//~^ ERROR use of deprecated unit variant `a::Enum::VFoo`
26+
use a::Enum::VBar;
27+
//~^ ERROR use of deprecated tuple variant `a::Enum::VBar`
28+
use a::Enum::VBaz;
29+
//~^ ERROR use of deprecated variant `a::Enum::VBaz`
30+
31+
fn main() {
32+
a::Foo;
33+
//~^ ERROR use of deprecated unit struct `a::Foo`
34+
a::Bar();
35+
//~^ ERROR use of deprecated tuple struct `a::Bar`
36+
a::Baz {};
37+
//~^ ERROR use of deprecated struct `a::Baz`
38+
39+
a::Enum::VFoo;
40+
//~^ ERROR use of deprecated unit variant `a::Enum::VFoo`
41+
a::Enum::VBar();
42+
//~^ ERROR use of deprecated tuple variant `a::Enum::VBar`
43+
a::Enum::VBaz{};
44+
//~^ ERROR use of deprecated variant `a::Enum::VBaz`
45+
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
error: use of deprecated unit struct `a::Foo`
2+
--> $DIR/unit_and_tuple_struct.rs:17:8
3+
|
4+
LL | use a::Foo;
5+
| ^^^
6+
|
7+
note: the lint level is defined here
8+
--> $DIR/unit_and_tuple_struct.rs:1:9
9+
|
10+
LL | #![deny(deprecated)]
11+
| ^^^^^^^^^^
12+
13+
error: use of deprecated tuple struct `a::Bar`
14+
--> $DIR/unit_and_tuple_struct.rs:19:8
15+
|
16+
LL | use a::Bar;
17+
| ^^^
18+
19+
error: use of deprecated struct `a::Baz`
20+
--> $DIR/unit_and_tuple_struct.rs:21:8
21+
|
22+
LL | use a::Baz;
23+
| ^^^
24+
25+
error: use of deprecated unit variant `a::Enum::VFoo`
26+
--> $DIR/unit_and_tuple_struct.rs:24:14
27+
|
28+
LL | use a::Enum::VFoo;
29+
| ^^^^
30+
31+
error: use of deprecated tuple variant `a::Enum::VBar`
32+
--> $DIR/unit_and_tuple_struct.rs:26:14
33+
|
34+
LL | use a::Enum::VBar;
35+
| ^^^^
36+
37+
error: use of deprecated variant `a::Enum::VBaz`
38+
--> $DIR/unit_and_tuple_struct.rs:28:14
39+
|
40+
LL | use a::Enum::VBaz;
41+
| ^^^^
42+
43+
error: use of deprecated unit struct `a::Foo`
44+
--> $DIR/unit_and_tuple_struct.rs:32:6
45+
|
46+
LL | a::Foo;
47+
| ^^^
48+
49+
error: use of deprecated tuple struct `a::Bar`
50+
--> $DIR/unit_and_tuple_struct.rs:34:6
51+
|
52+
LL | a::Bar();
53+
| ^^^
54+
55+
error: use of deprecated struct `a::Baz`
56+
--> $DIR/unit_and_tuple_struct.rs:36:6
57+
|
58+
LL | a::Baz {};
59+
| ^^^
60+
61+
error: use of deprecated unit variant `a::Enum::VFoo`
62+
--> $DIR/unit_and_tuple_struct.rs:39:12
63+
|
64+
LL | a::Enum::VFoo;
65+
| ^^^^
66+
67+
error: use of deprecated tuple variant `a::Enum::VBar`
68+
--> $DIR/unit_and_tuple_struct.rs:41:12
69+
|
70+
LL | a::Enum::VBar();
71+
| ^^^^
72+
73+
error: use of deprecated variant `a::Enum::VBaz`
74+
--> $DIR/unit_and_tuple_struct.rs:43:12
75+
|
76+
LL | a::Enum::VBaz{};
77+
| ^^^^
78+
79+
error: aborting due to 12 previous errors
80+

0 commit comments

Comments
 (0)