Skip to content

Commit 42bed72

Browse files
committed
Auto merge of #38689 - pnkfelix:dont-check-stability-on-private-items, r=nikomatsakis
Dont check stability for items that are not pub to universe. Dont check stability for items that are not pub to universe. In other words, skip it for private and even `pub(restricted)` items, because stability checks are only relevant to things visible in other crates. Fix #38412.
2 parents ea2d41e + ab8e925 commit 42bed72

File tree

4 files changed

+285
-1
lines changed

4 files changed

+285
-1
lines changed

src/librustc/middle/stability.rs

+36-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use hir::map as hir_map;
1818
use lint;
1919
use hir::def::Def;
2020
use hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId, DefIndex, LOCAL_CRATE};
21-
use ty::TyCtxt;
21+
use ty::{self, TyCtxt};
2222
use middle::privacy::AccessLevels;
2323
use syntax::symbol::Symbol;
2424
use syntax_pos::{Span, DUMMY_SP};
@@ -432,6 +432,36 @@ struct Checker<'a, 'tcx: 'a> {
432432
}
433433

434434
impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
435+
// (See issue #38412)
436+
fn skip_stability_check_due_to_privacy(self, def_id: DefId) -> bool {
437+
let visibility = {
438+
// Check if `def_id` is a trait method.
439+
match self.sess.cstore.associated_item(def_id) {
440+
Some(ty::AssociatedItem { container: ty::TraitContainer(trait_def_id), .. }) => {
441+
// Trait methods do not declare visibility (even
442+
// for visibility info in cstore). Use containing
443+
// trait instead, so methods of pub traits are
444+
// themselves considered pub.
445+
self.sess.cstore.visibility(trait_def_id)
446+
}
447+
_ => {
448+
// Otherwise, cstore info works directly.
449+
self.sess.cstore.visibility(def_id)
450+
}
451+
}
452+
};
453+
454+
match visibility {
455+
// must check stability for pub items.
456+
ty::Visibility::Public => false,
457+
458+
// these are not visible outside crate; therefore
459+
// stability markers are irrelevant, if even present.
460+
ty::Visibility::Restricted(..) |
461+
ty::Visibility::Invisible => true,
462+
}
463+
}
464+
435465
pub fn check_stability(self, def_id: DefId, id: NodeId, span: Span) {
436466
if self.sess.codemap().span_allows_unstable(span) {
437467
debug!("stability: \
@@ -492,6 +522,11 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
492522
self.stability.borrow_mut().used_features.insert(feature.clone(), level.clone());
493523
}
494524

525+
// Issue 38412: private items lack stability markers.
526+
if self.skip_stability_check_due_to_privacy(def_id) {
527+
return
528+
}
529+
495530
match stability {
496531
Some(&Stability { level: attr::Unstable {ref reason, issue}, ref feature, .. }) => {
497532
if !self.stability.borrow().active_features.contains(feature) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// This crate attempts to enumerate the various scenarios for how a
12+
// type can define fields and methods with various visiblities and
13+
// stabilities.
14+
//
15+
// The basic stability pattern in this file has four cases:
16+
// 1. no stability attribute at all
17+
// 2. a stable attribute (feature "unit_test")
18+
// 3. an unstable attribute that unit test declares (feature "unstable_declared")
19+
// 4. an unstable attribute that unit test fails to declare (feature "unstable_undeclared")
20+
//
21+
// This file also covers four kinds of visibility: private,
22+
// pub(module), pub(crate), and pub.
23+
//
24+
// However, since stability attributes can only be observed in
25+
// cross-crate linkage scenarios, there is little reason to take the
26+
// cross-product (4 stability cases * 4 visiblity cases), because the
27+
// first three visibility cases cannot be accessed outside this crate,
28+
// and therefore stability is only relevant when the visibility is pub
29+
// to the whole universe.
30+
//
31+
// (The only reason to do so would be if one were worried about the
32+
// compiler having some subtle bug where adding a stability attribute
33+
// introduces a privacy violation. As a way to provide evidence that
34+
// this is not occurring, I have put stability attributes on some
35+
// non-pub fields, marked with SILLY below)
36+
37+
#![feature(staged_api)]
38+
#![feature(pub_restricted)]
39+
40+
#![stable(feature = "unit_test", since = "0.0.0")]
41+
42+
#[stable(feature = "unit_test", since = "0.0.0")]
43+
pub use m::{Record, Trait, Tuple};
44+
45+
mod m {
46+
#[derive(Default)]
47+
#[stable(feature = "unit_test", since = "0.0.0")]
48+
pub struct Record {
49+
#[stable(feature = "unit_test", since = "0.0.0")]
50+
pub a_stable_pub: i32,
51+
#[unstable(feature = "unstable_declared", issue = "38412")]
52+
pub a_unstable_declared_pub: i32,
53+
#[unstable(feature = "unstable_undeclared", issue = "38412")]
54+
pub a_unstable_undeclared_pub: i32,
55+
#[unstable(feature = "unstable_undeclared", issue = "38412")] // SILLY
56+
pub(crate) b_crate: i32,
57+
#[unstable(feature = "unstable_declared", issue = "38412")] // SILLY
58+
pub(m) c_mod: i32,
59+
#[stable(feature = "unit_test", since = "0.0.0")] // SILLY
60+
d_priv: i32
61+
}
62+
63+
#[derive(Default)]
64+
#[stable(feature = "unit_test", since = "1.0.0")]
65+
pub struct Tuple(
66+
#[stable(feature = "unit_test", since = "0.0.0")]
67+
pub i32,
68+
#[unstable(feature = "unstable_declared", issue = "38412")]
69+
pub i32,
70+
#[unstable(feature = "unstable_undeclared", issue = "38412")]
71+
pub i32,
72+
73+
pub(crate) i32,
74+
pub(m) i32,
75+
i32);
76+
77+
impl Record {
78+
#[stable(feature = "unit_test", since = "1.0.0")]
79+
pub fn new() -> Self { Default::default() }
80+
}
81+
82+
impl Tuple {
83+
#[stable(feature = "unit_test", since = "1.0.0")]
84+
pub fn new() -> Self { Default::default() }
85+
}
86+
87+
88+
#[stable(feature = "unit_test", since = "0.0.0")]
89+
pub trait Trait {
90+
#[stable(feature = "unit_test", since = "0.0.0")]
91+
type Type;
92+
#[stable(feature = "unit_test", since = "0.0.0")]
93+
fn stable_trait_method(&self) -> Self::Type;
94+
#[unstable(feature = "unstable_undeclared", issue = "38412")]
95+
fn unstable_undeclared_trait_method(&self) -> Self::Type;
96+
#[unstable(feature = "unstable_declared", issue = "38412")]
97+
fn unstable_declared_trait_method(&self) -> Self::Type;
98+
}
99+
100+
#[stable(feature = "unit_test", since = "0.0.0")]
101+
impl Trait for Record {
102+
type Type = i32;
103+
fn stable_trait_method(&self) -> i32 { self.d_priv }
104+
fn unstable_undeclared_trait_method(&self) -> i32 { self.d_priv }
105+
fn unstable_declared_trait_method(&self) -> i32 { self.d_priv }
106+
}
107+
108+
#[stable(feature = "unit_test", since = "0.0.0")]
109+
impl Trait for Tuple {
110+
type Type = i32;
111+
fn stable_trait_method(&self) -> i32 { self.3 }
112+
fn unstable_undeclared_trait_method(&self) -> i32 { self.3 }
113+
fn unstable_declared_trait_method(&self) -> i32 { self.3 }
114+
}
115+
116+
impl Record {
117+
#[unstable(feature = "unstable_undeclared", issue = "38412")]
118+
pub fn unstable_undeclared(&self) -> i32 { self.d_priv }
119+
#[unstable(feature = "unstable_declared", issue = "38412")]
120+
pub fn unstable_declared(&self) -> i32 { self.d_priv }
121+
#[stable(feature = "unit_test", since = "0.0.0")]
122+
pub fn stable(&self) -> i32 { self.d_priv }
123+
124+
#[unstable(feature = "unstable_undeclared", issue = "38412")] // SILLY
125+
pub(crate) fn pub_crate(&self) -> i32 { self.d_priv }
126+
#[unstable(feature = "unstable_declared", issue = "38412")] // SILLY
127+
pub(m) fn pub_mod(&self) -> i32 { self.d_priv }
128+
#[stable(feature = "unit_test", since = "0.0.0")] // SILLY
129+
fn private(&self) -> i32 { self.d_priv }
130+
}
131+
132+
impl Tuple {
133+
#[unstable(feature = "unstable_undeclared", issue = "38412")]
134+
pub fn unstable_undeclared(&self) -> i32 { self.0 }
135+
#[unstable(feature = "unstable_declared", issue = "38412")]
136+
pub fn unstable_declared(&self) -> i32 { self.0 }
137+
#[stable(feature = "unit_test", since = "0.0.0")]
138+
pub fn stable(&self) -> i32 { self.0 }
139+
140+
pub(crate) fn pub_crate(&self) -> i32 { self.0 }
141+
pub(m) fn pub_mod(&self) -> i32 { self.0 }
142+
fn private(&self) -> i32 { self.0 }
143+
}
144+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// aux-build:pub_and_stability.rs
12+
13+
#![feature(staged_api)]
14+
#![feature(unused_feature)]
15+
16+
// A big point of this test is that we *declare* `unstable_declared`,
17+
// but do *not* declare `unstable_undeclared`. This way we can check
18+
// that the compiler is letting in uses of declared feature-gated
19+
// stuff but still rejecting uses of undeclared feature-gated stuff.
20+
#![feature(unstable_declared)]
21+
22+
extern crate pub_and_stability;
23+
use pub_and_stability::{Record, Trait, Tuple};
24+
25+
fn main() {
26+
// Okay
27+
let Record { .. } = Record::new();
28+
// Okay (for now; see RFC Issue #902)
29+
let Tuple(..) = Tuple::new();
30+
31+
// Okay
32+
let Record { a_stable_pub: _, a_unstable_declared_pub: _, .. } = Record::new();
33+
// Okay (for now; see RFC Issue #902)
34+
let Tuple(_, _, ..) = Tuple::new(); // analogous to above
35+
36+
let Record { a_stable_pub: _, a_unstable_declared_pub: _, a_unstable_undeclared_pub: _, .. } =
37+
Record::new();
38+
//~^^ ERROR use of unstable library feature 'unstable_undeclared'
39+
40+
let Tuple(_, _, _, ..) = Tuple::new(); // analogous to previous
41+
//~^ ERROR use of unstable library feature 'unstable_undeclared'
42+
43+
let r = Record::new();
44+
let t = Tuple::new();
45+
46+
r.a_stable_pub;
47+
r.a_unstable_declared_pub;
48+
r.a_unstable_undeclared_pub; //~ ERROR use of unstable library feature
49+
r.b_crate; //~ ERROR is private
50+
r.c_mod; //~ ERROR is private
51+
r.d_priv; //~ ERROR is private
52+
53+
t.0;
54+
t.1;
55+
t.2; //~ ERROR use of unstable library feature
56+
t.3; //~ ERROR is private
57+
t.4; //~ ERROR is private
58+
t.5; //~ ERROR is private
59+
60+
r.stable_trait_method();
61+
r.unstable_declared_trait_method();
62+
r.unstable_undeclared_trait_method(); //~ ERROR use of unstable library feature
63+
64+
r.stable();
65+
r.unstable_declared();
66+
r.unstable_undeclared(); //~ ERROR use of unstable library feature
67+
68+
r.pub_crate(); //~ ERROR `pub_crate` is private
69+
r.pub_mod(); //~ ERROR `pub_mod` is private
70+
r.private(); //~ ERROR `private` is private
71+
72+
let t = Tuple::new();
73+
t.stable_trait_method();
74+
t.unstable_declared_trait_method();
75+
t.unstable_undeclared_trait_method(); //~ ERROR use of unstable library feature
76+
77+
t.stable();
78+
t.unstable_declared();
79+
t.unstable_undeclared(); //~ ERROR use of unstable library feature
80+
81+
t.pub_crate(); //~ ERROR `pub_crate` is private
82+
t.pub_mod(); //~ ERROR `pub_mod` is private
83+
t.private(); //~ ERROR `private` is private
84+
85+
}

src/test/compile-fail/issue-38412.rs

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
fn main() {
12+
let Box(a) = loop { };
13+
//~^ ERROR field `0` of struct `std::boxed::Box` is private
14+
15+
// (The below is a trick to allow compiler to infer a type for
16+
// variable `a` without attempting to ascribe a type to the
17+
// pattern or otherwise attempting to name the Box type, which
18+
// would run afoul of issue #22207)
19+
let _b: *mut i32 = *a;
20+
}

0 commit comments

Comments
 (0)