Skip to content

Commit ebee8e1

Browse files
committed
Error on private items with stability attributes
It doesn't make sense for a private item to have a stability attribute, and it is likely a mistake. Report an error when we see a case of this.
1 parent e742158 commit ebee8e1

File tree

3 files changed

+113
-1
lines changed

3 files changed

+113
-1
lines changed

compiler/rustc_passes/src/stability.rs

+28-1
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
219219
if kind == AnnotationKind::Prohibited
220220
|| (kind == AnnotationKind::Container && stab.level.is_stable() && is_deprecated)
221221
{
222-
self.tcx.sess.struct_span_err(span,"this stability annotation is useless")
222+
self.tcx.sess.struct_span_err(span, "this stability annotation is useless")
223223
.span_label(span, "useless stability annotation")
224224
.span_label(item_sp, "the stability attribute annotates this item")
225225
.emit();
@@ -605,6 +605,24 @@ impl<'tcx> MissingStabilityAnnotations<'tcx> {
605605
}
606606
}
607607
}
608+
609+
fn check_private_stability(&self, hir_id: HirId, span: Span) {
610+
let stab = self.tcx.stability().local_stability(hir_id);
611+
let is_error = stab.is_some() && !self.access_levels.is_reachable(hir_id);
612+
if is_error {
613+
let def_id = self.tcx.hir().local_def_id(hir_id);
614+
let descr = self.tcx.def_kind(def_id).descr(def_id.to_def_id());
615+
self.tcx
616+
.sess
617+
.struct_span_err(
618+
span,
619+
&format!("{} is private but has a stability attribute", descr),
620+
)
621+
.help("if it is meant to be private, remove the stability attribute")
622+
.help("or, if it is meant to be public, make it public")
623+
.emit();
624+
}
625+
}
608626
}
609627

610628
impl<'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'tcx> {
@@ -635,11 +653,14 @@ impl<'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'tcx> {
635653
self.check_missing_const_stability(i.hir_id(), i.span);
636654
}
637655

656+
self.check_private_stability(i.hir_id(), i.span);
657+
638658
intravisit::walk_item(self, i)
639659
}
640660

641661
fn visit_trait_item(&mut self, ti: &'tcx hir::TraitItem<'tcx>) {
642662
self.check_missing_stability(ti.hir_id(), ti.span);
663+
self.check_private_stability(ti.hir_id(), ti.span);
643664
intravisit::walk_trait_item(self, ti);
644665
}
645666

@@ -648,26 +669,31 @@ impl<'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'tcx> {
648669
if self.tcx.impl_trait_ref(impl_def_id).is_none() {
649670
self.check_missing_stability(ii.hir_id(), ii.span);
650671
}
672+
self.check_private_stability(ii.hir_id(), ii.span);
651673
intravisit::walk_impl_item(self, ii);
652674
}
653675

654676
fn visit_variant(&mut self, var: &'tcx Variant<'tcx>, g: &'tcx Generics<'tcx>, item_id: HirId) {
655677
self.check_missing_stability(var.id, var.span);
678+
self.check_private_stability(var.id, var.span);
656679
intravisit::walk_variant(self, var, g, item_id);
657680
}
658681

659682
fn visit_field_def(&mut self, s: &'tcx FieldDef<'tcx>) {
660683
self.check_missing_stability(s.hir_id, s.span);
684+
self.check_private_stability(s.hir_id, s.span);
661685
intravisit::walk_field_def(self, s);
662686
}
663687

664688
fn visit_foreign_item(&mut self, i: &'tcx hir::ForeignItem<'tcx>) {
665689
self.check_missing_stability(i.hir_id(), i.span);
690+
self.check_private_stability(i.hir_id(), i.span);
666691
intravisit::walk_foreign_item(self, i);
667692
}
668693

669694
fn visit_macro_def(&mut self, md: &'tcx hir::MacroDef<'tcx>) {
670695
self.check_missing_stability(md.hir_id(), md.span);
696+
self.check_private_stability(md.hir_id(), md.span);
671697
}
672698

673699
// Note that we don't need to `check_missing_stability` for default generic parameters,
@@ -930,6 +956,7 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
930956
let krate = tcx.hir().krate();
931957
let mut missing = MissingStabilityAnnotations { tcx, access_levels };
932958
missing.check_missing_stability(hir::CRATE_HIR_ID, krate.item.inner);
959+
missing.check_private_stability(hir::CRATE_HIR_ID, krate.item.inner);
933960
intravisit::walk_crate(&mut missing, krate);
934961
krate.visit_all_item_likes(&mut missing.as_deep_visitor());
935962
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#![feature(staged_api)]
2+
#![stable(feature = "rust1", since = "1.0.0")]
3+
#![crate_type = "lib"]
4+
5+
#[stable(feature = "rust1", since = "1.0.0")]
6+
mod mod_stable {}
7+
//~^ ERROR module is private but has a stability attribute
8+
9+
#[unstable(feature = "foo", issue = "none")]
10+
mod mod_unstable {}
11+
//~^ ERROR module is private but has a stability attribute
12+
13+
#[stable(feature = "rust1", since = "1.0.0")]
14+
fn fn_stable() {}
15+
//~^ ERROR function is private but has a stability attribute
16+
17+
#[unstable(feature = "foo", issue = "none")]
18+
fn fn_unstable() {}
19+
//~^ ERROR function is private but has a stability attribute
20+
21+
#[stable(feature = "rust1", since = "1.0.0")]
22+
#[rustc_const_stable(feature = "rust1", since = "1.0.0")]
23+
const fn const_fn_stable() {}
24+
//~^ ERROR function is private but has a stability attribute
25+
26+
#[unstable(feature = "foo", issue = "none")]
27+
#[rustc_const_unstable(feature = "foo", issue = "none")]
28+
const fn const_fn_unstable() {}
29+
//~^ ERROR function is private but has a stability attribute
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
error: module is private but has a stability attribute
2+
--> $DIR/stability-without-publicity.rs:6:1
3+
|
4+
LL | mod mod_stable {}
5+
| ^^^^^^^^^^^^^^^^^
6+
|
7+
= help: if it is meant to be private, remove the stability attribute
8+
= help: or, if it is meant to be public, make it public
9+
10+
error: module is private but has a stability attribute
11+
--> $DIR/stability-without-publicity.rs:10:1
12+
|
13+
LL | mod mod_unstable {}
14+
| ^^^^^^^^^^^^^^^^^^^
15+
|
16+
= help: if it is meant to be private, remove the stability attribute
17+
= help: or, if it is meant to be public, make it public
18+
19+
error: function is private but has a stability attribute
20+
--> $DIR/stability-without-publicity.rs:14:1
21+
|
22+
LL | fn fn_stable() {}
23+
| ^^^^^^^^^^^^^^^^^
24+
|
25+
= help: if it is meant to be private, remove the stability attribute
26+
= help: or, if it is meant to be public, make it public
27+
28+
error: function is private but has a stability attribute
29+
--> $DIR/stability-without-publicity.rs:18:1
30+
|
31+
LL | fn fn_unstable() {}
32+
| ^^^^^^^^^^^^^^^^^^^
33+
|
34+
= help: if it is meant to be private, remove the stability attribute
35+
= help: or, if it is meant to be public, make it public
36+
37+
error: function is private but has a stability attribute
38+
--> $DIR/stability-without-publicity.rs:23:1
39+
|
40+
LL | const fn const_fn_stable() {}
41+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
42+
|
43+
= help: if it is meant to be private, remove the stability attribute
44+
= help: or, if it is meant to be public, make it public
45+
46+
error: function is private but has a stability attribute
47+
--> $DIR/stability-without-publicity.rs:28:1
48+
|
49+
LL | const fn const_fn_unstable() {}
50+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
51+
|
52+
= help: if it is meant to be private, remove the stability attribute
53+
= help: or, if it is meant to be public, make it public
54+
55+
error: aborting due to 6 previous errors
56+

0 commit comments

Comments
 (0)