auto merge of #13237 : alexcrichton/rust/private-tuple-structs, r=brson

This is the final commit need to implement [RFC #4](https://github.com/rust-lang/rfcs/blob/master/active/0004-private-fields.md), it makes all tuple struct fields private by default, overridable with the `pub` keyword.

I'll note one divergence from the original RFC which is outlined in the first commit.
This commit is contained in:
bors 2014-04-03 18:41:45 -07:00
commit c2e457686b
31 changed files with 326 additions and 79 deletions

View File

@ -28,7 +28,7 @@ use distributions::{ziggurat, ziggurat_tables, Sample, IndependentSample};
/// Generate Normal Random
/// Samples*](http://www.doornik.com/research/ziggurat.pdf). Nuffield
/// College, Oxford
pub struct Exp1(f64);
pub struct Exp1(pub f64);
// This could be done via `-rng.gen::<f64>().ln()` but that is slower.
impl Rand for Exp1 {

View File

@ -27,7 +27,7 @@ use distributions::{ziggurat, ziggurat_tables, Sample, IndependentSample};
/// Generate Normal Random
/// Samples*](http://www.doornik.com/research/ziggurat.pdf). Nuffield
/// College, Oxford
pub struct StandardNormal(f64);
pub struct StandardNormal(pub f64);
impl Rand for StandardNormal {
fn rand<R:Rng>(rng: &mut R) -> StandardNormal {

View File

@ -666,7 +666,7 @@ pub fn random<T: Rand>() -> T {
/// let Open01(val) = random::<Open01<f32>>();
/// println!("f32 from (0,1): {}", val);
/// ```
pub struct Open01<F>(F);
pub struct Open01<F>(pub F);
/// A wrapper for generating floating point numbers uniformly in the
/// closed interval `[0,1]` (including both endpoints).
@ -682,7 +682,7 @@ pub struct Open01<F>(F);
/// let Closed01(val) = random::<Closed01<f32>>();
/// println!("f32 from [0,1]: {}", val);
/// ```
pub struct Closed01<F>(F);
pub struct Closed01<F>(pub F);
#[cfg(test)]
mod test {

View File

@ -290,3 +290,11 @@ pub fn get_exported_macros(cstore: &cstore::CStore,
let cdata = cstore.get_crate_data(crate_num);
decoder::get_exported_macros(cdata)
}
pub fn get_tuple_struct_definition_if_ctor(cstore: &cstore::CStore,
def_id: ast::DefId)
-> Option<ast::DefId>
{
let cdata = cstore.get_crate_data(def_id.krate);
decoder::get_tuple_struct_definition_if_ctor(cdata, def_id.node)
}

View File

@ -929,23 +929,26 @@ pub fn get_static_methods_if_impl(intr: Rc<IdentInterner>,
/// If node_id is the constructor of a tuple struct, retrieve the NodeId of
/// the actual type definition, otherwise, return None
pub fn get_tuple_struct_definition_if_ctor(cdata: Cmd,
node_id: ast::NodeId) -> Option<ast::NodeId> {
node_id: ast::NodeId)
-> Option<ast::DefId>
{
let item = lookup_item(node_id, cdata.data());
let mut ret = None;
reader::tagged_docs(item, tag_items_data_item_is_tuple_struct_ctor, |_| {
ret = Some(item_reqd_and_translated_parent_item(cdata.cnum, item));
false
});
ret.map(|x| x.node)
ret
}
pub fn get_item_attrs(cdata: Cmd,
node_id: ast::NodeId,
orig_node_id: ast::NodeId,
f: |Vec<@ast::MetaItem> |) {
// The attributes for a tuple struct are attached to the definition, not the ctor;
// we assume that someone passing in a tuple struct ctor is actually wanting to
// look at the definition
let node_id = get_tuple_struct_definition_if_ctor(cdata, node_id).unwrap_or(node_id);
let node_id = get_tuple_struct_definition_if_ctor(cdata, orig_node_id);
let node_id = node_id.map(|x| x.node).unwrap_or(orig_node_id);
let item = lookup_item(node_id, cdata.data());
reader::tagged_docs(item, tag_attributes, |attributes| {
reader::tagged_docs(attributes, tag_attribute, |attribute| {

View File

@ -56,11 +56,11 @@ pub struct Edge<E> {
}
#[deriving(Eq)]
pub struct NodeIndex(uint);
pub struct NodeIndex(pub uint);
pub static InvalidNodeIndex: NodeIndex = NodeIndex(uint::MAX);
#[deriving(Eq)]
pub struct EdgeIndex(uint);
pub struct EdgeIndex(pub uint);
pub static InvalidEdgeIndex: EdgeIndex = EdgeIndex(uint::MAX);
// Use a private field here to guarantee no more instances are created:

View File

@ -14,6 +14,7 @@
use std::mem::replace;
use metadata::csearch;
use middle::lint;
use middle::resolve;
use middle::ty;
@ -358,6 +359,12 @@ enum PrivacyResult {
DisallowedBy(ast::NodeId),
}
enum FieldName {
UnnamedField(uint), // index
// FIXME #6993: change type (and name) from Ident to Name
NamedField(ast::Ident),
}
impl<'a> PrivacyVisitor<'a> {
// used when debugging
fn nodestr(&self, id: ast::NodeId) -> ~str {
@ -560,18 +567,23 @@ impl<'a> PrivacyVisitor<'a> {
}
// Checks that a field is in scope.
// FIXME #6993: change type (and name) from Ident to Name
fn check_field(&mut self, span: Span, id: ast::DefId, ident: ast::Ident) {
for field in ty::lookup_struct_fields(self.tcx, id).iter() {
if field.name != ident.name { continue; }
if field.vis == ast::Public { break }
if !is_local(field.id) ||
!self.private_accessible(field.id.node) {
self.tcx.sess.span_err(span,
format!("field `{}` is private",
token::get_ident(ident)))
fn check_field(&mut self, span: Span, id: ast::DefId,
name: FieldName) {
let fields = ty::lookup_struct_fields(self.tcx, id);
let field = match name {
NamedField(ident) => {
fields.iter().find(|f| f.name == ident.name).unwrap()
}
break;
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);
}
}
@ -634,10 +646,11 @@ impl<'a> PrivacyVisitor<'a> {
_ => {},
}
}
// If an import is not used in either namespace, we still want to check
// that it could be legal. Therefore we check in both namespaces and only
// report an error if both would be illegal. We only report one error,
// even if it is illegal to import from both namespaces.
// If an import is not used in either namespace, we still
// want to check that it could be legal. Therefore we check
// in both namespaces and only report an error if both would
// be illegal. We only report one error, even if it is
// illegal to import from both namespaces.
match (value_priv, check_value, type_priv, check_type) {
(Some(p), resolve::Unused, None, _) |
(None, _, Some(p), resolve::Unused) => {
@ -701,7 +714,8 @@ impl<'a> PrivacyVisitor<'a> {
// is whether the trait itself is accessible or not.
MethodParam(MethodParam { trait_id: trait_id, .. }) |
MethodObject(MethodObject { trait_id: trait_id, .. }) => {
self.report_error(self.ensure_public(span, trait_id, None, "source trait"));
self.report_error(self.ensure_public(span, trait_id, None,
"source trait"));
}
}
}
@ -726,7 +740,7 @@ impl<'a> Visitor<()> for PrivacyVisitor<'a> {
match ty::get(ty::expr_ty_adjusted(self.tcx, base,
&*self.method_map.borrow())).sty {
ty::ty_struct(id, _) => {
self.check_field(expr.span, id, ident);
self.check_field(expr.span, id, NamedField(ident));
}
_ => {}
}
@ -749,7 +763,8 @@ impl<'a> Visitor<()> for PrivacyVisitor<'a> {
match ty::get(ty::expr_ty(self.tcx, expr)).sty {
ty::ty_struct(id, _) => {
for field in (*fields).iter() {
self.check_field(expr.span, id, field.ident.node);
self.check_field(expr.span, id,
NamedField(field.ident.node));
}
}
ty::ty_enum(_, _) => {
@ -757,7 +772,7 @@ impl<'a> Visitor<()> for PrivacyVisitor<'a> {
ast::DefVariant(_, variant_id, _) => {
for field in fields.iter() {
self.check_field(expr.span, variant_id,
field.ident.node);
NamedField(field.ident.node));
}
}
_ => self.tcx.sess.span_bug(expr.span,
@ -772,6 +787,46 @@ impl<'a> Visitor<()> for PrivacyVisitor<'a> {
struct type?!"),
}
}
ast::ExprPath(..) => {
let guard = |did: ast::DefId| {
let fields = ty::lookup_struct_fields(self.tcx, did);
let any_priv = fields.iter().any(|f| {
f.vis != ast::Public && (
!is_local(f.id) ||
!self.private_accessible(f.id.node))
});
if any_priv {
self.tcx.sess.span_err(expr.span,
"cannot invoke tuple struct constructor \
with private fields");
}
};
match self.tcx.def_map.borrow().find(&expr.id) {
Some(&ast::DefStruct(did)) => {
guard(if is_local(did) {
local_def(self.tcx.map.get_parent(did.node))
} else {
// "tuple structs" with zero fields (such as
// `pub struct Foo;`) don't have a ctor_id, hence
// the unwrap_or to the same struct id.
let maybe_did =
csearch::get_tuple_struct_definition_if_ctor(
&self.tcx.sess.cstore, did);
maybe_did.unwrap_or(did)
})
}
// Tuple struct constructors across crates are identified as
// DefFn types, so we explicitly handle that case here.
Some(&ast::DefFn(did, _)) if !is_local(did) => {
match csearch::get_tuple_struct_definition_if_ctor(
&self.tcx.sess.cstore, did) {
Some(did) => guard(did),
None => {}
}
}
_ => {}
}
}
_ => {}
}
@ -821,7 +876,8 @@ impl<'a> Visitor<()> for PrivacyVisitor<'a> {
match ty::get(ty::pat_ty(self.tcx, pattern)).sty {
ty::ty_struct(id, _) => {
for field in fields.iter() {
self.check_field(pattern.span, id, field.ident);
self.check_field(pattern.span, id,
NamedField(field.ident));
}
}
ty::ty_enum(_, _) => {
@ -829,7 +885,7 @@ impl<'a> Visitor<()> for PrivacyVisitor<'a> {
Some(&ast::DefVariant(_, variant_id, _)) => {
for field in fields.iter() {
self.check_field(pattern.span, variant_id,
field.ident);
NamedField(field.ident));
}
}
_ => self.tcx.sess.span_bug(pattern.span,
@ -844,6 +900,27 @@ impl<'a> Visitor<()> for PrivacyVisitor<'a> {
struct type?!"),
}
}
// Patterns which bind no fields are allowable (the path is check
// elsewhere).
ast::PatEnum(_, Some(ref fields)) => {
match ty::get(ty::pat_ty(self.tcx, pattern)).sty {
ty::ty_struct(id, _) => {
for (i, field) in fields.iter().enumerate() {
match field.node {
ast::PatWild(..) => continue,
_ => {}
}
self.check_field(field.span, id, UnnamedField(i));
}
}
ty::ty_enum(..) => {
// enum fields have no privacy at this time
}
_ => {}
}
}
_ => {}
}

View File

@ -12,7 +12,7 @@ use lib::llvm::{llvm, BasicBlockRef};
use middle::trans::value::{Users, Value};
use std::iter::{Filter, Map};
pub struct BasicBlock(BasicBlockRef);
pub struct BasicBlock(pub BasicBlockRef);
pub type Preds<'a> = Map<'a, Value, BasicBlock, Filter<'a, Value, Users>>;

View File

@ -13,7 +13,7 @@ use middle::trans::basic_block::BasicBlock;
use middle::trans::common::Block;
use std::libc::c_uint;
pub struct Value(ValueRef);
pub struct Value(pub ValueRef);
macro_rules! opt_val ( ($e:expr) => (
unsafe {

View File

@ -866,13 +866,13 @@ impl CLike for BuiltinBound {
}
#[deriving(Clone, Eq, TotalEq, Hash)]
pub struct TyVid(uint);
pub struct TyVid(pub uint);
#[deriving(Clone, Eq, TotalEq, Hash)]
pub struct IntVid(uint);
pub struct IntVid(pub uint);
#[deriving(Clone, Eq, TotalEq, Hash)]
pub struct FloatVid(uint);
pub struct FloatVid(pub uint);
#[deriving(Clone, Eq, TotalEq, Encodable, Decodable, Hash)]
pub struct RegionVid {

View File

@ -84,7 +84,7 @@ use syntax::ast;
// Note: Coerce is not actually a combiner, in that it does not
// conform to the same interface, though it performs a similar
// function.
pub struct Coerce<'f>(CombineFields<'f>);
pub struct Coerce<'f>(pub CombineFields<'f>);
impl<'f> Coerce<'f> {
pub fn get_ref<'a>(&'a self) -> &'a CombineFields<'f> {

View File

@ -28,7 +28,7 @@ use collections::HashMap;
use util::common::{indenter};
use util::ppaux::mt_to_str;
pub struct Glb<'f>(CombineFields<'f>); // "greatest lower bound" (common subtype)
pub struct Glb<'f>(pub CombineFields<'f>); // "greatest lower bound" (common subtype)
impl<'f> Glb<'f> {
pub fn get_ref<'a>(&'a self) -> &'a CombineFields<'f> { let Glb(ref v) = *self; v }

View File

@ -27,7 +27,7 @@ use syntax::ast::{ExternFn, ImpureFn, UnsafeFn};
use syntax::ast::{Onceness, Purity};
use util::ppaux::mt_to_str;
pub struct Lub<'f>(CombineFields<'f>); // least-upper-bound: common supertype
pub struct Lub<'f>(pub CombineFields<'f>); // least-upper-bound: common supertype
impl<'f> Lub<'f> {
pub fn get_ref<'a>(&'a self) -> &'a CombineFields<'f> { let Lub(ref v) = *self; v }

View File

@ -27,7 +27,7 @@ use util::ppaux::bound_region_to_str;
use syntax::ast::{Onceness, Purity};
pub struct Sub<'f>(CombineFields<'f>); // "subtype", "subregion" etc
pub struct Sub<'f>(pub CombineFields<'f>); // "subtype", "subregion" etc
impl<'f> Sub<'f> {
pub fn get_ref<'a>(&'a self) -> &'a CombineFields<'f> { let Sub(ref v) = *self; v }

View File

@ -17,7 +17,7 @@ use std::fmt;
/// Wrapper struct which will emit the HTML-escaped version of the contained
/// string when passed to a format string.
pub struct Escape<'a>(&'a str);
pub struct Escape<'a>(pub &'a str);
impl<'a> fmt::Show for Escape<'a> {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {

View File

@ -28,12 +28,12 @@ use html::render::{cache_key, current_location_key};
/// Helper to render an optional visibility with a space after it (if the
/// visibility is preset)
pub struct VisSpace(Option<ast::Visibility>);
pub struct VisSpace(pub Option<ast::Visibility>);
/// Similarly to VisSpace, this structure is used to render a purity with a
/// space after it.
pub struct PuritySpace(ast::Purity);
pub struct PuritySpace(pub ast::Purity);
/// Wrapper struct for properly emitting a method declaration.
pub struct Method<'a>(&'a clean::SelfTy, &'a clean::FnDecl);
pub struct Method<'a>(pub &'a clean::SelfTy, pub &'a clean::FnDecl);
impl VisSpace {
pub fn get(&self) -> Option<ast::Visibility> {

View File

@ -42,10 +42,10 @@ use html::highlight;
/// A unit struct which has the `fmt::Show` trait implemented. When
/// formatted, this struct will emit the HTML corresponding to the rendered
/// version of the contained markdown string.
pub struct Markdown<'a>(&'a str);
pub struct Markdown<'a>(pub &'a str);
/// A unit struct like `Markdown`, that renders the markdown with a
/// table of contents.
pub struct MarkdownWithToc<'a>(&'a str);
pub struct MarkdownWithToc<'a>(pub &'a str);
static OUTPUT_UNIT: libc::size_t = 64;
static MKDEXT_NO_INTRA_EMPHASIS: libc::c_uint = 1 << 0;

View File

@ -58,7 +58,7 @@ pub struct Task {
}
pub struct GarbageCollector;
pub struct LocalStorage(Option<local_data::Map>);
pub struct LocalStorage(pub Option<local_data::Map>);
/// A handle to a blocked task. Usually this means having the ~Task pointer by
/// ownership, but if the task is killable, a killer can steal it at any time.

View File

@ -14,40 +14,48 @@
#[experimental]
#[simd]
pub struct i8x16(i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8);
pub struct i8x16(pub i8, pub i8, pub i8, pub i8,
pub i8, pub i8, pub i8, pub i8,
pub i8, pub i8, pub i8, pub i8,
pub i8, pub i8, pub i8, pub i8);
#[experimental]
#[simd]
pub struct i16x8(i16, i16, i16, i16, i16, i16, i16, i16);
pub struct i16x8(pub i16, pub i16, pub i16, pub i16,
pub i16, pub i16, pub i16, pub i16);
#[experimental]
#[simd]
pub struct i32x4(i32, i32, i32, i32);
pub struct i32x4(pub i32, pub i32, pub i32, pub i32);
#[experimental]
#[simd]
pub struct i64x2(i64, i64);
pub struct i64x2(pub i64, pub i64);
#[experimental]
#[simd]
pub struct u8x16(u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8);
pub struct u8x16(pub u8, pub u8, pub u8, pub u8,
pub u8, pub u8, pub u8, pub u8,
pub u8, pub u8, pub u8, pub u8,
pub u8, pub u8, pub u8, pub u8);
#[experimental]
#[simd]
pub struct u16x8(u16, u16, u16, u16, u16, u16, u16, u16);
pub struct u16x8(pub u16, pub u16, pub u16, pub u16,
pub u16, pub u16, pub u16, pub u16);
#[experimental]
#[simd]
pub struct u32x4(u32, u32, u32, u32);
pub struct u32x4(pub u32, pub u32, pub u32, pub u32);
#[experimental]
#[simd]
pub struct u64x2(u64, u64);
pub struct u64x2(pub u64, pub u64);
#[experimental]
#[simd]
pub struct f32x4(f32, f32, f32, f32);
pub struct f32x4(pub f32, pub f32, pub f32, pub f32);
#[experimental]
#[simd]
pub struct f64x2(f64, f64);
pub struct f64x2(pub f64, pub f64);

View File

@ -493,10 +493,10 @@ pub enum Expr_ {
ExprVstore(@Expr, ExprVstore),
// First expr is the place; second expr is the value.
ExprBox(@Expr, @Expr),
ExprVec(Vec<@Expr> , Mutability),
ExprCall(@Expr, Vec<@Expr> ),
ExprMethodCall(Ident, Vec<P<Ty>> , Vec<@Expr> ),
ExprTup(Vec<@Expr> ),
ExprVec(Vec<@Expr>, Mutability),
ExprCall(@Expr, Vec<@Expr>),
ExprMethodCall(Ident, Vec<P<Ty>>, Vec<@Expr>),
ExprTup(Vec<@Expr>),
ExprBinary(BinOp, @Expr, @Expr),
ExprUnary(UnOp, @Expr),
ExprLit(@Lit),
@ -508,14 +508,14 @@ pub enum Expr_ {
// Conditionless loop (can be exited with break, cont, or ret)
// FIXME #6993: change to Option<Name>
ExprLoop(P<Block>, Option<Ident>),
ExprMatch(@Expr, Vec<Arm> ),
ExprMatch(@Expr, Vec<Arm>),
ExprFnBlock(P<FnDecl>, P<Block>),
ExprProc(P<FnDecl>, P<Block>),
ExprBlock(P<Block>),
ExprAssign(@Expr, @Expr),
ExprAssignOp(BinOp, @Expr, @Expr),
ExprField(@Expr, Ident, Vec<P<Ty>> ),
ExprField(@Expr, Ident, Vec<P<Ty>>),
ExprIndex(@Expr, @Expr),
/// Expression that looks like a "name". For example,

View File

@ -66,7 +66,7 @@ impl<'a> Iterator<PathElem> for LinkedPath<'a> {
// HACK(eddyb) move this into libstd (value wrapper for slice::Items).
#[deriving(Clone)]
pub struct Values<'a, T>(slice::Items<'a, T>);
pub struct Values<'a, T>(pub slice::Items<'a, T>);
impl<'a, T: Copy> Iterator<T> for Values<'a, T> {
fn next(&mut self) -> Option<T> {

View File

@ -33,13 +33,13 @@ pub trait Pos {
/// A byte offset. Keep this small (currently 32-bits), as AST contains
/// a lot of them.
#[deriving(Clone, Eq, TotalEq, Hash, Ord, Show)]
pub struct BytePos(u32);
pub struct BytePos(pub u32);
/// A character offset. Because of multibyte utf8 characters, a byte offset
/// is not equivalent to a character offset. The CodeMap will convert BytePos
/// values to CharPos values as necessary.
#[deriving(Eq, Hash, Ord, Show)]
pub struct CharPos(uint);
pub struct CharPos(pub uint);
// FIXME: Lots of boilerplate in these impls, but so far my attempts to fix
// have been unsuccessful

View File

@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
pub struct Closed01<F>(F);
pub struct Closed01<F>(pub F);
pub trait Bar { fn new() -> Self; }

View File

@ -8,4 +8,4 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
pub struct A<'a>(&'a int);
pub struct A<'a>(pub &'a int);

View File

@ -8,4 +8,4 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
pub struct V2<T>(T, T);
pub struct V2<T>(pub T, pub T);

View File

@ -8,4 +8,4 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
pub struct Wrap<A>(A);
pub struct Wrap<A>(pub A);

View File

@ -9,7 +9,7 @@
// except according to those terms.
pub struct S(());
pub struct S(pub ());
impl S {
pub fn foo(&self) { }

View File

@ -161,15 +161,15 @@ pub enum Enum {
}
#[deprecated]
pub struct DeprecatedTupleStruct(int);
pub struct DeprecatedTupleStruct(pub int);
#[experimental]
pub struct ExperimentalTupleStruct(int);
pub struct ExperimentalTupleStruct(pub int);
#[unstable]
pub struct UnstableTupleStruct(int);
pub struct UnmarkedTupleStruct(int);
pub struct UnstableTupleStruct(pub int);
pub struct UnmarkedTupleStruct(pub int);
#[stable]
pub struct StableTupleStruct(int);
pub struct StableTupleStruct(pub int);
#[frozen]
pub struct FrozenTupleStruct(int);
pub struct FrozenTupleStruct(pub int);
#[locked]
pub struct LockedTupleStruct(int);
pub struct LockedTupleStruct(pub int);

View File

@ -10,4 +10,4 @@
#[crate_type="lib"];
pub struct Au(int);
pub struct Au(pub int);

View File

@ -0,0 +1,14 @@
// 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.
pub struct A(());
pub struct B(int);
pub struct C(pub int, int);
pub struct D(pub int);

View File

@ -0,0 +1,137 @@
// 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-tuple-struct.rs
// ignore-fast
extern crate other = "privacy-tuple-struct";
mod a {
pub struct A(());
pub struct B(int);
pub struct C(pub int, int);
pub struct D(pub int);
fn test() {
let a = A(());
let b = B(2);
let c = C(2, 3);
let d = D(4);
let A(()) = a;
let A(_) = a;
match a { A(()) => {} }
match a { A(_) => {} }
let B(_) = b;
let B(_b) = b;
match b { B(_) => {} }
match b { B(_b) => {} }
match b { B(1) => {} B(_) => {} }
let C(_, _) = c;
let C(_a, _) = c;
let C(_, _b) = c;
let C(_a, _b) = c;
match c { C(_, _) => {} }
match c { C(_a, _) => {} }
match c { C(_, _b) => {} }
match c { C(_a, _b) => {} }
let D(_) = d;
let D(_d) = d;
match d { D(_) => {} }
match d { D(_d) => {} }
match d { D(1) => {} D(_) => {} }
let a2 = A;
let b2 = B;
let c2 = C;
let d2 = D;
}
}
fn this_crate() {
let a = a::A(()); //~ ERROR: cannot invoke tuple struct constructor
let b = a::B(2); //~ ERROR: cannot invoke tuple struct constructor
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;
match a { a::A(()) => {} } //~ ERROR: field #1 is private
match a { a::A(_) => {} }
let a::B(_) = b;
let a::B(_b) = b; //~ ERROR: field #1 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
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
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
let a::D(_) = d;
let a::D(_d) = d;
match d { a::D(_) => {} }
match d { a::D(_d) => {} }
match d { a::D(1) => {} a::D(_) => {} }
let a2 = a::A; //~ ERROR: cannot invoke tuple struct constructor
let b2 = a::B; //~ ERROR: cannot invoke tuple struct constructor
let c2 = a::C; //~ ERROR: cannot invoke tuple struct constructor
let d2 = a::D;
}
fn xcrate() {
let a = other::A(()); //~ ERROR: cannot invoke tuple struct constructor
let b = other::B(2); //~ ERROR: cannot invoke tuple struct constructor
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;
match a { other::A(()) => {} } //~ ERROR: field #1 is private
match a { other::A(_) => {} }
let other::B(_) = b;
let other::B(_b) = b; //~ ERROR: field #1 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
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
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
let other::D(_) = d;
let other::D(_d) = d;
match d { other::D(_) => {} }
match d { other::D(_d) => {} }
match d { other::D(1) => {} other::D(_) => {} }
let a2 = other::A; //~ ERROR: cannot invoke tuple struct constructor
let b2 = other::B; //~ ERROR: cannot invoke tuple struct constructor
let c2 = other::C; //~ ERROR: cannot invoke tuple struct constructor
let d2 = other::D;
}
fn main() {}