parent
ade310cbb6
commit
dab8fec4af
10 changed files with 121 additions and 13 deletions
|
@ -1548,6 +1548,7 @@ keyword for struct fields and enum variants). When an item is declared as `pub`,
|
||||||
it can be thought of as being accessible to the outside world. For example:
|
it can be thought of as being accessible to the outside world. For example:
|
||||||
|
|
||||||
~~~~
|
~~~~
|
||||||
|
# fn main() {}
|
||||||
// Declare a private struct
|
// Declare a private struct
|
||||||
struct Foo;
|
struct Foo;
|
||||||
|
|
||||||
|
|
|
@ -87,6 +87,7 @@ Reaching the end of the iterator is signalled by returning `None` instead of
|
||||||
`Some(item)`:
|
`Some(item)`:
|
||||||
|
|
||||||
~~~
|
~~~
|
||||||
|
# fn main() {}
|
||||||
/// A stream of N zeroes
|
/// A stream of N zeroes
|
||||||
struct ZeroStream {
|
struct ZeroStream {
|
||||||
priv remaining: uint
|
priv remaining: uint
|
||||||
|
@ -301,6 +302,7 @@ the iterator can provide better information.
|
||||||
The `ZeroStream` from earlier can provide an exact lower and upper bound:
|
The `ZeroStream` from earlier can provide an exact lower and upper bound:
|
||||||
|
|
||||||
~~~
|
~~~
|
||||||
|
# fn main() {}
|
||||||
/// A stream of N zeroes
|
/// A stream of N zeroes
|
||||||
struct ZeroStream {
|
struct ZeroStream {
|
||||||
priv remaining: uint
|
priv remaining: uint
|
||||||
|
|
|
@ -216,7 +216,7 @@ Now consider code like the following:
|
||||||
|
|
||||||
~~~~
|
~~~~
|
||||||
# enum t1 { good_1(t2, uint), bad_1 };
|
# enum t1 { good_1(t2, uint), bad_1 };
|
||||||
# pub struct t2 { body: t3 }
|
# struct t2 { body: t3 }
|
||||||
# enum t3 { good_2(uint), bad_2};
|
# enum t3 { good_2(uint), bad_2};
|
||||||
# fn f(x: t1) -> uint {
|
# fn f(x: t1) -> uint {
|
||||||
match x {
|
match x {
|
||||||
|
@ -262,7 +262,7 @@ macro_rules! biased_match (
|
||||||
)
|
)
|
||||||
|
|
||||||
# enum t1 { good_1(t2, uint), bad_1 };
|
# enum t1 { good_1(t2, uint), bad_1 };
|
||||||
# pub struct t2 { body: t3 }
|
# struct t2 { body: t3 }
|
||||||
# enum t3 { good_2(uint), bad_2};
|
# enum t3 { good_2(uint), bad_2};
|
||||||
# fn f(x: t1) -> uint {
|
# fn f(x: t1) -> uint {
|
||||||
biased_match!((x) ~ (good_1(g1, val)) else { return 0 };
|
biased_match!((x) ~ (good_1(g1, val)) else { return 0 };
|
||||||
|
@ -364,7 +364,7 @@ macro_rules! biased_match (
|
||||||
|
|
||||||
|
|
||||||
# enum t1 { good_1(t2, uint), bad_1 };
|
# enum t1 { good_1(t2, uint), bad_1 };
|
||||||
# pub struct t2 { body: t3 }
|
# struct t2 { body: t3 }
|
||||||
# enum t3 { good_2(uint), bad_2};
|
# enum t3 { good_2(uint), bad_2};
|
||||||
# fn f(x: t1) -> uint {
|
# fn f(x: t1) -> uint {
|
||||||
biased_match!(
|
biased_match!(
|
||||||
|
|
|
@ -2568,6 +2568,7 @@ pub fn foo() { bar(); }
|
||||||
~~~
|
~~~
|
||||||
// c.rs
|
// c.rs
|
||||||
pub fn bar() { println("Baz!"); }
|
pub fn bar() { println("Baz!"); }
|
||||||
|
# fn main() {}
|
||||||
~~~
|
~~~
|
||||||
|
|
||||||
There also exist two short forms for importing multiple names at once:
|
There also exist two short forms for importing multiple names at once:
|
||||||
|
@ -2743,7 +2744,7 @@ Therefore, if you plan to compile your crate as a library, you should annotate i
|
||||||
#[link(name = "farm", vers = "2.5")];
|
#[link(name = "farm", vers = "2.5")];
|
||||||
|
|
||||||
// ...
|
// ...
|
||||||
# pub fn farm() {}
|
# fn farm() {}
|
||||||
~~~~
|
~~~~
|
||||||
|
|
||||||
You can also in turn require in a `extern mod` statement that certain link metadata items match some criteria.
|
You can also in turn require in a `extern mod` statement that certain link metadata items match some criteria.
|
||||||
|
@ -2769,7 +2770,7 @@ or setting the crate type (library or executable) explicitly:
|
||||||
|
|
||||||
// Turn on a warning
|
// Turn on a warning
|
||||||
#[warn(non_camel_case_types)]
|
#[warn(non_camel_case_types)]
|
||||||
# pub fn farm() {}
|
# fn farm() {}
|
||||||
~~~~
|
~~~~
|
||||||
|
|
||||||
If you're compiling your crate with `rustpkg`,
|
If you're compiling your crate with `rustpkg`,
|
||||||
|
@ -2790,7 +2791,9 @@ We define two crates, and use one of them as a library in the other.
|
||||||
~~~~
|
~~~~
|
||||||
// world.rs
|
// world.rs
|
||||||
#[link(name = "world", vers = "0.42")];
|
#[link(name = "world", vers = "0.42")];
|
||||||
|
# extern mod extra;
|
||||||
pub fn explore() -> &'static str { "world" }
|
pub fn explore() -> &'static str { "world" }
|
||||||
|
# fn main() {}
|
||||||
~~~~
|
~~~~
|
||||||
|
|
||||||
~~~~ {.xfail-test}
|
~~~~ {.xfail-test}
|
||||||
|
|
|
@ -846,7 +846,7 @@ mod tests {
|
||||||
|
|
||||||
fn check_sort(v1: &[int], v2: &[int]) {
|
fn check_sort(v1: &[int], v2: &[int]) {
|
||||||
let len = v1.len();
|
let len = v1.len();
|
||||||
pub fn le(a: &int, b: &int) -> bool { *a <= *b }
|
fn le(a: &int, b: &int) -> bool { *a <= *b }
|
||||||
let f = le;
|
let f = le;
|
||||||
let v3 = merge_sort::<int>(v1, f);
|
let v3 = merge_sort::<int>(v1, f);
|
||||||
let mut i = 0u;
|
let mut i = 0u;
|
||||||
|
@ -876,7 +876,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_merge_sort_mutable() {
|
fn test_merge_sort_mutable() {
|
||||||
pub fn le(a: &int, b: &int) -> bool { *a <= *b }
|
fn le(a: &int, b: &int) -> bool { *a <= *b }
|
||||||
let v1 = ~[3, 2, 1];
|
let v1 = ~[3, 2, 1];
|
||||||
let v2 = merge_sort(v1, le);
|
let v2 = merge_sort(v1, le);
|
||||||
assert_eq!(v2, ~[1, 2, 3]);
|
assert_eq!(v2, ~[1, 2, 3]);
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
//! which are available for use externally when compiled as a library.
|
//! which are available for use externally when compiled as a library.
|
||||||
|
|
||||||
use std::hashmap::{HashSet, HashMap};
|
use std::hashmap::{HashSet, HashMap};
|
||||||
|
use std::util;
|
||||||
|
|
||||||
use middle::resolve;
|
use middle::resolve;
|
||||||
use middle::ty;
|
use middle::ty;
|
||||||
|
@ -275,6 +276,7 @@ impl<'self> Visitor<()> for EmbargoVisitor<'self> {
|
||||||
struct PrivacyVisitor<'self> {
|
struct PrivacyVisitor<'self> {
|
||||||
tcx: ty::ctxt,
|
tcx: ty::ctxt,
|
||||||
curitem: ast::NodeId,
|
curitem: ast::NodeId,
|
||||||
|
in_fn: bool,
|
||||||
|
|
||||||
// See comments on the same field in `EmbargoVisitor`.
|
// See comments on the same field in `EmbargoVisitor`.
|
||||||
path_all_public_items: &'self ExportedItems,
|
path_all_public_items: &'self ExportedItems,
|
||||||
|
@ -688,6 +690,63 @@ impl<'self> PrivacyVisitor<'self> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// When inside of something like a function or a method, visibility has no
|
||||||
|
/// control over anything so this forbids any mention of any visibility
|
||||||
|
fn check_all_inherited(&self, item: @ast::item) {
|
||||||
|
let tcx = self.tcx;
|
||||||
|
let check_inherited = |sp: Span, vis: ast::visibility| {
|
||||||
|
if vis != ast::inherited {
|
||||||
|
tcx.sess.span_err(sp, "visibility has no effect inside functions");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let check_struct = |def: &@ast::struct_def| {
|
||||||
|
for f in def.fields.iter() {
|
||||||
|
match f.node.kind {
|
||||||
|
ast::named_field(_, p) => check_inherited(f.span, p),
|
||||||
|
ast::unnamed_field => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
check_inherited(item.span, item.vis);
|
||||||
|
match item.node {
|
||||||
|
ast::item_impl(_, _, _, ref methods) => {
|
||||||
|
for m in methods.iter() {
|
||||||
|
check_inherited(m.span, m.vis);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ast::item_foreign_mod(ref fm) => {
|
||||||
|
for i in fm.items.iter() {
|
||||||
|
check_inherited(i.span, i.vis);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ast::item_enum(ref def, _) => {
|
||||||
|
for v in def.variants.iter() {
|
||||||
|
check_inherited(v.span, v.node.vis);
|
||||||
|
|
||||||
|
match v.node.kind {
|
||||||
|
ast::struct_variant_kind(ref s) => check_struct(s),
|
||||||
|
ast::tuple_variant_kind(*) => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ast::item_struct(ref def, _) => check_struct(def),
|
||||||
|
|
||||||
|
ast::item_trait(_, _, ref methods) => {
|
||||||
|
for m in methods.iter() {
|
||||||
|
match *m {
|
||||||
|
ast::required(*) => {}
|
||||||
|
ast::provided(ref m) => check_inherited(m.span, m.vis),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ast::item_static(*) |
|
||||||
|
ast::item_fn(*) | ast::item_mod(*) | ast::item_ty(*) |
|
||||||
|
ast::item_mac(*) => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'self> Visitor<()> for PrivacyVisitor<'self> {
|
impl<'self> Visitor<()> for PrivacyVisitor<'self> {
|
||||||
|
@ -699,12 +758,28 @@ impl<'self> Visitor<()> for PrivacyVisitor<'self> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disallow unnecessary visibility qualifiers
|
// Disallow unnecessary visibility qualifiers
|
||||||
self.check_sane_privacy(item);
|
if self.in_fn {
|
||||||
|
self.check_all_inherited(item);
|
||||||
|
} else {
|
||||||
|
self.check_sane_privacy(item);
|
||||||
|
}
|
||||||
|
|
||||||
let orig_curitem = self.curitem;
|
let orig_curitem = util::replace(&mut self.curitem, item.id);
|
||||||
self.curitem = item.id;
|
let orig_in_fn = util::replace(&mut self.in_fn, match item.node {
|
||||||
|
ast::item_mod(*) => false, // modules turn privacy back on
|
||||||
|
_ => self.in_fn, // otherwise we inherit
|
||||||
|
});
|
||||||
visit::walk_item(self, item, ());
|
visit::walk_item(self, item, ());
|
||||||
self.curitem = orig_curitem;
|
self.curitem = orig_curitem;
|
||||||
|
self.in_fn = orig_in_fn;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_fn(&mut self, fk: &visit::fn_kind, fd: &ast::fn_decl,
|
||||||
|
b: &ast::Block, s: Span, n: ast::NodeId, _: ()) {
|
||||||
|
// This catches both functions and methods
|
||||||
|
let orig_in_fn = util::replace(&mut self.in_fn, true);
|
||||||
|
visit::walk_fn(self, fk, fd, b, s, n, ());
|
||||||
|
self.in_fn = orig_in_fn;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_expr(&mut self, expr: @ast::Expr, _: ()) {
|
fn visit_expr(&mut self, expr: @ast::Expr, _: ()) {
|
||||||
|
@ -907,6 +982,7 @@ pub fn check_crate(tcx: ty::ctxt,
|
||||||
{
|
{
|
||||||
let mut visitor = PrivacyVisitor {
|
let mut visitor = PrivacyVisitor {
|
||||||
curitem: ast::DUMMY_NODE_ID,
|
curitem: ast::DUMMY_NODE_ID,
|
||||||
|
in_fn: false,
|
||||||
tcx: tcx,
|
tcx: tcx,
|
||||||
path_all_public_items: &path_all_public_items,
|
path_all_public_items: &path_all_public_items,
|
||||||
parents: &parents,
|
parents: &parents,
|
||||||
|
|
|
@ -1409,7 +1409,7 @@ pub fn subst_tps(tcx: ctxt, tps: &[t], self_ty_opt: Option<t>, typ: t) -> t {
|
||||||
let mut subst = TpsSubst { tcx: tcx, self_ty_opt: self_ty_opt, tps: tps };
|
let mut subst = TpsSubst { tcx: tcx, self_ty_opt: self_ty_opt, tps: tps };
|
||||||
return subst.fold_ty(typ);
|
return subst.fold_ty(typ);
|
||||||
|
|
||||||
pub struct TpsSubst<'self> {
|
struct TpsSubst<'self> {
|
||||||
tcx: ctxt,
|
tcx: ctxt,
|
||||||
self_ty_opt: Option<t>,
|
self_ty_opt: Option<t>,
|
||||||
tps: &'self [t],
|
tps: &'self [t],
|
||||||
|
|
|
@ -138,7 +138,7 @@ pub fn expand_expr(extsbox: @mut SyntaxEnv,
|
||||||
|
|
||||||
let span = e.span;
|
let span = e.span;
|
||||||
|
|
||||||
pub fn mk_expr(_: @ExtCtxt, span: Span, node: Expr_)
|
fn mk_expr(_: @ExtCtxt, span: Span, node: Expr_)
|
||||||
-> @ast::Expr {
|
-> @ast::Expr {
|
||||||
@ast::Expr {
|
@ast::Expr {
|
||||||
id: ast::DUMMY_NODE_ID,
|
id: ast::DUMMY_NODE_ID,
|
||||||
|
|
26
src/test/compile-fail/unnecessary-private.rs
Normal file
26
src/test/compile-fail/unnecessary-private.rs
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
// Copyright 2013 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.
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
pub struct A; //~ ERROR: visibility has no effect
|
||||||
|
pub enum B {} //~ ERROR: visibility has no effect
|
||||||
|
pub trait C { //~ ERROR: visibility has no effect
|
||||||
|
pub fn foo() {} //~ ERROR: visibility has no effect
|
||||||
|
}
|
||||||
|
impl A {
|
||||||
|
pub fn foo() {} //~ ERROR: visibility has no effect
|
||||||
|
}
|
||||||
|
|
||||||
|
struct D {
|
||||||
|
priv foo: int, //~ ERROR: visibility has no effect
|
||||||
|
}
|
||||||
|
pub fn foo() {} //~ ERROR: visibility has no effect
|
||||||
|
pub mod bar {} //~ ERROR: visibility has no effect
|
||||||
|
}
|
|
@ -14,7 +14,7 @@ pub fn main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl b {
|
impl b {
|
||||||
pub fn do_stuff(&self) -> int { return 37; }
|
fn do_stuff(&self) -> int { return 37; }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn b(i:int) -> b {
|
fn b(i:int) -> b {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue