Skip to content

Commit

Permalink
auto merge of rust-lang#13346 : ben0x539/rust/priv-field-in, r=alexcr…
Browse files Browse the repository at this point in the history
…ichton

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.
  • Loading branch information
bors committed Apr 6, 2014
2 parents d73bd64 + d4b73a7 commit 31e8f24
Show file tree
Hide file tree
Showing 10 changed files with 135 additions and 38 deletions.
38 changes: 30 additions & 8 deletions src/librustc/middle/privacy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -576,15 +576,37 @@ impl<'a> PrivacyVisitor<'a> {
}
UnnamedField(idx) => fields.get(idx)
};
if field.vis == ast::Public { return }
if !is_local(field.id) || !self.private_accessible(field.id.node) {
let msg = match name {
NamedField(name) => format!("field `{}` is private",
token::get_ident(name)),
UnnamedField(idx) => format!("field \\#{} is private", idx + 1),
};
self.tcx.sess.span_err(span, msg);
if field.vis == ast::Public ||
(is_local(field.id) && self.private_accessible(field.id.node)) {
return
}

let struct_type = ty::lookup_item_type(self.tcx, id).ty;
let struct_desc = match ty::get(struct_type).sty {
ty::ty_struct(_, _) => format!("struct `{}`", ty::item_path_str(self.tcx, id)),
ty::ty_bare_fn(ty::BareFnTy { sig: ty::FnSig { output, .. }, .. }) => {
// Struct `id` is really a struct variant of an enum,
// and we're really looking at the variant's constructor
// function. So get the return type for a detailed error
// message.
let enum_id = match ty::get(output).sty {
ty::ty_enum(id, _) => id,
_ => self.tcx.sess.span_bug(span, "enum variant doesn't \
belong to an enum")
};
format!("variant `{}` of enum `{}`",
ty::with_path(self.tcx, id, |mut p| p.last().unwrap()),
ty::item_path_str(self.tcx, enum_id))
}
_ => self.tcx.sess.span_bug(span, "can't find struct for field")
};
let msg = match name {
NamedField(name) => format!("field `{}` of {} is private",
token::get_ident(name), struct_desc),
UnnamedField(idx) => format!("field \\#{} of {} is private",
idx + 1, struct_desc),
};
self.tcx.sess.span_err(span, msg);
}

// Given the ID of a method, checks to ensure it's in scope.
Expand Down
17 changes: 17 additions & 0 deletions src/test/auxiliary/privacy-struct-variant.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![feature(struct_variant)]

pub enum Foo {
Bar {
baz: int
}
}
12 changes: 8 additions & 4 deletions src/test/compile-fail/issue-3763.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,15 @@ mod my_mod {

fn main() {
let my_struct = my_mod::MyStruct();
let _woohoo = (&my_struct).priv_field; //~ ERROR field `priv_field` is private
let _woohoo = (~my_struct).priv_field; //~ ERROR field `priv_field` is private
let _woohoo = (@my_struct).priv_field; //~ ERROR field `priv_field` is private
let _woohoo = (&my_struct).priv_field;
//~^ ERROR field `priv_field` of struct `my_mod::MyStruct` is private
let _woohoo = (~my_struct).priv_field;
//~^ ERROR field `priv_field` of struct `my_mod::MyStruct` is private
let _woohoo = (@my_struct).priv_field;
//~^ ERROR field `priv_field` of struct `my_mod::MyStruct` is private
(&my_struct).happyfun(); //~ ERROR method `happyfun` is private
(~my_struct).happyfun(); //~ ERROR method `happyfun` is private
(@my_struct).happyfun(); //~ ERROR method `happyfun` is private
let nope = my_struct.priv_field; //~ ERROR field `priv_field` is private
let nope = my_struct.priv_field;
//~^ ERROR field `priv_field` of struct `my_mod::MyStruct` is private
}
48 changes: 48 additions & 0 deletions src/test/compile-fail/privacy-struct-variant.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// aux-build:privacy-struct-variant.rs

#![feature(struct_variant)]

extern crate other = "privacy-struct-variant";

mod a {
pub enum Foo {
Bar {
baz: int
}
}

fn test() {
let foo = Bar { baz: 42 };

let Bar { baz: _ } = foo;
match foo { Bar { baz: _ } => {} }
}
}

fn main() {
let foo = a::Bar { baz: 42 };
//~^ ERROR: field `baz` of variant `Bar` of enum `a::Foo` is private

let a::Bar { baz: _ } = foo;
//~^ ERROR: field `baz` of variant `Bar` of enum `a::Foo` is private
match foo { a::Bar { baz: _ } => {} }
//~^ ERROR: field `baz` of variant `Bar` of enum `a::Foo` is private
//
let foo = other::Bar { baz: 42 };
//~^ ERROR: field `baz` of variant `Bar` of enum `privacy-struct-variant::Foo` is private

let other::Bar { baz: _ } = foo;
//~^ ERROR: field `baz` of variant `Bar` of enum `privacy-struct-variant::Foo` is private
match foo { other::Bar { baz: _ } => {} }
//~^ ERROR: field `baz` of variant `Bar` of enum `privacy-struct-variant::Foo` is private
}
41 changes: 23 additions & 18 deletions src/test/compile-fail/privacy5.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,25 +64,25 @@ fn this_crate() {
let c = a::C(2, 3); //~ ERROR: cannot invoke tuple struct constructor
let d = a::D(4);

let a::A(()) = a; //~ ERROR: field #1 is private
let a::A(()) = a; //~ ERROR: field #1 of struct `a::A` is private
let a::A(_) = a;
match a { a::A(()) => {} } //~ ERROR: field #1 is private
match a { a::A(()) => {} } //~ ERROR: field #1 of struct `a::A` is private
match a { a::A(_) => {} }

let a::B(_) = b;
let a::B(_b) = b; //~ ERROR: field #1 is private
let a::B(_b) = b; //~ ERROR: field #1 of struct `a::B` is private
match b { a::B(_) => {} }
match b { a::B(_b) => {} } //~ ERROR: field #1 is private
match b { a::B(1) => {} a::B(_) => {} } //~ ERROR: field #1 is private
match b { a::B(_b) => {} } //~ ERROR: field #1 of struct `a::B` is private
match b { a::B(1) => {} a::B(_) => {} } //~ ERROR: field #1 of struct `a::B` is private

let a::C(_, _) = c;
let a::C(_a, _) = c;
let a::C(_, _b) = c; //~ ERROR: field #2 is private
let a::C(_a, _b) = c; //~ ERROR: field #2 is private
let a::C(_, _b) = c; //~ ERROR: field #2 of struct `a::C` is private
let a::C(_a, _b) = c; //~ ERROR: field #2 of struct `a::C` is private
match c { a::C(_, _) => {} }
match c { a::C(_a, _) => {} }
match c { a::C(_, _b) => {} } //~ ERROR: field #2 is private
match c { a::C(_a, _b) => {} } //~ ERROR: field #2 is private
match c { a::C(_, _b) => {} } //~ ERROR: field #2 of struct `a::C` is private
match c { a::C(_a, _b) => {} } //~ ERROR: field #2 of struct `a::C` is private

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

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

let other::B(_) = b;
let other::B(_b) = b; //~ ERROR: field #1 is private
let other::B(_b) = b; //~ ERROR: field #1 of struct `privacy-tuple-struct::B` is private
match b { other::B(_) => {} }
match b { other::B(_b) => {} } //~ ERROR: field #1 is private
match b { other::B(1) => {} other::B(_) => {} } //~ ERROR: field #1 is private
match b { other::B(_b) => {} }
//~^ ERROR: field #1 of struct `privacy-tuple-struct::B` is private
match b { other::B(1) => {} other::B(_) => {} }
//~^ ERROR: field #1 of struct `privacy-tuple-struct::B` is private

let other::C(_, _) = c;
let other::C(_a, _) = c;
let other::C(_, _b) = c; //~ ERROR: field #2 is private
let other::C(_a, _b) = c; //~ ERROR: field #2 is private
let other::C(_, _b) = c; //~ ERROR: field #2 of struct `privacy-tuple-struct::C` is private
let other::C(_a, _b) = c; //~ ERROR: field #2 of struct `privacy-tuple-struct::C` is private
match c { other::C(_, _) => {} }
match c { other::C(_a, _) => {} }
match c { other::C(_, _b) => {} } //~ ERROR: field #2 is private
match c { other::C(_a, _b) => {} } //~ ERROR: field #2 is private
match c { other::C(_, _b) => {} }
//~^ ERROR: field #2 of struct `privacy-tuple-struct::C` is private
match c { other::C(_a, _b) => {} }
//~^ ERROR: field #2 of struct `privacy-tuple-struct::C` is private

let other::D(_) = d;
let other::D(_d) = d;
Expand Down
3 changes: 2 additions & 1 deletion src/test/compile-fail/private-struct-field-cross-crate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,6 @@ use cci_class::kitties::cat;

fn main() {
let nyan : cat = cat(52u, 99);
assert!((nyan.meows == 52u)); //~ ERROR field `meows` is private
assert!((nyan.meows == 52u));
//~^ ERROR field `meows` of struct `cci_class::kitties::cat` is private
}
2 changes: 1 addition & 1 deletion src/test/compile-fail/private-struct-field-ctor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,5 @@ mod a {
}

fn main() {
let s = a::Foo { x: 1 }; //~ ERROR field `x` is private
let s = a::Foo { x: 1 }; //~ ERROR field `x` of struct `a::Foo` is private
}
2 changes: 1 addition & 1 deletion src/test/compile-fail/private-struct-field-pattern.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,6 @@ mod a {

fn main() {
match a::make() {
Foo { x: _ } => {} //~ ERROR field `x` is private
Foo { x: _ } => {} //~ ERROR field `x` of struct `a::Foo` is private
}
}
2 changes: 1 addition & 1 deletion src/test/compile-fail/private-struct-field.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,5 @@ mod cat {

fn main() {
let nyan = cat::new_cat();
assert!(nyan.meows == 52); //~ ERROR field `meows` is private
assert!(nyan.meows == 52); //~ ERROR field `meows` of struct `cat::Cat` is private
}
8 changes: 4 additions & 4 deletions src/test/compile-fail/struct-field-privacy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,16 @@ fn test(a: A, b: inner::A, c: inner::B, d: xc::A, e: xc::B) {
//~^^ ERROR: struct `A` is private

a.a;
b.a; //~ ERROR: field `a` is private
b.a; //~ ERROR: field `a` of struct `inner::A` is private
b.b;
c.a;
c.b; //~ ERROR: field `b` is private
c.b; //~ ERROR: field `b` of struct `inner::B` is private

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

e.a;
e.b; //~ ERROR: field `b` is private
e.b; //~ ERROR: field `b` of struct `struct-field-privacy::B` is private
}

fn main() {}

0 comments on commit 31e8f24

Please sign in to comment.