Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 31 additions & 2 deletions compiler/rustc_passes/src/stability.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE, LocalDefId, LocalModDefId};
use rustc_hir::intravisit::{self, Visitor, VisitorExt};
use rustc_hir::{
self as hir, AmbigArg, ConstStability, DefaultBodyStability, FieldDef, Item, ItemKind,
Stability, StabilityLevel, StableSince, TraitRef, Ty, TyKind, UnstableReason,
self as hir, AmbigArg, ConstStability, DefaultBodyStability, FieldDef, HirId, Item, ItemKind,
Path, Stability, StabilityLevel, StableSince, TraitRef, Ty, TyKind, UnstableReason, UsePath,
VERSION_PLACEHOLDER, Variant, find_attr,
};
use rustc_middle::hir::nested_filter;
Expand Down Expand Up @@ -739,6 +739,35 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> {
intravisit::walk_poly_trait_ref(self, t);
}

fn visit_use(&mut self, path: &'tcx UsePath<'tcx>, hir_id: HirId) {
let res = path.res;

// A use item can import something from two namespaces at the same time.
// For deprecation/stability we don't want to warn twice.
// This specifically happens with constructors for unit/tuple structs.
if let Some(ty_ns_res) = res.type_ns
&& let Some(value_ns_res) = res.value_ns
&& let Some(type_ns_did) = ty_ns_res.opt_def_id()
&& let Some(value_ns_did) = value_ns_res.opt_def_id()
&& let DefKind::Ctor(.., _) = self.tcx.def_kind(value_ns_did)
&& self.tcx.parent(value_ns_did) == type_ns_did
{
// Only visit the value namespace path when we've detected a duplicate,
// not the type namespace path.
let UsePath { segments, res: _, span } = *path;
self.visit_path(&Path { segments, res: value_ns_res, span }, hir_id);

// Though, visit the macro namespace if it exists,
// regardless of the checks above relating to constructors.
if let Some(res) = res.macro_ns {
self.visit_path(&Path { segments, res, span }, hir_id);
}
} else {
// if there's no duplicate, just walk as normal
intravisit::walk_use(self, path, hir_id)
}
}

fn visit_path(&mut self, path: &hir::Path<'tcx>, id: hir::HirId) {
if let Some(def_id) = path.res.opt_def_id() {
let method_span = path.segments.last().map(|s| s.ident.span);
Expand Down
45 changes: 45 additions & 0 deletions tests/ui/deprecation/unit_and_tuple_struct.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#![deny(deprecated)]

#[deprecated]
pub mod a {
pub struct Foo;
pub struct Bar();
pub struct Baz {}

pub enum Enum {
VFoo,
VBar(),
VBaz {},
}
}


use a::Foo;
//~^ ERROR use of deprecated unit struct `a::Foo`
use a::Bar;
//~^ ERROR use of deprecated tuple struct `a::Bar`
use a::Baz;
//~^ ERROR use of deprecated struct `a::Baz`

use a::Enum::VFoo;
//~^ ERROR use of deprecated unit variant `a::Enum::VFoo`
use a::Enum::VBar;
//~^ ERROR use of deprecated tuple variant `a::Enum::VBar`
use a::Enum::VBaz;
//~^ ERROR use of deprecated variant `a::Enum::VBaz`

fn main() {
a::Foo;
//~^ ERROR use of deprecated unit struct `a::Foo`
a::Bar();
//~^ ERROR use of deprecated tuple struct `a::Bar`
a::Baz {};
//~^ ERROR use of deprecated struct `a::Baz`

a::Enum::VFoo;
//~^ ERROR use of deprecated unit variant `a::Enum::VFoo`
a::Enum::VBar();
//~^ ERROR use of deprecated tuple variant `a::Enum::VBar`
a::Enum::VBaz{};
//~^ ERROR use of deprecated variant `a::Enum::VBaz`
}
80 changes: 80 additions & 0 deletions tests/ui/deprecation/unit_and_tuple_struct.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
error: use of deprecated unit struct `a::Foo`
--> $DIR/unit_and_tuple_struct.rs:17:8
|
LL | use a::Foo;
| ^^^
|
note: the lint level is defined here
--> $DIR/unit_and_tuple_struct.rs:1:9
|
LL | #![deny(deprecated)]
| ^^^^^^^^^^

error: use of deprecated tuple struct `a::Bar`
--> $DIR/unit_and_tuple_struct.rs:19:8
|
LL | use a::Bar;
| ^^^

error: use of deprecated struct `a::Baz`
--> $DIR/unit_and_tuple_struct.rs:21:8
|
LL | use a::Baz;
| ^^^

error: use of deprecated unit variant `a::Enum::VFoo`
--> $DIR/unit_and_tuple_struct.rs:24:14
|
LL | use a::Enum::VFoo;
| ^^^^

error: use of deprecated tuple variant `a::Enum::VBar`
--> $DIR/unit_and_tuple_struct.rs:26:14
|
LL | use a::Enum::VBar;
| ^^^^

error: use of deprecated variant `a::Enum::VBaz`
--> $DIR/unit_and_tuple_struct.rs:28:14
|
LL | use a::Enum::VBaz;
| ^^^^

error: use of deprecated unit struct `a::Foo`
--> $DIR/unit_and_tuple_struct.rs:32:6
|
LL | a::Foo;
| ^^^

error: use of deprecated tuple struct `a::Bar`
--> $DIR/unit_and_tuple_struct.rs:34:6
|
LL | a::Bar();
| ^^^

error: use of deprecated struct `a::Baz`
--> $DIR/unit_and_tuple_struct.rs:36:6
|
LL | a::Baz {};
| ^^^

error: use of deprecated unit variant `a::Enum::VFoo`
--> $DIR/unit_and_tuple_struct.rs:39:12
|
LL | a::Enum::VFoo;
| ^^^^

error: use of deprecated tuple variant `a::Enum::VBar`
--> $DIR/unit_and_tuple_struct.rs:41:12
|
LL | a::Enum::VBar();
| ^^^^

error: use of deprecated variant `a::Enum::VBaz`
--> $DIR/unit_and_tuple_struct.rs:43:12
|
LL | a::Enum::VBaz{};
| ^^^^

error: aborting due to 12 previous errors

Loading