diff --git a/src/librustc/middle/privacy.rs b/src/librustc/middle/privacy.rs index 9d9faee36450a..ee514ba5f2438 100644 --- a/src/librustc/middle/privacy.rs +++ b/src/librustc/middle/privacy.rs @@ -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. diff --git a/src/test/auxiliary/privacy-struct-variant.rs b/src/test/auxiliary/privacy-struct-variant.rs new file mode 100644 index 0000000000000..af2e3328d3a1f --- /dev/null +++ b/src/test/auxiliary/privacy-struct-variant.rs @@ -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 or the MIT license +// , 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 + } +} diff --git a/src/test/compile-fail/issue-3763.rs b/src/test/compile-fail/issue-3763.rs index 736ac55aef545..8eed8aa86441a 100644 --- a/src/test/compile-fail/issue-3763.rs +++ b/src/test/compile-fail/issue-3763.rs @@ -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 } diff --git a/src/test/compile-fail/privacy-struct-variant.rs b/src/test/compile-fail/privacy-struct-variant.rs new file mode 100644 index 0000000000000..d6fab326ba16f --- /dev/null +++ b/src/test/compile-fail/privacy-struct-variant.rs @@ -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 or the MIT license +// , 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 +} diff --git a/src/test/compile-fail/privacy5.rs b/src/test/compile-fail/privacy5.rs index c057236265e94..2683022c4c823 100644 --- a/src/test/compile-fail/privacy5.rs +++ b/src/test/compile-fail/privacy5.rs @@ -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; @@ -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; diff --git a/src/test/compile-fail/private-struct-field-cross-crate.rs b/src/test/compile-fail/private-struct-field-cross-crate.rs index 0993ac9a64ad3..45c4b2b7ae1b0 100644 --- a/src/test/compile-fail/private-struct-field-cross-crate.rs +++ b/src/test/compile-fail/private-struct-field-cross-crate.rs @@ -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 } diff --git a/src/test/compile-fail/private-struct-field-ctor.rs b/src/test/compile-fail/private-struct-field-ctor.rs index a5cee47d4e39a..ae19c22149669 100644 --- a/src/test/compile-fail/private-struct-field-ctor.rs +++ b/src/test/compile-fail/private-struct-field-ctor.rs @@ -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 } diff --git a/src/test/compile-fail/private-struct-field-pattern.rs b/src/test/compile-fail/private-struct-field-pattern.rs index ee1303b99dd52..991457ef1ce7c 100644 --- a/src/test/compile-fail/private-struct-field-pattern.rs +++ b/src/test/compile-fail/private-struct-field-pattern.rs @@ -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 } } diff --git a/src/test/compile-fail/private-struct-field.rs b/src/test/compile-fail/private-struct-field.rs index 52e979342f57d..3f6fa573cc0b5 100644 --- a/src/test/compile-fail/private-struct-field.rs +++ b/src/test/compile-fail/private-struct-field.rs @@ -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 } diff --git a/src/test/compile-fail/struct-field-privacy.rs b/src/test/compile-fail/struct-field-privacy.rs index b6ae7235bb3de..82ba9a02a304a 100644 --- a/src/test/compile-fail/struct-field-privacy.rs +++ b/src/test/compile-fail/struct-field-privacy.rs @@ -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() {}