auto merge of #9735 : alexcrichton/rust/privacy, r=cmr

This is the culmination and attempted resolution of #8215. The commits have many more details about implementation details and the consequences of this refinement.

I'll point out specific locations which may be possible causes for alarm. In general, I have been very happy with how things have turned out. I'm a little sad that I couldn't remove privacy from resolve as much as I did, but I blame glob imports (although in theory even some of this can be mitigated as well).
This commit is contained in:
bors 2013-10-07 21:46:39 -07:00
commit 6ddd011ce8
58 changed files with 1945 additions and 1310 deletions

View File

@ -1501,6 +1501,171 @@ is `extern "abi" fn(A1, ..., An) -> R`,
where `A1...An` are the declared types of its arguments
and `R` is the decalred return type.
## Visibility and Privacy
These two terms are often used interchangeably, and what they are attempting to
convey is the answer to the question "Can this item be used at this location?"
Rust's name resolution operates on a global hierarchy of namespaces. Each level
in the hierarchy can be thought of as some item. The items are one of those
mentioned above, but also include external crates. Declaring or defining a new
module can be thought of as inserting a new tree into the hierarchy at the
location of the definition.
To control whether interfaces can be used across modules, Rust checks each use
of an item to see whether it should be allowed or not. This is where privacy
warnings are generated, or otherwise "you used a private item of another module
and weren't allowed to."
By default, everything in rust is *private*, with two exceptions. The first
exception is that struct fields are public by default (but the struct itself is
still private by default), and the remaining exception is that enum variants in
a `pub` enum are the default visibility of the enum container itself.. You are
allowed to alter this default visibility with the `pub` keyword (or `priv`
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:
~~~
// Declare a private struct
struct Foo;
// Declare a public struct with a private field
pub struct Bar {
priv field: int
}
// Declare a public enum with public and private variants
pub enum State {
PubliclyAccessibleState,
priv PrivatelyAccessibleState
}
~~~
With the notion of an item being either public or private, Rust allows item
accesses in two cases:
1. If an item is public, then it can be used externally through any of its
public ancestors.
2. If an item is private, it may be accessed by the current module and its
descendants.
These two cases are surprisingly powerful for creating module hierarchies
exposing public APIs while hiding internal implementation details. To help
explain, here's a few use cases and what they would entail.
* A library developer needs to expose functionality to crates which link against
their library. As a consequence of the first case, this means that anything
which is usable externally must be `pub` from the root down to the destination
item. Any private item in the chain will disallow external accesses.
* A crate needs a global available "helper module" to itself, but it doesn't
want to expose the helper module as a public API. To accomplish this, the root
of the crate's hierarchy would have a private module which then internally has
a "public api". Because the entire crate is an ancestor of the root, then the
entire local crate can access this private module through the second case.
* When writing unit tests for a module, it's often a common idiom to have an
immediate child of the module to-be-tested named `mod test`. This module could
access any items of the parent module through the second case, meaning that
internal implementation details could also be seamlessly tested from the child
module.
In the second case, it mentions that a private item "can be accessed" by the
current module and its descendants, but the exact meaning of accessing an item
depends on what the item is. Accessing a module, for example, would mean looking
inside of it (to import more items). On the other hand, accessing a function
would mean that it is invoked.
Here's an example of a program which exemplifies the three cases outlined above.
~~~
// This module is private, meaning that no external crate can access this
// module. Because it is private at the root of this current crate, however, any
// module in the crate may access any publicly visible item in this module.
mod crate_helper_module {
// This function can be used by anything in the current crate
pub fn crate_helper() {}
// This function *cannot* be used by anything else in the crate. It is not
// publicly visible outside of the `crate_helper_module`, so only this
// current module and its descendants may access it.
fn implementation_detail() {}
}
// This function is "public to the root" meaning that it's available to external
// crates linking against this one.
pub fn public_api() {}
// Similarly to 'public_api', this module is public so external crates may look
// inside of it.
pub mod submodule {
use crate_helper_module;
pub fn my_method() {
// Any item in the local crate may invoke the helper module's public
// interface through a combination of the two rules above.
crate_helper_module::crate_helper();
}
// This function is hidden to any module which is not a descendant of
// `submodule`
fn my_implementation() {}
#[cfg(test)]
mod test {
#[test]
fn test_my_implementation() {
// Because this module is a descendant of `submodule`, it's allowed
// to access private items inside of `submodule` without a privacy
// violation.
super::my_implementation();
}
}
}
# fn main() {}
~~~
For a rust program to pass the privacy checking pass, all paths must be valid
accesses given the two rules above. This includes all use statements,
expressions, types, etc.
### Re-exporting and Visibility
Rust allows publicly re-exporting items through a `pub use` directive. Because
this is a public directive, this allows the item to be used in the current
module through the rules above. It essentially allows public access into the
re-exported item. For example, this program is valid:
~~~
pub use api = self::implementation;
mod implementation {
pub fn f() {}
}
# fn main() {}
~~~
This means that any external crate referencing `implementation::f` would receive
a privacy violation, while the path `api::f` would be allowed.
When re-exporting a private item, it can be thought of as allowing the "privacy
chain" being short-circuited through the reexport instead of passing through the
namespace hierarchy as it normally would.
### Glob imports and Visibility
Currently glob imports are considered an "experimental" language feature. For
sanity purpose along with helping the implementation, glob imports will only
import public items from their destination, not private items.
> **Note:** This is subject to change, glob exports may be removed entirely or
> they could possibly import private items for a privacy error to later be
> issued if the item is used.
## Attributes
~~~~~~~~{.ebnf .gram}

View File

@ -2322,19 +2322,18 @@ fn main() {
The `::farm::chicken` construct is what we call a 'path'.
Because it's starting with a `::`, it's also a 'global path',
which qualifies an item by its full path in the module hierarchy
relative to the crate root.
Because it's starting with a `::`, it's also a 'global path', which qualifies
an item by its full path in the module hierarchy relative to the crate root.
If the path were to start with a regular identifier, like `farm::chicken`, it would be
a 'local path' instead. We'll get to them later.
If the path were to start with a regular identifier, like `farm::chicken`, it
would be a 'local path' instead. We'll get to them later.
Now, if you actually tried to compile this code example, you'll notice
that you get a `unresolved name: 'farm::chicken'` error. That's because per default,
items (`fn`, `struct`, `static`, `mod`, ...) are only visible inside the module
they are defined in.
Now, if you actually tried to compile this code example, you'll notice that you
get a `function 'chicken' is private` error. That's because by default, items
(`fn`, `struct`, `static`, `mod`, ...) are private.
To make them visible outside their containing modules, you need to mark them _public_ with `pub`:
To make them visible outside their containing modules, you need to mark them
_public_ with `pub`:
~~~~
mod farm {
@ -2356,7 +2355,8 @@ Rust doesn't support encapsulation: both struct fields and methods can
be private. But this encapsulation is at the module level, not the
struct level.
For convenience, fields are _public_ by default, and can be made _private_ with the `priv` keyword:
For convenience, fields are _public_ by default, and can be made _private_ with
the `priv` keyword:
~~~
mod farm {
@ -2393,7 +2393,8 @@ fn main() {
# fn make_me_a_chicken() -> farm::Chicken { 0 }
~~~
> ***Note:*** Visibility rules are currently buggy and not fully defined, you might have to add or remove `pub` along a path until it works.
Exact details and specifications about visibility rules can be found in the Rust
manual.
## Files and modules

View File

@ -40,7 +40,7 @@ pub trait Deque<T> : Mutable {
}
#[cfg(test)]
mod bench {
pub mod bench {
use std::container::MutableMap;
use std::{vec, rand};
use std::rand::Rng;

View File

@ -346,7 +346,7 @@ impl <T: FixedBuffer> StandardPadding for T {
#[cfg(test)]
mod test {
pub mod test {
use std::rand::{IsaacRng, Rng};
use std::vec;

View File

@ -101,7 +101,8 @@ pub trait Stats {
/// Extracted collection of all the summary statistics of a sample set.
#[deriving(Clone, Eq)]
struct Summary {
#[allow(missing_doc)]
pub struct Summary {
sum: f64,
min: f64,
max: f64,

View File

@ -199,7 +199,6 @@ pub fn phase_2_configure_and_expand(sess: Session,
pub struct CrateAnalysis {
exp_map2: middle::resolve::ExportMap2,
exported_items: @middle::privacy::ExportedItems,
ty_cx: ty::ctxt,
maps: astencode::Maps,
reachable: @mut HashSet<ast::NodeId>
@ -229,7 +228,9 @@ pub fn phase_3_run_analysis_passes(sess: Session,
let middle::resolve::CrateMap {
def_map: def_map,
exp_map2: exp_map2,
trait_map: trait_map
trait_map: trait_map,
external_exports: external_exports,
last_private_map: last_private_map
} =
time(time_passes, "resolution", (), |_|
middle::resolve::resolve_crate(sess, lang_items, crate));
@ -261,9 +262,10 @@ pub fn phase_3_run_analysis_passes(sess: Session,
middle::check_const::check_crate(sess, crate, ast_map, def_map,
method_map, ty_cx));
let exported_items =
time(time_passes, "privacy checking", (), |_|
middle::privacy::check_crate(ty_cx, &method_map, &exp_map2, crate));
let maps = (external_exports, last_private_map);
time(time_passes, "privacy checking", maps, |(a, b)|
middle::privacy::check_crate(ty_cx, &method_map, &exp_map2,
a, b, crate));
time(time_passes, "effect checking", (), |_|
middle::effect::check_crate(ty_cx, method_map, crate));
@ -305,7 +307,6 @@ pub fn phase_3_run_analysis_passes(sess: Session,
CrateAnalysis {
exp_map2: exp_map2,
exported_items: @exported_items,
ty_cx: ty_cx,
maps: astencode::Maps {
root_map: root_map,

View File

@ -837,8 +837,9 @@ fn each_child_of_item_or_crate(intr: @ident_interner,
let def_like = item_to_def_like(child_item_doc,
child_def_id,
cdata.cnum);
callback(def_like, token::str_to_ident(name),
item_visibility(child_item_doc));
// These items have a public visibility because they're part of
// a public re-export.
callback(def_like, token::str_to_ident(name), ast::public);
}
}

View File

@ -58,7 +58,6 @@ pub struct EncodeParams<'self> {
diag: @mut span_handler,
tcx: ty::ctxt,
reexports2: middle::resolve::ExportMap2,
exported_items: @middle::privacy::ExportedItems,
item_symbols: &'self HashMap<ast::NodeId, ~str>,
discrim_symbols: &'self HashMap<ast::NodeId, @str>,
non_inlineable_statics: &'self HashSet<ast::NodeId>,
@ -89,7 +88,6 @@ pub struct EncodeContext<'self> {
tcx: ty::ctxt,
stats: @mut Stats,
reexports2: middle::resolve::ExportMap2,
exported_items: @middle::privacy::ExportedItems,
item_symbols: &'self HashMap<ast::NodeId, ~str>,
discrim_symbols: &'self HashMap<ast::NodeId, @str>,
non_inlineable_statics: &'self HashSet<ast::NodeId>,
@ -625,6 +623,7 @@ fn encode_info_for_mod(ecx: &EncodeContext,
}
encode_path(ecx, ebml_w, path, ast_map::path_mod(name));
encode_visibility(ebml_w, vis);
// Encode the reexports of this module, if this module is public.
if vis == public {
@ -1277,12 +1276,7 @@ fn my_visit_item(i:@item, items: ast_map::map, ebml_w:&writer::Encoder,
let mut ebml_w = ebml_w.clone();
// See above
let ecx : &EncodeContext = unsafe { cast::transmute(ecx_ptr) };
let vis = if ecx.exported_items.contains(&i.id) {
ast::public
} else {
ast::inherited
};
encode_info_for_item(ecx, &mut ebml_w, i, index, *pt, vis);
encode_info_for_item(ecx, &mut ebml_w, i, index, *pt, i.vis);
}
_ => fail2!("bad item")
}
@ -1628,7 +1622,7 @@ impl<'self> Visitor<()> for ImplVisitor<'self> {
// Load eagerly if this is an implementation of the Drop trait
// or if the trait is not defined in this crate.
if def_id == self.ecx.tcx.lang_items.drop_trait().unwrap() ||
if Some(def_id) == self.ecx.tcx.lang_items.drop_trait() ||
def_id.crate != LOCAL_CRATE {
self.ebml_w.start_tag(tag_impls_impl);
encode_def_id(self.ebml_w, local_def(item.id));
@ -1744,7 +1738,6 @@ pub fn encode_metadata(parms: EncodeParams, crate: &Crate) -> ~[u8] {
diag,
tcx,
reexports2,
exported_items,
discrim_symbols,
cstore,
encode_inlined_item,
@ -1760,7 +1753,6 @@ pub fn encode_metadata(parms: EncodeParams, crate: &Crate) -> ~[u8] {
tcx: tcx,
stats: stats,
reexports2: reexports2,
exported_items: exported_items,
item_symbols: item_symbols,
discrim_symbols: discrim_symbols,
non_inlineable_statics: non_inlineable_statics,

View File

@ -31,8 +31,8 @@ use syntax::ast_util::id_range;
use syntax::codemap::Span;
use syntax::print::pprust;
use syntax::visit;
use syntax::visit::Visitor;
use syntax::ast::{Expr, fn_kind, fn_decl, Block, NodeId, Stmt, Pat, Local};
use syntax::visit::{Visitor, fn_kind};
use syntax::ast::{Expr, fn_decl, Block, NodeId, Stmt, Pat, Local};
mod lifetime;
mod restrictions;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -3034,7 +3034,6 @@ pub fn crate_ctxt_to_encode_parms<'r>(cx: &'r CrateContext, ie: encoder::encode_
diag: diag,
tcx: cx.tcx,
reexports2: cx.exp_map2,
exported_items: cx.exported_items,
item_symbols: item_symbols,
discrim_symbols: discrim_symbols,
non_inlineable_statics: &cx.non_inlineable_statics,
@ -3116,7 +3115,6 @@ pub fn trans_crate(sess: session::Session,
llmod_id,
analysis.ty_cx,
analysis.exp_map2,
analysis.exported_items,
analysis.maps,
symbol_hasher,
link_meta,

View File

@ -16,7 +16,6 @@ use lib::llvm::{llvm, TargetData, TypeNames};
use lib::llvm::mk_target_data;
use metadata::common::LinkMeta;
use middle::astencode;
use middle::privacy;
use middle::resolve;
use middle::trans::adt;
use middle::trans::base;
@ -49,7 +48,6 @@ pub struct CrateContext {
intrinsics: HashMap<&'static str, ValueRef>,
item_vals: HashMap<ast::NodeId, ValueRef>,
exp_map2: resolve::ExportMap2,
exported_items: @privacy::ExportedItems,
reachable: @mut HashSet<ast::NodeId>,
item_symbols: HashMap<ast::NodeId, ~str>,
link_meta: LinkMeta,
@ -125,7 +123,6 @@ impl CrateContext {
name: &str,
tcx: ty::ctxt,
emap2: resolve::ExportMap2,
exported_items: @privacy::ExportedItems,
maps: astencode::Maps,
symbol_hasher: hash::State,
link_meta: LinkMeta,
@ -185,7 +182,6 @@ impl CrateContext {
intrinsics: intrinsics,
item_vals: HashMap::new(),
exp_map2: emap2,
exported_items: exported_items,
reachable: reachable,
item_symbols: HashMap::new(),
link_meta: link_meta,

View File

@ -581,7 +581,7 @@ impl Datum {
if !header && !ty::type_contents(bcx.tcx(), content_ty).contains_managed() {
let ptr = self.to_value_llval(bcx);
let ty = type_of(bcx.ccx(), content_ty);
let ty = type_of::type_of(bcx.ccx(), content_ty);
let body = PointerCast(bcx, ptr, ty.ptr_to());
Datum {val: body, ty: content_ty, mode: ByRef(ZeroMem)}
} else { // has a header

View File

@ -1026,7 +1026,7 @@ fn trans_lvalue_unadjusted(bcx: @mut Block, expr: &ast::Expr) -> DatumBlock {
// which may not be equal to the enum's type for
// non-C-like enums.
let val = base::get_item_val(bcx.ccx(), did.node);
let pty = type_of(bcx.ccx(), const_ty).ptr_to();
let pty = type_of::type_of(bcx.ccx(), const_ty).ptr_to();
PointerCast(bcx, val, pty)
} else {
{
@ -1040,7 +1040,7 @@ fn trans_lvalue_unadjusted(bcx: @mut Block, expr: &ast::Expr) -> DatumBlock {
}
unsafe {
let llty = type_of(bcx.ccx(), const_ty);
let llty = type_of::type_of(bcx.ccx(), const_ty);
let symbol = csearch::get_symbol(
bcx.ccx().sess.cstore,
did);
@ -1396,7 +1396,7 @@ fn trans_unary_datum(bcx: @mut Block,
heap: heap) -> DatumBlock {
let _icx = push_ctxt("trans_boxed_expr");
if heap == heap_exchange {
let llty = type_of(bcx.ccx(), contents_ty);
let llty = type_of::type_of(bcx.ccx(), contents_ty);
let size = llsize_of(bcx.ccx(), llty);
let Result { bcx: bcx, val: val } = malloc_raw_dyn(bcx, contents_ty,
heap_exchange, size);

View File

@ -203,7 +203,7 @@ pub fn lazily_emit_tydesc_glue(ccx: @mut CrateContext,
field: uint,
ti: @mut tydesc_info) {
let _icx = push_ctxt("lazily_emit_tydesc_glue");
let llfnty = Type::glue_fn(type_of::type_of(ccx, ti.ty).ptr_to());
let llfnty = Type::glue_fn(type_of(ccx, ti.ty).ptr_to());
if lazily_emit_simplified_tydesc_glue(ccx, field, ti) {
return;
@ -345,7 +345,7 @@ pub fn make_visit_glue(bcx: @mut Block, v: ValueRef, t: ty::t) -> @mut Block {
bcx.tcx().sess.fatal(s);
}
};
let v = PointerCast(bcx, v, type_of::type_of(bcx.ccx(), object_ty).ptr_to());
let v = PointerCast(bcx, v, type_of(bcx.ccx(), object_ty).ptr_to());
bcx = reflect::emit_calls_to_trait_visit_ty(bcx, t, v, visitor_trait.def_id);
// The visitor is a boxed object and needs to be dropped
add_clean(bcx, v, object_ty);

View File

@ -330,8 +330,8 @@ impl CoherenceChecker {
let impl_poly_type = ty::lookup_item_type(tcx, impl_id);
let provided = ty::provided_trait_methods(tcx, trait_ref.def_id);
for trait_method in provided.iter() {
let prov = ty::provided_trait_methods(tcx, trait_ref.def_id);
for trait_method in prov.iter() {
// Synthesize an ID.
let new_id = tcx.sess.next_node_id();
let new_did = local_def(new_id);

View File

@ -126,7 +126,7 @@ enum Implementor {
/// to be a fairly large and expensive structure to clone. Instead this adheres
/// to both `Send` and `Freeze` so it may be stored in a `RWArc` instance and
/// shared among the various rendering tasks.
struct Cache {
pub struct Cache {
/// Mapping of typaram ids to the name of the type parameter. This is used
/// when pretty-printing a type (so pretty printing doesn't have to
/// painfully maintain a context like this)

View File

@ -24,7 +24,7 @@ use utils::*;
/// This structure keeps track of the state of the world for the code being
/// executed in rusti.
#[deriving(Clone)]
struct Program {
pub struct Program {
/// All known local variables
local_vars: HashMap<~str, LocalVariable>,
/// New variables which will be present (learned from typechecking)

View File

@ -36,10 +36,10 @@ pub mod c_double_utils {
pub fn exp(n: c_double) -> c_double;
// rename: for consistency with underscore usage elsewhere
#[link_name="expm1"]
fn exp_m1(n: c_double) -> c_double;
pub fn exp_m1(n: c_double) -> c_double;
pub fn exp2(n: c_double) -> c_double;
#[link_name="fabs"]
fn abs(n: c_double) -> c_double;
pub fn abs(n: c_double) -> c_double;
// rename: for clarity and consistency with add/sub/mul/div
#[link_name="fdim"]
pub fn abs_sub(a: c_double, b: c_double) -> c_double;

View File

@ -335,14 +335,15 @@ mod test {
// newtype struct autoderef weirdness
#[test]
fn test_buffered_stream() {
use rt;
struct S;
impl Writer for S {
impl rt::io::Writer for S {
fn write(&mut self, _: &[u8]) {}
fn flush(&mut self) {}
}
impl Reader for S {
impl rt::io::Reader for S {
fn read(&mut self, _: &mut [u8]) -> Option<uint> { None }
fn eof(&mut self) -> bool { true }
}

View File

@ -300,7 +300,8 @@ pub mod comm_adapters;
mod extensions;
/// Non-I/O things needed by the I/O module
mod support;
// XXX: shouldn this really be pub?
pub mod support;
/// Basic Timer
pub mod timer;

View File

@ -67,14 +67,27 @@ use rt::local::Local;
use rt::sched::{Scheduler, Shutdown};
use rt::sleeper_list::SleeperList;
use rt::task::{Task, SchedTask, GreenTask, Sched};
use rt::thread::Thread;
use rt::work_queue::WorkQueue;
use rt::uv::uvio::UvEventLoop;
use unstable::atomics::{AtomicInt, SeqCst};
use unstable::sync::UnsafeArc;
use vec;
use vec::{OwnedVector, MutableVector, ImmutableVector};
use self::thread::Thread;
use self::work_queue::WorkQueue;
// XXX: these probably shouldn't be public...
#[doc(hidden)]
pub mod shouldnt_be_public {
pub use super::sched::Scheduler;
pub use super::kill::KillHandle;
pub use super::thread::Thread;
pub use super::work_queue::WorkQueue;
pub use super::select::SelectInner;
pub use super::rtio::EventLoop;
pub use super::select::{SelectInner, SelectPortInner};
}
/// The global (exchange) heap.
pub mod global_heap;

View File

@ -803,6 +803,12 @@ impl SchedHandle {
self.queue.push(msg);
self.remote.fire();
}
pub fn send_task_from_friend(&mut self, friend: ~Task) {
self.send(TaskFromFriend(friend));
}
pub fn send_shutdown(&mut self) {
self.send(Shutdown);
}
}
struct CleanupJob {

View File

@ -15,10 +15,8 @@ use iter::{Iterator, DoubleEndedIterator};
use option::*;
// use either::{Either, Left, Right};
// use rt::kill::BlockedTask;
use rt::sched::Scheduler;
use rt::select::{SelectInner, SelectPortInner};
use rt::local::Local;
use rt::rtio::EventLoop;
use rt::shouldnt_be_public::{EventLoop, Scheduler, SelectInner, SelectPortInner};
use task;
use unstable::finally::Finally;
use vec::{OwnedVector, MutableVector};

View File

@ -551,7 +551,7 @@ pub fn deschedule() {
//! Yield control to the task scheduler
use rt::local::Local;
use rt::sched::Scheduler;
use rt::shouldnt_be_public::Scheduler;
// FIXME(#7544): Optimize this, since we know we won't block.
let sched: ~Scheduler = Local::take();
@ -1069,7 +1069,7 @@ fn test_try_fail() {
#[cfg(test)]
fn get_sched_id() -> int {
do Local::borrow |sched: &mut ::rt::sched::Scheduler| {
do Local::borrow |sched: &mut ::rt::shouldnt_be_public::Scheduler| {
sched.sched_id() as int
}
}

View File

@ -89,11 +89,8 @@ use unstable::sync::Exclusive;
use rt::in_green_task_context;
use rt::local::Local;
use rt::task::{Task, Sched};
use rt::kill::KillHandle;
use rt::sched::Scheduler;
use rt::shouldnt_be_public::{Scheduler, KillHandle, WorkQueue, Thread};
use rt::uv::uvio::UvEventLoop;
use rt::thread::Thread;
use rt::work_queue::WorkQueue;
#[cfg(test)] use task::default_task_opts;
#[cfg(test)] use comm;
@ -556,8 +553,6 @@ fn enlist_many(child: &KillHandle, child_arc: &TaskGroupArc,
}
pub fn spawn_raw(mut opts: TaskOpts, f: ~fn()) {
use rt::sched::*;
rtassert!(in_green_task_context());
let child_data = Cell::new(gen_child_taskgroup(opts.linked, opts.supervised));
@ -622,7 +617,7 @@ pub fn spawn_raw(mut opts: TaskOpts, f: ~fn()) {
let mut new_sched_handle = new_sched.make_handle();
// Allow the scheduler to exit when the pinned task exits
new_sched_handle.send(Shutdown);
new_sched_handle.send_shutdown();
// Pin the new task to the new scheduler
let new_task = if opts.watched {
@ -660,7 +655,7 @@ pub fn spawn_raw(mut opts: TaskOpts, f: ~fn()) {
rtdebug!("enqueing join_task");
// Now tell the original scheduler to join with this thread
// by scheduling a thread-joining task on the original scheduler
orig_sched_handle.send(TaskFromFriend(join_task));
orig_sched_handle.send_task_from_friend(join_task);
// NB: We can't simply send a message from here to another task
// because this code isn't running in a task and message passing doesn't

View File

@ -38,7 +38,7 @@ a normal large stack.
*/
pub fn run_in_bare_thread(f: ~fn()) {
use cell::Cell;
use rt::thread::Thread;
use rt::shouldnt_be_public::Thread;
let f_cell = Cell::new(f);
let (port, chan) = comm::stream();

View File

@ -90,10 +90,10 @@ mod tests {
use super::*;
use clone::Clone;
use ops::Drop;
use option::{None, Some};
use either::{Either, Left, Right};
use sys::size_of;
use kinds::Drop;
#[test]
fn identity_crisis() {

View File

@ -702,32 +702,6 @@ pub fn struct_def_is_tuple_like(struct_def: &ast::struct_def) -> bool {
struct_def.ctor_id.is_some()
}
pub fn visibility_to_privacy(visibility: visibility) -> Privacy {
match visibility {
public => Public,
inherited | private => Private
}
}
pub fn variant_visibility_to_privacy(visibility: visibility,
enclosing_is_public: bool)
-> Privacy {
if enclosing_is_public {
match visibility {
public | inherited => Public,
private => Private
}
} else {
visibility_to_privacy(visibility)
}
}
#[deriving(Eq)]
pub enum Privacy {
Private,
Public
}
/// Returns true if the given pattern consists solely of an identifier
/// and false otherwise.
pub fn pat_is_ident(pat: @ast::Pat) -> bool {
@ -990,7 +964,7 @@ mod test {
use super::*;
use std::io;
use opt_vec;
use std::hash::HashMap;
use std::hashmap::HashMap;
fn ident_to_segment(id : &Ident) -> PathSegment {
PathSegment{identifier:id.clone(), lifetime: None, types: opt_vec::Empty}

View File

@ -1551,7 +1551,8 @@ mod test {
let varrefs = @mut ~[];
visit::walk_crate(&mut new_path_finder(varrefs), &renamed_ast, ());
match varrefs {
@[Path{segments:[ref seg],_}] => assert_eq!(mtwt_resolve(seg.identifier),a2_name),
@[ast::Path{segments:[ref seg],_}] =>
assert_eq!(mtwt_resolve(seg.identifier),a2_name),
_ => assert_eq!(0,1)
}
@ -1565,7 +1566,8 @@ mod test {
let varrefs = @mut ~[];
visit::walk_crate(&mut new_path_finder(varrefs), &double_renamed, ());
match varrefs {
@[Path{segments:[ref seg],_}] => assert_eq!(mtwt_resolve(seg.identifier),a3_name),
@[ast::Path{segments:[ref seg],_}] =>
assert_eq!(mtwt_resolve(seg.identifier),a3_name),
_ => assert_eq!(0,1)
}
}

View File

@ -8,9 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// error-pattern: import
use m::unexported;
//~^ ERROR: is private
mod m {
pub fn exported() { }

View File

@ -8,12 +8,10 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// error-pattern: unresolved name
mod foo {
pub fn x() { }
enum y { y1, }
}
fn main() { let z = foo::y1; }
fn main() { let z = foo::y1; } //~ ERROR: is private

View File

@ -0,0 +1,47 @@
// 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.
// Make sure that globs only bring in public things.
#[feature(globs)];
use bar::*;
mod bar {
use import = self::fpriv;
fn fpriv() {}
extern {
fn epriv();
}
enum A { A1 }
pub enum B { B1 }
struct C;
type D = int;
}
fn foo<T>() {}
fn main() {
fpriv(); //~ ERROR: unresolved
epriv(); //~ ERROR: unresolved
A1; //~ ERROR: unresolved
B1;
C; //~ ERROR: unresolved
import(); //~ ERROR: unresolved
foo::<A>(); //~ ERROR: undeclared
//~^ ERROR: undeclared
foo::<C>(); //~ ERROR: undeclared
//~^ ERROR: undeclared
foo::<D>(); //~ ERROR: undeclared
//~^ ERROR: undeclared
}

View File

@ -8,12 +8,11 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use zoo::{duck, goose}; //~ ERROR failed to resolve import
//~^ ERROR unresolved import: found `goose` in `zoo` but it is private
use zoo::{duck, goose}; //~ ERROR: variant `goose` is private
mod zoo {
pub enum bird {
pub duck,
pub duck, //~ ERROR: unnecessary `pub` visibility
priv goose
}
}

View File

@ -8,13 +8,13 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use zoo::fly; //~ ERROR failed to resolve import
//~^ ERROR unresolved import: found `fly` in `zoo` but it is private
use zoo::fly; //~ ERROR: function `fly` is private
mod zoo {
type fly = ();
fn fly() {}
}
fn main() {}
fn main() {
fly();
}

View File

@ -8,12 +8,13 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use zoo::fly; //~ ERROR failed to resolve import
//~^ ERROR unresolved import: found `fly` in `zoo` but it is private
use zoo::fly; //~ ERROR: function `fly` is private
mod zoo {
fn fly() {}
}
fn main() {}
fn main() {
fly();
}

View File

@ -0,0 +1,39 @@
// 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.
#[feature(globs)];
// ensures that 'use foo:*' doesn't import non-public item
use m1::*;
mod foo {
pub fn foo() {}
}
mod a {
pub mod b {
use foo::foo;
type bar = int;
}
pub mod sub {
use a::b::*;
fn sub() -> bar { 1 }
//~^ ERROR: undeclared type name
}
}
mod m1 {
fn foo() {}
}
fn main() {
foo(); //~ ERROR: unresolved name
}

View File

@ -27,8 +27,7 @@ mod a {
}
pub mod sub {
use a::b::*;
fn sub() -> bar { foo(); 1 } //~ ERROR: unresolved name `foo`
//~^ ERROR: use of undeclared type name `bar`
fn sub() -> int { foo(); 1 } //~ ERROR: unresolved name `foo`
}
}
@ -36,6 +35,4 @@ mod m1 {
fn foo() {}
}
fn main() {
foo(); //~ ERROR: unresolved name `foo`
}
fn main() {}

View File

@ -18,5 +18,5 @@ mod bar {
fn main() {
local_data::set(bar::baz, -10.0);
//~^ ERROR unresolved name `bar::baz`
//~^ ERROR static `baz` is private
}

View File

@ -0,0 +1,169 @@
// 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.
#[feature(globs)];
#[no_std]; // makes debugging this test *a lot* easier (during resolve)
mod bar {
// shouln't bring in too much
pub use self::glob::*;
// can't publicly re-export private items
pub use self::baz::{foo, bar};
//~^ ERROR: function `bar` is private
pub use self::private::ppriv;
//~^ ERROR: function `ppriv` is private
pub struct A;
impl A {
pub fn foo() {}
fn bar() {}
pub fn foo2(&self) {}
fn bar2(&self) {}
}
pub enum Enum {
priv Priv,
Pub
}
mod baz {
pub struct A;
impl A {
pub fn foo() {}
fn bar() {}
pub fn foo2(&self) {}
fn bar2(&self) {}
}
// both of these are re-exported by `bar`, but only one should be
// validly re-exported
pub fn foo() {}
fn bar() {}
}
extern {
fn epriv();
pub fn epub();
}
fn test() {
self::Priv;
self::Pub;
unsafe {
epriv();
epub();
}
self::baz::A;
self::baz::A::foo();
self::baz::A::bar(); //~ ERROR: method `bar` is private
self::baz::A.foo2();
self::baz::A.bar2(); //~ ERROR: method `bar2` is private
// this used to cause an ICE in privacy traversal.
super::gpub();
}
mod glob {
pub fn gpub() {}
fn gpriv() {}
}
mod private {
fn ppriv() {}
}
}
pub fn gpub() {}
fn lol() {
bar::A;
bar::A::foo();
bar::A::bar(); //~ ERROR: method `bar` is private
bar::A.foo2();
bar::A.bar2(); //~ ERROR: method `bar2` is private
}
mod foo {
fn test() {
::bar::A::foo();
::bar::A::bar(); //~ ERROR: method `bar` is private
::bar::A.foo2();
::bar::A.bar2(); //~ ERROR: method `bar2` is private
::bar::baz::A::foo(); //~ ERROR: method `foo` is private
::bar::baz::A::bar(); //~ ERROR: method `bar` is private
::bar::baz::A.foo2(); //~ ERROR: struct `A` is private
::bar::baz::A.bar2(); //~ ERROR: struct `A` is private
//~^ ERROR: method `bar2` is private
::lol();
::bar::Priv; //~ ERROR: variant `Priv` is private
::bar::Pub;
unsafe {
::bar::epriv(); //~ ERROR: function `epriv` is private
::bar::epub();
}
::bar::foo();
::bar::bar();
::bar::gpub();
::bar::baz::foo(); //~ ERROR: function `foo` is private
::bar::baz::bar(); //~ ERROR: function `bar` is private
}
fn test2() {
use bar::baz::{foo, bar};
//~^ ERROR: function `foo` is private
//~^^ ERROR: function `bar` is private
foo();
bar();
}
fn test3() {
use bar::baz;
//~^ ERROR: module `baz` is private
}
fn test4() {
use bar::{foo, bar};
foo();
bar();
}
fn test5() {
use bar;
bar::foo();
bar::bar();
}
}
pub mod mytest {
// Even though the inner `A` struct is a publicly exported item (usable from
// external crates through `foo::foo`, it should not be accessible through
// its definition path (which has the private `i` module).
use self::foo::foo;
use self::foo::i::A; //~ ERROR: type `A` is private
pub mod foo {
pub use foo = self::i::A;
mod i {
pub struct A;
}
}
}
#[start] fn main(_: int, _: **u8) -> int { 3 }

View File

@ -0,0 +1,38 @@
// 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.
#[feature(globs)];
#[no_std]; // makes debugging this test *a lot* easier (during resolve)
// Test to make sure that globs don't leak in regular `use` statements.
mod bar {
pub use self::glob::*;
mod glob {
use foo;
}
}
pub fn foo() {}
fn test1() {
use bar::foo; //~ ERROR: unresolved import
//~^ ERROR: failed to resolve
}
fn test2() {
use bar::glob::foo;
//~^ ERROR: there is no
//~^^ ERROR: failed to resolve
}
#[start] fn main(_: int, _: **u8) -> int { 3 }

View File

@ -0,0 +1,33 @@
// 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.
#[feature(globs)];
#[no_std]; // makes debugging this test *a lot* easier (during resolve)
// Test to make sure that private items imported through globs remain private
// when they're used.
mod bar {
pub use self::glob::*;
mod glob {
fn gpriv() {}
}
}
pub fn foo() {}
fn test1() {
use bar::gpriv; //~ ERROR: unresolved import
//~^ ERROR: failed to resolve
gpriv();
}
#[start] fn main(_: int, _: **u8) -> int { 3 }

View File

@ -0,0 +1,32 @@
// 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.
#[feature(globs)];
#[no_std]; // makes debugging this test *a lot* easier (during resolve)
// Test to make sure that private items imported through globs remain private
// when they're used.
mod bar {
pub use self::glob::*;
mod glob {
fn gpriv() {}
}
}
pub fn foo() {}
fn test2() {
use bar::glob::gpriv; //~ ERROR: function `gpriv` is private
gpriv();
}
#[start] fn main(_: int, _: **u8) -> int { 3 }

View File

@ -13,5 +13,5 @@ mod a {
}
fn main() {
a::f(); //~ ERROR unresolved name
a::f(); //~ ERROR function `f` is private
}

View File

@ -17,5 +17,5 @@ mod a {
}
fn main() {
let x = a::Liege; //~ ERROR unresolved name
let x = a::Liege; //~ ERROR variant `Liege` is private
}

View File

@ -24,15 +24,15 @@ mod child {
fn foo(_: int) {}
fn full_ref() {
foo(static_priv_by_default::private); //~ ERROR: unresolved name
foo(static_priv_by_default::private); //~ ERROR: static `private` is private
foo(static_priv_by_default::public);
foo(child::childs_child::private); //~ ERROR: unresolved name
foo(child::childs_child::private); //~ ERROR: static `private` is private
foo(child::childs_child::public);
}
fn medium_ref() {
use child::childs_child;
foo(childs_child::private); //~ ERROR: unresolved name
foo(childs_child::private); //~ ERROR: static `private` is private
foo(childs_child::public);
}

View File

@ -19,11 +19,22 @@ mod child {
}
}
fn main() {
use static_priv_by_default::private; //~ ERROR: unresolved import
//~^ ERROR: failed to resolve
use static_priv_by_default::public;
use child::childs_child::private; //~ ERROR: unresolved import
//~^ ERROR: failed to resolve
fn foo<T>(_: T) {}
fn test1() {
use child::childs_child::private;
//~^ ERROR: static `private` is private
use child::childs_child::public;
foo(private);
}
fn test2() {
use static_priv_by_default::private;
//~^ ERROR: static `private` is private
use static_priv_by_default::public;
foo(private);
}
fn main() {}

View File

@ -15,8 +15,8 @@ extern mod xc_private_method_lib;
fn main() {
let _ = xc_private_method_lib::Struct::static_meth_struct();
//~^ ERROR: unresolved name
//~^ ERROR: method `static_meth_struct` is private
let _ = xc_private_method_lib::Enum::static_meth_enum();
//~^ ERROR: unresolved name
//~^ ERROR: method `static_meth_enum` is private
}

View File

@ -10,15 +10,14 @@
// aux-build:static_priv_by_default.rs
#[allow(unused_imports)];
#[no_std];
#[no_std]; // helps if debugging resolve
extern mod static_priv_by_default;
fn foo<T>() {}
#[start]
fn main(_: int, _: **u8, _: *u8) -> int {
fn main(_: int, _: **u8) -> int {
// Actual public items should be public
static_priv_by_default::a;
static_priv_by_default::b;
@ -33,25 +32,23 @@ fn main(_: int, _: **u8, _: *u8) -> int {
// private items at the top should be inaccessible
static_priv_by_default::i;
//~^ ERROR: unresolved name
//~^ ERROR: static `i` is private
static_priv_by_default::j;
//~^ ERROR: unresolved name
//~^ ERROR: function `j` is private
static_priv_by_default::k;
//~^ ERROR: unresolved name
//~^ ERROR: struct `k` is private
foo::<static_priv_by_default::l>();
//~^ ERROR: use of undeclared type name
//~^^ ERROR: use of undeclared type name
//~^ ERROR: type `l` is private
// public items in a private mod should be inaccessible
static_priv_by_default::foo::a;
//~^ ERROR: unresolved name
//~^ ERROR: static `a` is private
static_priv_by_default::foo::b;
//~^ ERROR: unresolved name
//~^ ERROR: function `b` is private
static_priv_by_default::foo::c;
//~^ ERROR: unresolved name
//~^ ERROR: struct `c` is private
foo::<static_priv_by_default::foo::d>();
//~^ ERROR: use of undeclared type name
//~^^ ERROR: use of undeclared type name
//~^ ERROR: type `d` is private
3
}

View File

@ -9,7 +9,7 @@
// except according to those terms.
mod foo {
mod bar {
pub mod bar {
pub fn y() { super::super::foo::x(); }
}

View File

@ -17,7 +17,7 @@ mod rustrt1 {
#[abi = "cdecl"]
#[link_name = "rustrt"]
extern {
fn rust_get_test_int() -> libc::intptr_t;
pub fn rust_get_test_int() -> libc::intptr_t;
}
}
@ -27,7 +27,7 @@ mod rustrt2 {
#[abi = "cdecl"]
#[link_name = "rustrt"]
extern {
fn rust_get_test_int() -> libc::intptr_t;
pub fn rust_get_test_int() -> libc::intptr_t;
}
}

View File

@ -14,7 +14,7 @@ mod rustrt {
use std::libc;
extern {
fn rust_get_test_int() -> libc::intptr_t;
pub fn rust_get_test_int() -> libc::intptr_t;
}
}

View File

@ -11,7 +11,7 @@
mod rusti {
#[abi = "rust-intrinsic"]
extern "rust-intrinsic" {
fn uninit<T>() -> T;
pub fn uninit<T>() -> T;
}
}
pub fn main() {

View File

@ -17,24 +17,24 @@ extern mod extra;
mod rusti {
#[abi = "rust-intrinsic"]
extern "rust-intrinsic" {
fn ctpop8(x: i8) -> i8;
fn ctpop16(x: i16) -> i16;
fn ctpop32(x: i32) -> i32;
fn ctpop64(x: i64) -> i64;
pub fn ctpop8(x: i8) -> i8;
pub fn ctpop16(x: i16) -> i16;
pub fn ctpop32(x: i32) -> i32;
pub fn ctpop64(x: i64) -> i64;
fn ctlz8(x: i8) -> i8;
fn ctlz16(x: i16) -> i16;
fn ctlz32(x: i32) -> i32;
fn ctlz64(x: i64) -> i64;
pub fn ctlz8(x: i8) -> i8;
pub fn ctlz16(x: i16) -> i16;
pub fn ctlz32(x: i32) -> i32;
pub fn ctlz64(x: i64) -> i64;
fn cttz8(x: i8) -> i8;
fn cttz16(x: i16) -> i16;
fn cttz32(x: i32) -> i32;
fn cttz64(x: i64) -> i64;
pub fn cttz8(x: i8) -> i8;
pub fn cttz16(x: i16) -> i16;
pub fn cttz32(x: i32) -> i32;
pub fn cttz64(x: i64) -> i64;
fn bswap16(x: i16) -> i16;
fn bswap32(x: i32) -> i32;
fn bswap64(x: i64) -> i64;
pub fn bswap16(x: i16) -> i16;
pub fn bswap32(x: i32) -> i32;
pub fn bswap64(x: i64) -> i64;
}
}

View File

@ -8,4 +8,4 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
mod test;
pub mod test;

View File

@ -0,0 +1,29 @@
// 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.
pub mod test2 {
// This used to generate an ICE (make sure that default functions are
// parented to their trait to find the first private thing as the trait).
struct B;
trait A { fn foo(&self) {} }
impl A for B {}
mod tests {
use super::A;
fn foo() {
let a = super::B;
a.foo();
}
}
}
pub fn main() {}

View File

@ -46,7 +46,7 @@ mod m {
}
#[cfg(target_arch = "x86_64")]
mod m {
pub mod m {
pub fn align() -> uint { 8u }
pub fn size() -> uint { 16u }
}