Skip to content

Commit 5645122

Browse files
committed
Check adjustments and node substs
Cleanup checking of inherent static methods and fix checking of inherent associated constants Add more tests
1 parent c743e12 commit 5645122

File tree

5 files changed

+113
-36
lines changed

5 files changed

+113
-36
lines changed

src/librustc_privacy/lib.rs

+43-29
Original file line numberDiff line numberDiff line change
@@ -589,12 +589,23 @@ impl<'a, 'tcx> TypePrivacyVisitor<'a, 'tcx> {
589589
}
590590

591591
fn check_expr_pat_type(&mut self, id: ast::NodeId, span: Span) -> bool {
592+
self.span = span;
592593
if let Some(ty) = self.tables.node_id_to_type_opt(id) {
593-
self.span = span;
594-
ty.visit_with(self)
595-
} else {
596-
false
594+
if ty.visit_with(self) {
595+
return true;
596+
}
597+
}
598+
if self.tables.node_substs(id).visit_with(self) {
599+
return true;
597600
}
601+
if let Some(adjustments) = self.tables.adjustments.get(&id) {
602+
for adjustment in adjustments {
603+
if adjustment.target.visit_with(self) {
604+
return true;
605+
}
606+
}
607+
}
608+
false
598609
}
599610

600611
fn check_item(&mut self, item_id: ast::NodeId) -> &mut Self {
@@ -658,11 +669,10 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
658669
}
659670
hir::ExprMethodCall(name, ..) => {
660671
// Method calls have to be checked specially.
661-
if let Some(method) = self.tables.method_map.get(&ty::MethodCall::expr(expr.id)) {
662-
self.span = name.span;
663-
if method.ty.visit_with(self) || method.substs.visit_with(self) {
664-
return;
665-
}
672+
let def_id = self.tables.type_dependent_defs[&expr.id].def_id();
673+
self.span = name.span;
674+
if self.tcx.type_of(def_id).visit_with(self) {
675+
return;
666676
}
667677
}
668678
_ => {}
@@ -671,6 +681,24 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
671681
intravisit::walk_expr(self, expr);
672682
}
673683

684+
fn visit_qpath(&mut self, qpath: &'tcx hir::QPath, id: ast::NodeId, span: Span) {
685+
// Inherent associated constants don't have self type in substs,
686+
// we have to check it additionally.
687+
if let hir::QPath::TypeRelative(..) = *qpath {
688+
if let Some(def) = self.tables.type_dependent_defs.get(&id).cloned() {
689+
if let Some(assoc_item) = self.tcx.opt_associated_item(def.def_id()) {
690+
if let ty::ImplContainer(impl_def_id) = assoc_item.container {
691+
if self.tcx.type_of(impl_def_id).visit_with(self) {
692+
return;
693+
}
694+
}
695+
}
696+
}
697+
}
698+
699+
intravisit::walk_qpath(self, qpath, id, span);
700+
}
701+
674702
// Check types of patterns
675703
fn visit_pat(&mut self, pattern: &'tcx hir::Pat) {
676704
if self.check_expr_pat_type(pattern.id, pattern.span) {
@@ -767,25 +795,11 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
767795
self.tcx.sess.span_err(self.span, &msg);
768796
return true;
769797
}
770-
if let ty::TyFnDef(..) = ty.sty {
771-
// Inherent static methods don't have self type in substs,
772-
// we have to check it additionally.
773-
let mut impl_def_id = None;
774-
if let Some(node_id) = self.tcx.hir.as_local_node_id(def_id) {
775-
if let hir::map::NodeImplItem(..) = self.tcx.hir.get(node_id) {
776-
impl_def_id = Some(self.tcx.hir.get_parent_did(node_id));
777-
}
778-
} else if let Some(Def::Method(..)) = self.tcx.describe_def(def_id) {
779-
let candidate_impl_def_id = self.tcx.parent_def_id(def_id)
780-
.expect("no parent for method def_id");
781-
// `is_none` means it's an impl, not a trait
782-
if self.tcx.describe_def(candidate_impl_def_id).is_none() {
783-
impl_def_id = Some(candidate_impl_def_id)
784-
}
785-
}
786-
if let Some(impl_def_id) = impl_def_id {
787-
let self_ty = self.tcx.type_of(impl_def_id);
788-
if self_ty.visit_with(self) {
798+
// Inherent static methods don't have self type in substs,
799+
// we have to check it additionally.
800+
if let Some(assoc_item) = self.tcx.opt_associated_item(def_id) {
801+
if let ty::ImplContainer(impl_def_id) = assoc_item.container {
802+
if self.tcx.type_of(impl_def_id).visit_with(self) {
789803
return true;
790804
}
791805
}
@@ -827,7 +841,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
827841
self.tcx.sess.span_err(self.span, &msg);
828842
return true;
829843
}
830-
// Skip `Self` to avoid infinite recursion
844+
// `Self` here is the same `TyAnon`, so skip it to avoid infinite recursion
831845
for subst in trait_ref.substs.iter().skip(1) {
832846
if subst.visit_with(self) {
833847
return true;

src/test/compile-fail/auxiliary/private-inferred-type.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ pub struct Pub<T = Alias>(pub T);
2828
impl Pub<Priv> {
2929
pub fn static_method() {}
3030
}
31+
impl Pub<u8> {
32+
fn priv_metod(&self) {}
33+
}
3134

3235
pub macro m() {
3336
priv_fn;
@@ -37,5 +40,5 @@ pub macro m() {
3740
<u8 as PubTrait>::method;
3841
PrivTupleStruct;
3942
PubTupleStruct;
40-
Pub::static_method;
43+
Pub(0u8).priv_metod();
4144
}

src/test/compile-fail/private-inferred-type-3.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
// error-pattern:type `fn() {<u8 as ext::PrivTrait>::method}` is private
1616
// error-pattern:type `fn(u8) -> ext::PrivTupleStruct {ext::PrivTupleStruct::{{constructor}}}` is pr
1717
// error-pattern:type `fn(u8) -> ext::PubTupleStruct {ext::PubTupleStruct::{{constructor}}}` is priv
18-
// error-pattern:type `ext::Priv` is private
18+
// error-pattern:type `fn(&ext::Pub<u8>) {<ext::Pub<u8>>::priv_metod}` is private
1919

2020
#![feature(decl_macro)]
2121

src/test/compile-fail/private-inferred-type.rs

+61-5
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
#![feature(associated_consts)]
1112
#![feature(conservative_impl_trait)]
1213
#![feature(decl_macro)]
1314

@@ -29,7 +30,19 @@ mod m {
2930

3031
impl Pub<Priv> {
3132
pub fn static_method() {}
33+
pub const INHERENT_ASSOC_CONST: u8 = 0;
3234
}
35+
impl<T> Pub<T> {
36+
pub fn static_method_generic_self() {}
37+
pub const INHERENT_ASSOC_CONST_GENERIC_SELF: u8 = 0;
38+
}
39+
impl Pub<u8> {
40+
fn priv_metod(&self) {}
41+
pub fn method_with_substs<T>(&self) {}
42+
pub fn method_with_priv_params(&self, _: Priv) {}
43+
}
44+
impl TraitWithAssocConst for Priv {}
45+
impl TraitWithAssocTy for Priv { type AssocTy = u8; }
3346

3447
pub macro m() {
3548
priv_fn; //~ ERROR type `fn() {m::priv_fn}` is private
@@ -41,28 +54,71 @@ mod m {
4154
//~^ ERROR type `fn(u8) -> m::PrivTupleStruct {m::PrivTupleStruct::{{constructor}}}` is priv
4255
PubTupleStruct;
4356
//~^ ERROR type `fn(u8) -> m::PubTupleStruct {m::PubTupleStruct::{{constructor}}}` is privat
44-
Pub::static_method; //~ ERROR type `m::Priv` is private
57+
Pub(0u8).priv_metod();
58+
//~^ ERROR type `fn(&m::Pub<u8>) {<m::Pub<u8>>::priv_metod}` is private
4559
}
4660

4761
trait Trait {}
4862
pub trait TraitWithTyParam<T> {}
49-
pub trait TraitWithAssocTy { type X; }
63+
pub trait TraitWithTyParam2<T> { fn pub_method() {} }
64+
pub trait TraitWithAssocTy { type AssocTy; }
65+
pub trait TraitWithAssocConst { const TRAIT_ASSOC_CONST: u8 = 0; }
5066
impl Trait for u8 {}
5167
impl<T> TraitWithTyParam<T> for u8 {}
52-
impl TraitWithAssocTy for u8 { type X = Priv; }
68+
impl TraitWithTyParam2<Priv> for u8 {}
69+
impl TraitWithAssocTy for u8 { type AssocTy = Priv; }
5370

5471
pub fn leak_anon1() -> impl Trait + 'static { 0 }
5572
pub fn leak_anon2() -> impl TraitWithTyParam<Alias> { 0 }
56-
pub fn leak_anon3() -> impl TraitWithAssocTy<X = Alias> { 0 }
73+
pub fn leak_anon3() -> impl TraitWithAssocTy<AssocTy = Alias> { 0 }
5774

5875
pub fn leak_dyn1() -> Box<Trait + 'static> { Box::new(0) }
5976
pub fn leak_dyn2() -> Box<TraitWithTyParam<Alias>> { Box::new(0) }
60-
pub fn leak_dyn3() -> Box<TraitWithAssocTy<X = Alias>> { Box::new(0) }
77+
pub fn leak_dyn3() -> Box<TraitWithAssocTy<AssocTy = Alias>> { Box::new(0) }
78+
}
79+
80+
mod adjust {
81+
// Construct a chain of derefs with a private type in the middle
82+
use std::ops::Deref;
83+
84+
pub struct S1;
85+
struct S2;
86+
pub type S2Alias = S2;
87+
pub struct S3;
88+
89+
impl Deref for S1 {
90+
type Target = S2Alias;
91+
fn deref(&self) -> &Self::Target { loop {} }
92+
}
93+
impl Deref for S2 {
94+
type Target = S3;
95+
fn deref(&self) -> &Self::Target { loop {} }
96+
}
97+
98+
impl S3 {
99+
pub fn method_s3(&self) {}
100+
}
61101
}
62102

63103
fn main() {
104+
let _: m::Alias; //~ ERROR type `m::Priv` is private
105+
let _: <m::Alias as m::TraitWithAssocTy>::AssocTy; // FIXME
64106
m::Alias {}; //~ ERROR type `m::Priv` is private
65107
m::Pub { 0: m::Alias {} }; //~ ERROR type `m::Priv` is private
108+
m::Pub { 0: loop {} }; // FIXME
109+
m::Pub::static_method; //~ ERROR type `m::Priv` is private
110+
m::Pub::INHERENT_ASSOC_CONST; //~ ERROR type `m::Priv` is private
111+
m::Pub(0u8).method_with_substs::<m::Alias>(); //~ ERROR type `m::Priv` is private
112+
m::Pub(0u8).method_with_priv_params(loop{}); //~ ERROR type `m::Priv` is private
113+
<m::Alias as m::TraitWithAssocConst>::TRAIT_ASSOC_CONST; //~ ERROR type `m::Priv` is private
114+
<m::Pub<m::Alias>>::INHERENT_ASSOC_CONST; //~ ERROR type `m::Priv` is private
115+
<m::Pub<m::Alias>>::INHERENT_ASSOC_CONST_GENERIC_SELF; //~ ERROR type `m::Priv` is private
116+
<m::Pub<m::Alias>>::static_method_generic_self; //~ ERROR type `m::Priv` is private
117+
use m::TraitWithTyParam2;
118+
u8::pub_method; //~ ERROR type `m::Priv` is private
119+
120+
adjust::S1.method_s3(); //~ ERROR type `adjust::S2` is private
121+
66122
m::m!();
67123

68124
m::leak_anon1(); //~ ERROR trait `m::Trait` is private

src/test/compile-fail/private-type-in-interface.rs

+4
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ extern crate private_inferred_type as ext;
1717
mod m {
1818
struct Priv;
1919
pub type Alias = Priv;
20+
21+
pub trait Trait { type X; }
22+
impl Trait for Priv { type X = u8; }
2023
}
2124

2225
fn f(_: m::Alias) {} //~ ERROR type `m::Priv` is private
@@ -28,6 +31,7 @@ trait Tr1 {}
2831
impl m::Alias {} //~ ERROR type `m::Priv` is private
2932
impl Tr1 for ext::Alias {} //~ ERROR type `ext::Priv` is private
3033
//~^ ERROR type `ext::Priv` is private
34+
type A = <m::Alias as m::Trait>::X; //~ ERROR type `m::Priv` is private
3135

3236
trait Tr2<T> {}
3337
impl<T> Tr2<T> for u8 {}

0 commit comments

Comments
 (0)