Skip to content

Commit 31e8f24

Browse files
committed
auto merge of rust-lang#13346 : ben0x539/rust/priv-field-in, r=alexcrichton
In the error message for when a private field is used, include the name of the struct, or if it's a struct-like enum variant, the names of the variant and the enum. This fixes rust-lang#13341.
2 parents d73bd64 + d4b73a7 commit 31e8f24

10 files changed

+135
-38
lines changed

src/librustc/middle/privacy.rs

+30-8
Original file line numberDiff line numberDiff line change
@@ -576,15 +576,37 @@ impl<'a> PrivacyVisitor<'a> {
576576
}
577577
UnnamedField(idx) => fields.get(idx)
578578
};
579-
if field.vis == ast::Public { return }
580-
if !is_local(field.id) || !self.private_accessible(field.id.node) {
581-
let msg = match name {
582-
NamedField(name) => format!("field `{}` is private",
583-
token::get_ident(name)),
584-
UnnamedField(idx) => format!("field \\#{} is private", idx + 1),
585-
};
586-
self.tcx.sess.span_err(span, msg);
579+
if field.vis == ast::Public ||
580+
(is_local(field.id) && self.private_accessible(field.id.node)) {
581+
return
587582
}
583+
584+
let struct_type = ty::lookup_item_type(self.tcx, id).ty;
585+
let struct_desc = match ty::get(struct_type).sty {
586+
ty::ty_struct(_, _) => format!("struct `{}`", ty::item_path_str(self.tcx, id)),
587+
ty::ty_bare_fn(ty::BareFnTy { sig: ty::FnSig { output, .. }, .. }) => {
588+
// Struct `id` is really a struct variant of an enum,
589+
// and we're really looking at the variant's constructor
590+
// function. So get the return type for a detailed error
591+
// message.
592+
let enum_id = match ty::get(output).sty {
593+
ty::ty_enum(id, _) => id,
594+
_ => self.tcx.sess.span_bug(span, "enum variant doesn't \
595+
belong to an enum")
596+
};
597+
format!("variant `{}` of enum `{}`",
598+
ty::with_path(self.tcx, id, |mut p| p.last().unwrap()),
599+
ty::item_path_str(self.tcx, enum_id))
600+
}
601+
_ => self.tcx.sess.span_bug(span, "can't find struct for field")
602+
};
603+
let msg = match name {
604+
NamedField(name) => format!("field `{}` of {} is private",
605+
token::get_ident(name), struct_desc),
606+
UnnamedField(idx) => format!("field \\#{} of {} is private",
607+
idx + 1, struct_desc),
608+
};
609+
self.tcx.sess.span_err(span, msg);
588610
}
589611

590612
// Given the ID of a method, checks to ensure it's in scope.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
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+
#![feature(struct_variant)]
12+
13+
pub enum Foo {
14+
Bar {
15+
baz: int
16+
}
17+
}

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

+8-4
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,15 @@ mod my_mod {
2424

2525
fn main() {
2626
let my_struct = my_mod::MyStruct();
27-
let _woohoo = (&my_struct).priv_field; //~ ERROR field `priv_field` is private
28-
let _woohoo = (~my_struct).priv_field; //~ ERROR field `priv_field` is private
29-
let _woohoo = (@my_struct).priv_field; //~ ERROR field `priv_field` is private
27+
let _woohoo = (&my_struct).priv_field;
28+
//~^ ERROR field `priv_field` of struct `my_mod::MyStruct` is private
29+
let _woohoo = (~my_struct).priv_field;
30+
//~^ ERROR field `priv_field` of struct `my_mod::MyStruct` is private
31+
let _woohoo = (@my_struct).priv_field;
32+
//~^ ERROR field `priv_field` of struct `my_mod::MyStruct` is private
3033
(&my_struct).happyfun(); //~ ERROR method `happyfun` is private
3134
(~my_struct).happyfun(); //~ ERROR method `happyfun` is private
3235
(@my_struct).happyfun(); //~ ERROR method `happyfun` is private
33-
let nope = my_struct.priv_field; //~ ERROR field `priv_field` is private
36+
let nope = my_struct.priv_field;
37+
//~^ ERROR field `priv_field` of struct `my_mod::MyStruct` is private
3438
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
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:privacy-struct-variant.rs
12+
13+
#![feature(struct_variant)]
14+
15+
extern crate other = "privacy-struct-variant";
16+
17+
mod a {
18+
pub enum Foo {
19+
Bar {
20+
baz: int
21+
}
22+
}
23+
24+
fn test() {
25+
let foo = Bar { baz: 42 };
26+
27+
let Bar { baz: _ } = foo;
28+
match foo { Bar { baz: _ } => {} }
29+
}
30+
}
31+
32+
fn main() {
33+
let foo = a::Bar { baz: 42 };
34+
//~^ ERROR: field `baz` of variant `Bar` of enum `a::Foo` is private
35+
36+
let a::Bar { baz: _ } = foo;
37+
//~^ ERROR: field `baz` of variant `Bar` of enum `a::Foo` is private
38+
match foo { a::Bar { baz: _ } => {} }
39+
//~^ ERROR: field `baz` of variant `Bar` of enum `a::Foo` is private
40+
//
41+
let foo = other::Bar { baz: 42 };
42+
//~^ ERROR: field `baz` of variant `Bar` of enum `privacy-struct-variant::Foo` is private
43+
44+
let other::Bar { baz: _ } = foo;
45+
//~^ ERROR: field `baz` of variant `Bar` of enum `privacy-struct-variant::Foo` is private
46+
match foo { other::Bar { baz: _ } => {} }
47+
//~^ ERROR: field `baz` of variant `Bar` of enum `privacy-struct-variant::Foo` is private
48+
}

src/test/compile-fail/privacy5.rs

+23-18
Original file line numberDiff line numberDiff line change
@@ -64,25 +64,25 @@ fn this_crate() {
6464
let c = a::C(2, 3); //~ ERROR: cannot invoke tuple struct constructor
6565
let d = a::D(4);
6666

67-
let a::A(()) = a; //~ ERROR: field #1 is private
67+
let a::A(()) = a; //~ ERROR: field #1 of struct `a::A` is private
6868
let a::A(_) = a;
69-
match a { a::A(()) => {} } //~ ERROR: field #1 is private
69+
match a { a::A(()) => {} } //~ ERROR: field #1 of struct `a::A` is private
7070
match a { a::A(_) => {} }
7171

7272
let a::B(_) = b;
73-
let a::B(_b) = b; //~ ERROR: field #1 is private
73+
let a::B(_b) = b; //~ ERROR: field #1 of struct `a::B` is private
7474
match b { a::B(_) => {} }
75-
match b { a::B(_b) => {} } //~ ERROR: field #1 is private
76-
match b { a::B(1) => {} a::B(_) => {} } //~ ERROR: field #1 is private
75+
match b { a::B(_b) => {} } //~ ERROR: field #1 of struct `a::B` is private
76+
match b { a::B(1) => {} a::B(_) => {} } //~ ERROR: field #1 of struct `a::B` is private
7777

7878
let a::C(_, _) = c;
7979
let a::C(_a, _) = c;
80-
let a::C(_, _b) = c; //~ ERROR: field #2 is private
81-
let a::C(_a, _b) = c; //~ ERROR: field #2 is private
80+
let a::C(_, _b) = c; //~ ERROR: field #2 of struct `a::C` is private
81+
let a::C(_a, _b) = c; //~ ERROR: field #2 of struct `a::C` is private
8282
match c { a::C(_, _) => {} }
8383
match c { a::C(_a, _) => {} }
84-
match c { a::C(_, _b) => {} } //~ ERROR: field #2 is private
85-
match c { a::C(_a, _b) => {} } //~ ERROR: field #2 is private
84+
match c { a::C(_, _b) => {} } //~ ERROR: field #2 of struct `a::C` is private
85+
match c { a::C(_a, _b) => {} } //~ ERROR: field #2 of struct `a::C` is private
8686

8787
let a::D(_) = d;
8888
let a::D(_d) = d;
@@ -102,25 +102,30 @@ fn xcrate() {
102102
let c = other::C(2, 3); //~ ERROR: cannot invoke tuple struct constructor
103103
let d = other::D(4);
104104

105-
let other::A(()) = a; //~ ERROR: field #1 is private
105+
let other::A(()) = a; //~ ERROR: field #1 of struct `privacy-tuple-struct::A` is private
106106
let other::A(_) = a;
107-
match a { other::A(()) => {} } //~ ERROR: field #1 is private
107+
match a { other::A(()) => {} }
108+
//~^ ERROR: field #1 of struct `privacy-tuple-struct::A` is private
108109
match a { other::A(_) => {} }
109110

110111
let other::B(_) = b;
111-
let other::B(_b) = b; //~ ERROR: field #1 is private
112+
let other::B(_b) = b; //~ ERROR: field #1 of struct `privacy-tuple-struct::B` is private
112113
match b { other::B(_) => {} }
113-
match b { other::B(_b) => {} } //~ ERROR: field #1 is private
114-
match b { other::B(1) => {} other::B(_) => {} } //~ ERROR: field #1 is private
114+
match b { other::B(_b) => {} }
115+
//~^ ERROR: field #1 of struct `privacy-tuple-struct::B` is private
116+
match b { other::B(1) => {} other::B(_) => {} }
117+
//~^ ERROR: field #1 of struct `privacy-tuple-struct::B` is private
115118

116119
let other::C(_, _) = c;
117120
let other::C(_a, _) = c;
118-
let other::C(_, _b) = c; //~ ERROR: field #2 is private
119-
let other::C(_a, _b) = c; //~ ERROR: field #2 is private
121+
let other::C(_, _b) = c; //~ ERROR: field #2 of struct `privacy-tuple-struct::C` is private
122+
let other::C(_a, _b) = c; //~ ERROR: field #2 of struct `privacy-tuple-struct::C` is private
120123
match c { other::C(_, _) => {} }
121124
match c { other::C(_a, _) => {} }
122-
match c { other::C(_, _b) => {} } //~ ERROR: field #2 is private
123-
match c { other::C(_a, _b) => {} } //~ ERROR: field #2 is private
125+
match c { other::C(_, _b) => {} }
126+
//~^ ERROR: field #2 of struct `privacy-tuple-struct::C` is private
127+
match c { other::C(_a, _b) => {} }
128+
//~^ ERROR: field #2 of struct `privacy-tuple-struct::C` is private
124129

125130
let other::D(_) = d;
126131
let other::D(_d) = d;

src/test/compile-fail/private-struct-field-cross-crate.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,6 @@ use cci_class::kitties::cat;
1414

1515
fn main() {
1616
let nyan : cat = cat(52u, 99);
17-
assert!((nyan.meows == 52u)); //~ ERROR field `meows` is private
17+
assert!((nyan.meows == 52u));
18+
//~^ ERROR field `meows` of struct `cci_class::kitties::cat` is private
1819
}

src/test/compile-fail/private-struct-field-ctor.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,5 @@ mod a {
1515
}
1616

1717
fn main() {
18-
let s = a::Foo { x: 1 }; //~ ERROR field `x` is private
18+
let s = a::Foo { x: 1 }; //~ ERROR field `x` of struct `a::Foo` is private
1919
}

src/test/compile-fail/private-struct-field-pattern.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,6 @@ mod a {
2222

2323
fn main() {
2424
match a::make() {
25-
Foo { x: _ } => {} //~ ERROR field `x` is private
25+
Foo { x: _ } => {} //~ ERROR field `x` of struct `a::Foo` is private
2626
}
2727
}

src/test/compile-fail/private-struct-field.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,5 @@ mod cat {
2020

2121
fn main() {
2222
let nyan = cat::new_cat();
23-
assert!(nyan.meows == 52); //~ ERROR field `meows` is private
23+
assert!(nyan.meows == 52); //~ ERROR field `meows` of struct `cat::Cat` is private
2424
}

src/test/compile-fail/struct-field-privacy.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -32,16 +32,16 @@ fn test(a: A, b: inner::A, c: inner::B, d: xc::A, e: xc::B) {
3232
//~^^ ERROR: struct `A` is private
3333

3434
a.a;
35-
b.a; //~ ERROR: field `a` is private
35+
b.a; //~ ERROR: field `a` of struct `inner::A` is private
3636
b.b;
3737
c.a;
38-
c.b; //~ ERROR: field `b` is private
38+
c.b; //~ ERROR: field `b` of struct `inner::B` is private
3939

40-
d.a; //~ ERROR: field `a` is private
40+
d.a; //~ ERROR: field `a` of struct `struct-field-privacy::A` is private
4141
d.b;
4242

4343
e.a;
44-
e.b; //~ ERROR: field `b` is private
44+
e.b; //~ ERROR: field `b` of struct `struct-field-privacy::B` is private
4545
}
4646

4747
fn main() {}

0 commit comments

Comments
 (0)