提交 b9ff86e2 编写于 作者: B bors

auto merge of #13835 : alexcrichton/rust/localdata, r=brson

This commit brings the local_data api up to modern rust standards with a few key
improvements:

* All functionality is now exposed as a method on the keys themselves. Instead
  of importing std::local_data, you now use "key.set()" and "key.get()".

* All closures have been removed in favor of RAII functionality. This means that
  get() and get_mut() no long require closures, but rather return
  Option<SmartPointer> where the smart pointer takes care of relinquishing the
  borrow and also implements the necessary Deref traits

* The modify() function was removed to cut the local_data interface down to its
  bare essentials (similarly to how RefCell removed set/get).

[breaking-change]
......@@ -1617,8 +1617,7 @@ mod test_map {
use std::cmp::Equiv;
use std::hash::Hash;
use std::iter::{Iterator,range_inclusive,range_step_inclusive};
use std::local_data;
use std::vec;
use std::cell::RefCell;
struct KindaIntLike(int);
......@@ -1657,7 +1656,7 @@ fn test_insert() {
assert_eq!(*m.find(&2).unwrap(), 4);
}
local_data_key!(drop_vector: vec::Vec<int>)
local_data_key!(drop_vector: RefCell<Vec<int>>)
#[deriving(Hash, Eq, TotalEq)]
struct Dropable {
......@@ -1667,8 +1666,8 @@ struct Dropable {
impl Dropable {
fn new(k: uint) -> Dropable {
local_data::get_mut(drop_vector,
|v| { v.unwrap().as_mut_slice()[k] += 1; });
let v = drop_vector.get().unwrap();
v.borrow_mut().as_mut_slice()[k] += 1;
Dropable { k: k }
}
......@@ -1676,23 +1675,23 @@ fn new(k: uint) -> Dropable {
impl Drop for Dropable {
fn drop(&mut self) {
local_data::get_mut(drop_vector, |v|
{ v.unwrap().as_mut_slice()[self.k] -= 1; });
let v = drop_vector.get().unwrap();
v.borrow_mut().as_mut_slice()[self.k] -= 1;
}
}
#[test]
fn test_drops() {
local_data::set(drop_vector, vec::Vec::from_elem(200, 0));
drop_vector.replace(Some(RefCell::new(Vec::from_elem(200, 0))));
{
let mut m = HashMap::new();
local_data::get(drop_vector, |v| {
for i in range(0u, 200) {
assert_eq!(v.unwrap().as_slice()[i], 0);
}
});
let v = drop_vector.get().unwrap();
for i in range(0u, 200) {
assert_eq!(v.borrow().as_slice()[i], 0);
}
drop(v);
for i in range(0u, 100) {
let d1 = Dropable::new(i);
......@@ -1700,11 +1699,11 @@ fn test_drops() {
m.insert(d1, d2);
}
local_data::get(drop_vector, |v| {
for i in range(0u, 200) {
assert_eq!(v.unwrap().as_slice()[i], 1);
}
});
let v = drop_vector.get().unwrap();
for i in range(0u, 200) {
assert_eq!(v.borrow().as_slice()[i], 1);
}
drop(v);
for i in range(0u, 50) {
let k = Dropable::new(i);
......@@ -1712,30 +1711,27 @@ fn test_drops() {
assert!(v.is_some());
local_data::get(drop_vector, |v| {
assert_eq!(v.unwrap().as_slice()[i], 1);
assert_eq!(v.unwrap().as_slice()[i+100], 1);
});
let v = drop_vector.get().unwrap();
assert_eq!(v.borrow().as_slice()[i], 1);
assert_eq!(v.borrow().as_slice()[i+100], 1);
}
local_data::get(drop_vector, |v| {
for i in range(0u, 50) {
assert_eq!(v.unwrap().as_slice()[i], 0);
assert_eq!(v.unwrap().as_slice()[i+100], 0);
}
let v = drop_vector.get().unwrap();
for i in range(0u, 50) {
assert_eq!(v.borrow().as_slice()[i], 0);
assert_eq!(v.borrow().as_slice()[i+100], 0);
}
for i in range(50u, 100) {
assert_eq!(v.unwrap().as_slice()[i], 1);
assert_eq!(v.unwrap().as_slice()[i+100], 1);
}
});
for i in range(50u, 100) {
assert_eq!(v.borrow().as_slice()[i], 1);
assert_eq!(v.borrow().as_slice()[i+100], 1);
}
}
local_data::get(drop_vector, |v| {
for i in range(0u, 200) {
assert_eq!(v.unwrap().as_slice()[i], 0);
}
});
let v = drop_vector.get().unwrap();
for i in range(0u, 200) {
assert_eq!(v.borrow().as_slice()[i], 0);
}
}
#[test]
......
......@@ -122,7 +122,6 @@ fn main() {
use std::fmt;
use std::io::LineBufferedWriter;
use std::io;
use std::local_data;
use std::os;
use std::rt;
use std::slice;
......@@ -228,7 +227,7 @@ pub fn log(level: u32, loc: &'static LogLocation, args: &fmt::Arguments) {
// Completely remove the local logger from TLS in case anyone attempts to
// frob the slot while we're doing the logging. This will destroy any logger
// set during logging.
let mut logger = local_data::pop(local_logger).unwrap_or_else(|| {
let mut logger = local_logger.replace(None).unwrap_or_else(|| {
box DefaultLogger { handle: io::stderr() } as Box<Logger:Send>
});
logger.log(&LogRecord {
......@@ -238,7 +237,7 @@ pub fn log(level: u32, loc: &'static LogLocation, args: &fmt::Arguments) {
module_path: loc.module_path,
line: loc.line,
});
local_data::set(local_logger, logger);
local_logger.replace(Some(logger));
}
/// Getter for the global log level. This is a function so that it can be called
......@@ -250,9 +249,7 @@ pub fn log_level() -> u32 { unsafe { LOG_LEVEL } }
/// Replaces the task-local logger with the specified logger, returning the old
/// logger.
pub fn set_logger(logger: Box<Logger:Send>) -> Option<Box<Logger:Send>> {
let prev = local_data::pop(local_logger);
local_data::set(local_logger, logger);
return prev;
local_logger.replace(Some(logger))
}
/// A LogRecord is created by the logging macros, and passed as the only
......
......@@ -79,7 +79,6 @@
use std::cast;
use std::io::IoResult;
use std::kinds::marker;
use std::local_data;
use std::strbuf::StrBuf;
pub use isaac::{IsaacRng, Isaac64Rng};
......@@ -581,9 +580,6 @@ pub struct TaskRng {
marker: marker::NoSend,
}
// used to make space in TLS for a random number generator
local_data_key!(TASK_RNG_KEY: Box<TaskRngInner>)
/// Retrieve the lazily-initialized task-local random number
/// generator, seeded by the system. Intended to be used in method
/// chaining style, e.g. `task_rng().gen::<int>()`.
......@@ -596,7 +592,10 @@ pub struct TaskRng {
/// the same sequence always. If absolute consistency is required,
/// explicitly select an RNG, e.g. `IsaacRng` or `Isaac64Rng`.
pub fn task_rng() -> TaskRng {
local_data::get_mut(TASK_RNG_KEY, |rng| match rng {
// used to make space in TLS for a random number generator
local_data_key!(TASK_RNG_KEY: Box<TaskRngInner>)
match TASK_RNG_KEY.get() {
None => {
let r = match StdRng::new() {
Ok(r) => r,
......@@ -607,12 +606,15 @@ pub fn task_rng() -> TaskRng {
TaskRngReseeder);
let ptr = &mut *rng as *mut TaskRngInner;
local_data::set(TASK_RNG_KEY, rng);
TASK_RNG_KEY.replace(Some(rng));
TaskRng { rng: ptr, marker: marker::NoSend }
}
Some(rng) => TaskRng { rng: &mut **rng, marker: marker::NoSend }
})
Some(rng) => TaskRng {
rng: &**rng as *_ as *mut TaskRngInner,
marker: marker::NoSend
}
}
}
impl Rng for TaskRng {
......
......@@ -74,7 +74,6 @@
use libc::c_uint;
use std::c_str::ToCStr;
use std::cell::{Cell, RefCell};
use std::local_data;
use std::rc::Rc;
use syntax::abi::{X86, X86_64, Arm, Mips, Rust, RustIntrinsic};
use syntax::ast_util::{local_def, is_local};
......@@ -88,19 +87,17 @@
use time;
local_data_key!(task_local_insn_key: Vec<&'static str> )
local_data_key!(task_local_insn_key: RefCell<Vec<&'static str>>)
pub fn with_insn_ctxt(blk: |&[&'static str]|) {
local_data::get(task_local_insn_key, |c| {
match c {
Some(ctx) => blk(ctx.as_slice()),
None => ()
}
})
match task_local_insn_key.get() {
Some(ctx) => blk(ctx.borrow().as_slice()),
None => ()
}
}
pub fn init_insn_ctxt() {
local_data::set(task_local_insn_key, Vec::new());
task_local_insn_key.replace(Some(RefCell::new(Vec::new())));
}
pub struct _InsnCtxt { _x: () }
......@@ -108,23 +105,19 @@ pub struct _InsnCtxt { _x: () }
#[unsafe_destructor]
impl Drop for _InsnCtxt {
fn drop(&mut self) {
local_data::modify(task_local_insn_key, |c| {
c.map(|mut ctx| {
ctx.pop();
ctx
})
})
match task_local_insn_key.get() {
Some(ctx) => { ctx.borrow_mut().pop(); }
None => {}
}
}
}
pub fn push_ctxt(s: &'static str) -> _InsnCtxt {
debug!("new InsnCtxt: {}", s);
local_data::modify(task_local_insn_key, |c| {
c.map(|mut ctx| {
ctx.push(s);
ctx
})
});
match task_local_insn_key.get() {
Some(ctx) => ctx.borrow_mut().push(s),
None => {}
}
_InsnCtxt { _x: () }
}
......
......@@ -14,23 +14,21 @@
use syntax::visit;
use syntax::visit::Visitor;
use std::local_data;
use time;
pub fn time<T, U>(do_it: bool, what: &str, u: U, f: |U| -> T) -> T {
local_data_key!(depth: uint);
if !do_it { return f(u); }
let old = local_data::get(depth, |d| d.map(|a| *a).unwrap_or(0));
local_data::set(depth, old + 1);
let old = depth.get().map(|d| *d).unwrap_or(0);
depth.replace(Some(old + 1));
let start = time::precise_time_s();
let rv = f(u);
let end = time::precise_time_s();
println!("{}time: {:3.3f} s\t{}", " ".repeat(old), end - start, what);
local_data::set(depth, old);
depth.replace(Some(old));
rv
}
......
......@@ -26,7 +26,6 @@
use rustc::metadata::csearch;
use rustc::metadata::decoder;
use std::local_data;
use std::strbuf::StrBuf;
use core;
......@@ -77,7 +76,7 @@ pub struct Crate {
impl<'a> Clean<Crate> for visit_ast::RustdocVisitor<'a> {
fn clean(&self) -> Crate {
let cx = local_data::get(super::ctxtkey, |x| *x.unwrap());
let cx = super::ctxtkey.get().unwrap();
let mut externs = Vec::new();
cx.sess().cstore.iter_crate_data(|n, meta| {
......@@ -251,7 +250,7 @@ fn clean(&self) -> Item {
// determine if we should display the inner contents or
// the outer `mod` item for the source code.
let where = {
let ctxt = local_data::get(super::ctxtkey, |x| *x.unwrap());
let ctxt = super::ctxtkey.get().unwrap();
let cm = ctxt.sess().codemap();
let outer = cm.lookup_char_pos(self.where_outer.lo);
let inner = cm.lookup_char_pos(self.where_inner.lo);
......@@ -726,7 +725,7 @@ impl Clean<Type> for ast::Ty {
fn clean(&self) -> Type {
use syntax::ast::*;
debug!("cleaning type `{:?}`", self);
let ctxt = local_data::get(super::ctxtkey, |x| *x.unwrap());
let ctxt = super::ctxtkey.get().unwrap();
let codemap = ctxt.sess().codemap();
debug!("span corresponds to `{}`", codemap.span_to_str(self.span));
match self.node {
......@@ -909,7 +908,7 @@ pub struct Span {
impl Clean<Span> for syntax::codemap::Span {
fn clean(&self) -> Span {
let ctxt = local_data::get(super::ctxtkey, |x| *x.unwrap());
let ctxt = super::ctxtkey.get().unwrap();
let cm = ctxt.sess().codemap();
let filename = cm.span_to_filename(*self);
let lo = cm.lookup_char_pos(self.lo);
......@@ -1237,7 +1236,7 @@ trait ToSource {
impl ToSource for syntax::codemap::Span {
fn to_src(&self) -> ~str {
debug!("converting span {:?} to snippet", self.clean());
let ctxt = local_data::get(super::ctxtkey, |x| x.unwrap().clone());
let ctxt = super::ctxtkey.get().unwrap();
let cm = ctxt.sess().codemap().clone();
let sn = match cm.span_to_snippet(*self) {
Some(x) => x,
......@@ -1292,7 +1291,7 @@ fn name_from_pat(p: &ast::Pat) -> ~str {
/// Given a Type, resolve it using the def_map
fn resolve_type(path: Path, tpbs: Option<Vec<TyParamBound> >,
id: ast::NodeId) -> Type {
let cx = local_data::get(super::ctxtkey, |x| *x.unwrap());
let cx = super::ctxtkey.get().unwrap();
let tycx = match cx.maybe_typed {
core::Typed(ref tycx) => tycx,
// If we're extracting tests, this return value doesn't matter.
......@@ -1351,7 +1350,7 @@ fn resolve_use_source(path: Path, id: ast::NodeId) -> ImportSource {
}
fn resolve_def(id: ast::NodeId) -> Option<ast::DefId> {
let cx = local_data::get(super::ctxtkey, |x| *x.unwrap());
let cx = super::ctxtkey.get().unwrap();
match cx.maybe_typed {
core::Typed(ref tcx) => {
tcx.def_map.borrow().find(&id).map(|&d| ast_util::def_id_of_def(d))
......
......@@ -20,7 +20,6 @@
use std::cell::RefCell;
use std::os;
use std::local_data;
use collections::HashSet;
use visit_ast::RustdocVisitor;
......@@ -109,7 +108,7 @@ pub fn run_core(libs: HashSet<Path>, cfgs: Vec<~str>, path: &Path)
-> (clean::Crate, CrateAnalysis) {
let (ctxt, analysis) = get_ast_and_resolve(path, libs, cfgs);
let ctxt = @ctxt;
local_data::set(super::ctxtkey, ctxt);
super::ctxtkey.replace(Some(ctxt));
let krate = {
let mut v = RustdocVisitor::new(ctxt, Some(&analysis));
......
......@@ -17,7 +17,6 @@
use std::fmt;
use std::io;
use std::local_data;
use std::strbuf::StrBuf;
use syntax::ast;
......@@ -206,78 +205,72 @@ fn path(w: &mut io::Writer, path: &clean::Path, print_all: bool,
generics.push_str("&gt;");
}
// Did someone say rightward-drift?
local_data::get(current_location_key, |loc| {
let loc = loc.unwrap();
local_data::get(cache_key, |cache| {
let cache = cache.unwrap();
let abs_root = root(&**cache, loc.as_slice());
let rel_root = match path.segments.get(0).name.as_slice() {
"self" => Some("./".to_owned()),
_ => None,
};
if print_all {
let amt = path.segments.len() - 1;
match rel_root {
Some(root) => {
let mut root = StrBuf::from_str(root);
for seg in path.segments.slice_to(amt).iter() {
if "super" == seg.name || "self" == seg.name {
try!(write!(w, "{}::", seg.name));
} else {
root.push_str(seg.name);
root.push_str("/");
try!(write!(w, "<a class='mod'
href='{}index.html'>{}</a>::",
root.as_slice(),
seg.name));
}
}
}
None => {
for seg in path.segments.slice_to(amt).iter() {
try!(write!(w, "{}::", seg.name));
}
let loc = current_location_key.get().unwrap();
let cache = cache_key.get().unwrap();
let abs_root = root(&**cache, loc.as_slice());
let rel_root = match path.segments.get(0).name.as_slice() {
"self" => Some("./".to_owned()),
_ => None,
};
if print_all {
let amt = path.segments.len() - 1;
match rel_root {
Some(root) => {
let mut root = StrBuf::from_str(root);
for seg in path.segments.slice_to(amt).iter() {
if "super" == seg.name || "self" == seg.name {
try!(write!(w, "{}::", seg.name));
} else {
root.push_str(seg.name);
root.push_str("/");
try!(write!(w, "<a class='mod'
href='{}index.html'>{}</a>::",
root.as_slice(),
seg.name));
}
}
}
match info(&**cache) {
// This is a documented path, link to it!
Some((ref fqp, shortty)) if abs_root.is_some() => {
let mut url = StrBuf::from_str(abs_root.unwrap());
let to_link = fqp.slice_to(fqp.len() - 1);
for component in to_link.iter() {
url.push_str(*component);
url.push_str("/");
}
match shortty {
item_type::Module => {
url.push_str(*fqp.last().unwrap());
url.push_str("/index.html");
}
_ => {
url.push_str(shortty.to_static_str());
url.push_str(".");
url.push_str(*fqp.last().unwrap());
url.push_str(".html");
}
}
try!(write!(w, "<a class='{}' href='{}' title='{}'>{}</a>",
shortty, url, fqp.connect("::"), last.name));
None => {
for seg in path.segments.slice_to(amt).iter() {
try!(write!(w, "{}::", seg.name));
}
}
}
}
match info(&**cache) {
// This is a documented path, link to it!
Some((ref fqp, shortty)) if abs_root.is_some() => {
let mut url = StrBuf::from_str(abs_root.unwrap());
let to_link = fqp.slice_to(fqp.len() - 1);
for component in to_link.iter() {
url.push_str(*component);
url.push_str("/");
}
match shortty {
item_type::Module => {
url.push_str(*fqp.last().unwrap());
url.push_str("/index.html");
}
_ => {
try!(write!(w, "{}", last.name));
url.push_str(shortty.to_static_str());
url.push_str(".");
url.push_str(*fqp.last().unwrap());
url.push_str(".html");
}
}
try!(write!(w, "{}", generics.as_slice()));
Ok(())
})
})
try!(write!(w, "<a class='{}' href='{}' title='{}'>{}</a>",
shortty, url, fqp.connect("::"), last.name));
}
_ => {
try!(write!(w, "{}", last.name));
}
}
try!(write!(w, "{}", generics.as_slice()));
Ok(())
}
/// Helper to render type parameters
......@@ -302,10 +295,8 @@ impl fmt::Show for clean::Type {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
clean::TyParamBinder(id) | clean::Generic(id) => {
local_data::get(cache_key, |cache| {
let m = cache.unwrap();
f.buf.write(m.typarams.get(&id).as_bytes())
})
let m = cache_key.get().unwrap();
f.buf.write(m.typarams.get(&id).as_bytes())
}
clean::ResolvedPath{id, typarams: ref tp, path: ref path} => {
try!(resolved_path(f.buf, id, path, false));
......
......@@ -27,11 +27,11 @@
#![allow(non_camel_case_types)]
use libc;
use std::cell::RefCell;
use std::fmt;
use std::io;
use std::local_data;
use std::str;
use std::slice;
use std::str;
use collections::HashMap;
use html::toc::TocBuilder;
......@@ -139,7 +139,7 @@ fn stripped_filtered_line<'a>(s: &'a str) -> Option<&'a str> {
}
}
local_data_key!(used_header_map: HashMap<~str, uint>)
local_data_key!(used_header_map: RefCell<HashMap<~str, uint>>)
pub fn render(w: &mut io::Writer, s: &str, print_toc: bool) -> fmt::Result {
extern fn block(ob: *mut hoedown_buffer, text: *hoedown_buffer,
......@@ -216,15 +216,12 @@ pub fn render(w: &mut io::Writer, s: &str, print_toc: bool) -> fmt::Result {
let opaque = unsafe { &mut *((*opaque).opaque as *mut MyOpaque) };
// Make sure our hyphenated ID is unique for this page
let id = local_data::get_mut(used_header_map, |map| {
let map = map.unwrap();
match map.find_mut(&id) {
None => {}
Some(a) => { *a += 1; return format!("{}-{}", id, *a - 1) }
}
map.insert(id.clone(), 1);
id.clone()
});
let map = used_header_map.get().unwrap();
let id = match map.borrow_mut().find_mut(&id) {
None => id,
Some(a) => { *a += 1; format!("{}-{}", id, *a - 1) }
};
map.borrow_mut().insert(id.clone(), 1);
let sec = match opaque.toc_builder {
Some(ref mut builder) => {
......@@ -348,7 +345,7 @@ pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector) {
/// used at the beginning of rendering an entire HTML page to reset from the
/// previous state (if any).
pub fn reset_headers() {
local_data::set(used_header_map, HashMap::new())
used_header_map.replace(Some(RefCell::new(HashMap::new())));
}
impl<'a> fmt::Show for Markdown<'a> {
......
......@@ -37,7 +37,6 @@
use std::fmt;
use std::io::{fs, File, BufferedWriter, MemWriter, BufferedReader};
use std::io;
use std::local_data;
use std::str;
use std::strbuf::StrBuf;
......@@ -243,24 +242,22 @@ pub fn run(mut krate: clean::Crate, dst: Path) -> io::IoResult<()> {
}
// Crawl the crate to build various caches used for the output
let mut cache = local_data::get(::analysiskey, |analysis| {
let public_items = analysis.map(|a| a.public_items.clone());
let public_items = public_items.unwrap_or(NodeSet::new());
Cache {
impls: HashMap::new(),
typarams: HashMap::new(),
paths: HashMap::new(),
traits: HashMap::new(),
implementors: HashMap::new(),
stack: Vec::new(),
parent_stack: Vec::new(),
search_index: Vec::new(),
extern_locations: HashMap::new(),
privmod: false,
public_items: public_items,
orphan_methods: Vec::new(),
}
});
let public_items = ::analysiskey.get().map(|a| a.public_items.clone());
let public_items = public_items.unwrap_or(NodeSet::new());
let mut cache = Cache {
impls: HashMap::new(),
typarams: HashMap::new(),
paths: HashMap::new(),
traits: HashMap::new(),
implementors: HashMap::new(),
stack: Vec::new(),
parent_stack: Vec::new(),
search_index: Vec::new(),
extern_locations: HashMap::new(),
privmod: false,
public_items: public_items,
orphan_methods: Vec::new(),
};
cache.stack.push(krate.name.clone());
krate = cache.fold_crate(krate);
......@@ -833,7 +830,7 @@ fn krate(self, mut krate: clean::Crate, cache: Cache) -> io::IoResult<()> {
item.name = Some(krate.name);
// using a rwarc makes this parallelizable in the future
local_data::set(cache_key, Arc::new(cache));
cache_key.replace(Some(Arc::new(cache)));
let mut work = vec!((self, item));
loop {
......@@ -859,7 +856,7 @@ fn render(w: io::File, cx: &mut Context, it: &clean::Item,
info!("Rendering an item to {}", w.path().display());
// A little unfortunate that this is done like this, but it sure
// does make formatting *a lot* nicer.
local_data::set(current_location_key, cx.current.clone());
current_location_key.replace(Some(cx.current.clone()));
let mut title = StrBuf::from_str(cx.current.connect("::"));
if pushname {
......@@ -1299,31 +1296,28 @@ fn meth(w: &mut Writer, m: &clean::TraitMethod) -> fmt::Result {
try!(write!(w, "</div>"));
}
local_data::get(cache_key, |cache| {
let cache = cache.unwrap();
match cache.implementors.find(&it.id) {
Some(implementors) => {
try!(write!(w, "
<h2 id='implementors'>Implementors</h2>
<ul class='item-list'>
"));
for i in implementors.iter() {
match *i {
PathType(ref ty) => {
try!(write!(w, "<li><code>{}</code></li>", *ty));
}
OtherType(ref generics, ref trait_, ref for_) => {
try!(write!(w, "<li><code>impl{} {} for {}</code></li>",
*generics, *trait_, *for_));
}
match cache_key.get().unwrap().implementors.find(&it.id) {
Some(implementors) => {
try!(write!(w, "
<h2 id='implementors'>Implementors</h2>
<ul class='item-list'>
"));
for i in implementors.iter() {
match *i {
PathType(ref ty) => {
try!(write!(w, "<li><code>{}</code></li>", *ty));
}
OtherType(ref generics, ref trait_, ref for_) => {
try!(write!(w, "<li><code>impl{} {} for {}</code></li>",
*generics, *trait_, *for_));
}
}
try!(write!(w, "</ul>"));
}
None => {}
try!(write!(w, "</ul>"));
}
Ok(())
})
None => {}
}
Ok(())
}
fn render_method(w: &mut Writer, meth: &clean::Item) -> fmt::Result {
......@@ -1550,51 +1544,48 @@ fn render_struct(w: &mut Writer, it: &clean::Item,
}
fn render_methods(w: &mut Writer, it: &clean::Item) -> fmt::Result {
local_data::get(cache_key, |cache| {
let c = cache.unwrap();
match c.impls.find(&it.id) {
Some(v) => {
let mut non_trait = v.iter().filter(|p| {
p.ref0().trait_.is_none()
});
let non_trait = non_trait.collect::<Vec<&(clean::Impl, Option<~str>)>>();
let mut traits = v.iter().filter(|p| {
p.ref0().trait_.is_some()
});
let traits = traits.collect::<Vec<&(clean::Impl, Option<~str>)>>();
if non_trait.len() > 0 {
try!(write!(w, "<h2 id='methods'>Methods</h2>"));
for &(ref i, ref dox) in non_trait.move_iter() {
match cache_key.get().unwrap().impls.find(&it.id) {
Some(v) => {
let mut non_trait = v.iter().filter(|p| {
p.ref0().trait_.is_none()
});
let non_trait = non_trait.collect::<Vec<&(clean::Impl, Option<~str>)>>();
let mut traits = v.iter().filter(|p| {
p.ref0().trait_.is_some()
});
let traits = traits.collect::<Vec<&(clean::Impl, Option<~str>)>>();
if non_trait.len() > 0 {
try!(write!(w, "<h2 id='methods'>Methods</h2>"));
for &(ref i, ref dox) in non_trait.move_iter() {
try!(render_impl(w, i, dox));
}
}
if traits.len() > 0 {
try!(write!(w, "<h2 id='implementations'>Trait \
Implementations</h2>"));
let mut any_derived = false;
for & &(ref i, ref dox) in traits.iter() {
if !i.derived {
try!(render_impl(w, i, dox));
} else {
any_derived = true;
}
}
if traits.len() > 0 {
try!(write!(w, "<h2 id='implementations'>Trait \
Implementations</h2>"));
let mut any_derived = false;
for & &(ref i, ref dox) in traits.iter() {
if !i.derived {
if any_derived {
try!(write!(w, "<h3 id='derived_implementations'>Derived Implementations \
</h3>"));
for &(ref i, ref dox) in traits.move_iter() {
if i.derived {
try!(render_impl(w, i, dox));
} else {
any_derived = true;
}
}
if any_derived {
try!(write!(w, "<h3 id='derived_implementations'>Derived Implementations \
</h3>"));
for &(ref i, ref dox) in traits.move_iter() {
if i.derived {
try!(render_impl(w, i, dox));
}
}
}
}
}
None => {}
}
Ok(())
})
None => {}
}
Ok(())
}
fn render_impl(w: &mut Writer, i: &clean::Impl,
......@@ -1644,9 +1635,8 @@ fn docmeth(w: &mut Writer, item: &clean::Item,
match trait_id {
None => {}
Some(id) => {
try!(local_data::get(cache_key, |cache| {
let cache = cache.unwrap();
match cache.traits.find(&id) {
try!({
match cache_key.get().unwrap().traits.find(&id) {
Some(t) => {
for method in t.methods.iter() {
let n = method.item().name.clone();
......@@ -1661,7 +1651,7 @@ fn docmeth(w: &mut Writer, item: &clean::Item,
None => {}
}
Ok(())
}))
})
}
}
try!(write!(w, "</div>"));
......
......@@ -28,7 +28,6 @@
extern crate log;
extern crate libc;
use std::local_data;
use std::io;
use std::io::{File, MemWriter};
use std::str;
......@@ -276,7 +275,7 @@ fn rust_input(cratefile: &str, matches: &getopts::Matches) -> Output {
&cr)
}).unwrap();
info!("finished with rustc");
local_data::set(analysiskey, analysis);
analysiskey.replace(Some(analysis));
// Process all of the crate attributes, extracting plugin metadata along
// with the passes which we are supposed to run.
......
......@@ -11,7 +11,6 @@
use collections::HashSet;
use rustc::util::nodemap::NodeSet;
use std::cmp;
use std::local_data;
use std::strbuf::StrBuf;
use std::uint;
use syntax::ast;
......@@ -86,13 +85,11 @@ fn fold_item(&mut self, i: Item) -> Option<Item> {
/// Strip private items from the point of view of a crate or externally from a
/// crate, specified by the `xcrate` flag.
pub fn strip_private(krate: clean::Crate) -> plugins::PluginResult {
pub fn strip_private(mut krate: clean::Crate) -> plugins::PluginResult {
// This stripper collects all *retained* nodes.
let mut retained = HashSet::new();
let exported_items = local_data::get(super::analysiskey, |analysis| {
analysis.unwrap().exported_items.clone()
});
let mut krate = krate;
let analysis = super::analysiskey.get().unwrap();
let exported_items = analysis.exported_items.clone();
// strip all private items
{
......
......@@ -12,7 +12,6 @@
use std::char;
use std::io;
use std::io::{Process, TempDir};
use std::local_data;
use std::os;
use std::str;
use std::strbuf::StrBuf;
......@@ -75,7 +74,7 @@ pub fn run(input: &str,
maybe_typed: core::NotTyped(sess),
src: input_path,
};
local_data::set(super::ctxtkey, ctx);
super::ctxtkey.replace(Some(ctx));
let mut v = RustdocVisitor::new(ctx, None);
v.visit(&ctx.krate);
......
此差异已折叠。
......@@ -289,12 +289,10 @@ fn run_fmt(fmt: &::std::fmt::Arguments) -> ! {
/// # Example
///
/// ```
/// use std::local_data;
///
/// local_data_key!(my_integer: int)
///
/// local_data::set(my_integer, 2);
/// local_data::get(my_integer, |val| println!("{}", val.map(|i| *i)));
/// my_integer.replace(Some(2));
/// println!("{}", my_integer.get().map(|a| *a));
/// ```
#[macro_export]
macro_rules! local_data_key(
......
......@@ -420,13 +420,12 @@ fn local_heap() {
#[test]
fn tls() {
use local_data;
local_data_key!(key: @~str)
local_data::set(key, @"data".to_owned());
assert!(*local_data::get(key, |k| k.map(|k| *k)).unwrap() == "data".to_owned());
key.replace(Some(@"data".to_owned()));
assert_eq!(key.get().unwrap().as_slice(), "data");
local_data_key!(key2: @~str)
local_data::set(key2, @"data".to_owned());
assert!(*local_data::get(key2, |k| k.map(|k| *k)).unwrap() == "data".to_owned());
key2.replace(Some(@"data".to_owned()));
assert_eq!(key2.get().unwrap().as_slice(), "data");
}
#[test]
......
......@@ -18,7 +18,6 @@
use ast::{Ident, Mrk, Name, SyntaxContext};
use std::cell::RefCell;
use std::local_data;
use std::rc::Rc;
use collections::HashMap;
......@@ -91,17 +90,14 @@ fn new_rename_internal(id: Ident,
pub fn with_sctable<T>(op: |&SCTable| -> T) -> T {
local_data_key!(sctable_key: Rc<SCTable>)
local_data::get(sctable_key, |opt_ts| {
let table = match opt_ts {
None => {
let ts = Rc::new(new_sctable_internal());
local_data::set(sctable_key, ts.clone());
ts
}
Some(ts) => ts.clone()
};
op(&*table)
})
match sctable_key.get() {
Some(ts) => op(&**ts),
None => {
let ts = Rc::new(new_sctable_internal());
sctable_key.replace(Some(ts.clone()));
op(&*ts)
}
}
}
// Make a fresh syntax context table with EmptyCtxt in slot zero
......@@ -154,17 +150,14 @@ pub fn resolve(id: Ident) -> Name {
fn with_resolve_table_mut<T>(op: |&mut ResolveTable| -> T) -> T {
local_data_key!(resolve_table_key: Rc<RefCell<ResolveTable>>)
local_data::get(resolve_table_key, |opt_ts| {
let table = match opt_ts {
None => {
let ts = Rc::new(RefCell::new(HashMap::new()));
local_data::set(resolve_table_key, ts.clone());
ts
}
Some(ts) => ts.clone()
};
op(&mut *table.borrow_mut())
})
match resolve_table_key.get() {
Some(ts) => op(&mut *ts.borrow_mut()),
None => {
let ts = Rc::new(RefCell::new(HashMap::new()));
resolve_table_key.replace(Some(ts.clone()));
op(&mut *ts.borrow_mut())
}
}
}
// Resolve a syntax object to a name, per MTWT.
......
......@@ -19,7 +19,6 @@
use serialize::{Decodable, Decoder, Encodable, Encoder};
use std::cast;
use std::fmt;
use std::local_data;
use std::path::BytesContainer;
use std::rc::Rc;
use std::strbuf::StrBuf;
......@@ -529,11 +528,11 @@ pub fn token_to_binop(tok: &Token) -> Option<ast::BinOp> {
// FIXME(eddyb) #8726 This should probably use a task-local reference.
pub fn get_ident_interner() -> Rc<IdentInterner> {
local_data_key!(key: Rc<::parse::token::IdentInterner>)
match local_data::get(key, |k| k.map(|k| k.clone())) {
Some(interner) => interner,
match key.get() {
Some(interner) => interner.clone(),
None => {
let interner = Rc::new(mk_fresh_ident_interner());
local_data::set(key, interner.clone());
key.replace(Some(interner.clone()));
interner
}
}
......
......@@ -15,7 +15,6 @@
extern crate syntax;
use std::any::Any;
use std::local_data;
use syntax::ast::Name;
use syntax::ext::base::SyntaxExtension;
......@@ -30,6 +29,6 @@ fn drop(&mut self) {}
#[macro_registrar]
pub fn registrar(_: |Name, SyntaxExtension|) {
local_data_key!(foo: Box<Any:Send>);
local_data::set(foo, box Foo { foo: 10 } as Box<Any:Send>);
foo.replace(Some(box Foo { foo: 10 } as Box<Any:Send>));
}
......@@ -10,8 +10,6 @@
// Testing that we can't store a reference it task-local storage
use std::local_data;
local_data_key!(key: @&int)
//~^ ERROR missing lifetime specifier
......
......@@ -8,8 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::local_data;
// check that the local data keys are private by default.
mod bar {
......@@ -17,6 +15,6 @@ mod bar {
}
fn main() {
local_data::set(bar::baz, -10.0);
bar::baz.replace(Some(-10.0));
//~^ ERROR static `baz` is private
}
......@@ -8,8 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::local_data;
local_data_key!(foo: int)
mod bar {
......@@ -17,12 +15,12 @@ mod bar {
}
pub fn main() {
local_data::get(foo, |x| assert!(x.is_none()));
local_data::get(bar::baz, |y| assert!(y.is_none()));
assert!(foo.get().is_none());
assert!(bar::baz.get().is_none());
local_data::set(foo, 3);
local_data::set(bar::baz, -10.0);
foo.replace(Some(3));
bar::baz.replace(Some(-10.0));
local_data::get(foo, |x| assert_eq!(*x.unwrap(), 3));
local_data::get(bar::baz, |y| assert_eq!(*y.unwrap(), -10.0));
assert_eq!(*foo.get().unwrap(), 3);
assert_eq!(*bar::baz.get().unwrap(), -10.0);
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册