Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Private fields for tuple structs #13237

Merged
merged 2 commits into from
Apr 4, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/librand/distributions/exponential.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
2 changes: 1 addition & 1 deletion src/librand/distributions/normal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
4 changes: 2 additions & 2 deletions src/librand/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -658,7 +658,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).
Expand All @@ -674,7 +674,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 {
Expand Down
8 changes: 8 additions & 0 deletions src/librustc/metadata/csearch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -311,3 +311,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)
}
11 changes: 7 additions & 4 deletions src/librustc/metadata/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -962,23 +962,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| {
Expand Down
4 changes: 2 additions & 2 deletions src/librustc/middle/graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,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:
Expand Down
119 changes: 98 additions & 21 deletions src/librustc/middle/privacy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

use std::mem::replace;

use metadata::csearch;
use middle::lint;
use middle::resolve;
use middle::ty;
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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);
}
}

Expand Down Expand Up @@ -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) => {
Expand Down Expand Up @@ -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"));
}
}
}
Expand All @@ -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));
}
_ => {}
}
Expand All @@ -749,15 +763,16 @@ 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(_, _) => {
match self.tcx.def_map.borrow().get_copy(&expr.id) {
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,
Expand All @@ -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 => {}
}
}
_ => {}
}
}
_ => {}
}

Expand Down Expand Up @@ -821,15 +876,16 @@ 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(_, _) => {
match self.tcx.def_map.borrow().find(&pattern.id) {
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,
Expand All @@ -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
}
_ => {}
}

}
_ => {}
}

Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/trans/basic_block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>>;

Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/trans/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
6 changes: 3 additions & 3 deletions src/librustc/middle/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -869,13 +869,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 {
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/typeck/infer/coercion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,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> {
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/typeck/infer/glb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 }
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/typeck/infer/lub.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 }
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/typeck/infer/sub.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 }
Expand Down
2 changes: 1 addition & 1 deletion src/librustdoc/html/escape.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
6 changes: 3 additions & 3 deletions src/librustdoc/html/format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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> {
Expand Down
Loading