syntax: Conditionally deriving(Hash) with Writers
If #[feature(default_type_parameters)] is enabled for a crate, then deriving(Hash) will expand with Hash<W: Writer> instead of Hash<SipState> so more hash algorithms can be used.
This commit is contained in:
parent
bec7b766fb
commit
0a84132928
9 changed files with 128 additions and 97 deletions
|
@ -224,8 +224,12 @@ pub fn phase_2_configure_and_expand(sess: Session,
|
||||||
front::config::strip_unconfigured_items(krate));
|
front::config::strip_unconfigured_items(krate));
|
||||||
|
|
||||||
krate = time(time_passes, "expansion", krate, |krate| {
|
krate = time(time_passes, "expansion", krate, |krate| {
|
||||||
|
let cfg = syntax::ext::expand::ExpansionConfig {
|
||||||
|
loader: loader,
|
||||||
|
deriving_hash_type_parameter: sess.features.default_type_params.get()
|
||||||
|
};
|
||||||
syntax::ext::expand::expand_crate(sess.parse_sess,
|
syntax::ext::expand::expand_crate(sess.parse_sess,
|
||||||
loader,
|
cfg,
|
||||||
krate)
|
krate)
|
||||||
});
|
});
|
||||||
// dump the syntax-time crates
|
// dump the syntax-time crates
|
||||||
|
|
|
@ -28,6 +28,7 @@ use syntax::attr;
|
||||||
use syntax::codemap::{DUMMY_SP, Span, ExpnInfo, NameAndSpan, MacroAttribute};
|
use syntax::codemap::{DUMMY_SP, Span, ExpnInfo, NameAndSpan, MacroAttribute};
|
||||||
use syntax::codemap;
|
use syntax::codemap;
|
||||||
use syntax::ext::base::ExtCtxt;
|
use syntax::ext::base::ExtCtxt;
|
||||||
|
use syntax::ext::expand::ExpansionConfig;
|
||||||
use syntax::fold::Folder;
|
use syntax::fold::Folder;
|
||||||
use syntax::fold;
|
use syntax::fold;
|
||||||
use syntax::opt_vec;
|
use syntax::opt_vec;
|
||||||
|
@ -165,7 +166,11 @@ fn generate_test_harness(sess: session::Session, krate: ast::Crate)
|
||||||
let loader = &mut Loader::new(sess);
|
let loader = &mut Loader::new(sess);
|
||||||
let mut cx: TestCtxt = TestCtxt {
|
let mut cx: TestCtxt = TestCtxt {
|
||||||
sess: sess,
|
sess: sess,
|
||||||
ext_cx: ExtCtxt::new(sess.parse_sess, sess.opts.cfg.clone(), loader),
|
ext_cx: ExtCtxt::new(sess.parse_sess, sess.opts.cfg.clone(),
|
||||||
|
ExpansionConfig {
|
||||||
|
loader: loader,
|
||||||
|
deriving_hash_type_parameter: false,
|
||||||
|
}),
|
||||||
path: RefCell::new(~[]),
|
path: RefCell::new(~[]),
|
||||||
testfns: RefCell::new(~[]),
|
testfns: RefCell::new(~[]),
|
||||||
is_test_crate: is_test_crate(&krate),
|
is_test_crate: is_test_crate(&krate),
|
||||||
|
|
|
@ -179,6 +179,13 @@ impl cmp::Eq for intern_key {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(stage0)]
|
||||||
|
impl Hash for intern_key {
|
||||||
|
fn hash(&self, s: &mut sip::SipState) {
|
||||||
|
unsafe { (*self.sty).hash(s) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[cfg(not(stage0))]
|
||||||
impl<W:Writer> Hash<W> for intern_key {
|
impl<W:Writer> Hash<W> for intern_key {
|
||||||
fn hash(&self, s: &mut W) {
|
fn hash(&self, s: &mut W) {
|
||||||
unsafe { (*self.sty).hash(s) }
|
unsafe { (*self.sty).hash(s) }
|
||||||
|
@ -251,6 +258,9 @@ pub struct ctxt_ {
|
||||||
diag: @syntax::diagnostic::SpanHandler,
|
diag: @syntax::diagnostic::SpanHandler,
|
||||||
// Specifically use a speedy hash algorithm for this hash map, it's used
|
// Specifically use a speedy hash algorithm for this hash map, it's used
|
||||||
// quite often.
|
// quite often.
|
||||||
|
#[cfg(stage0)]
|
||||||
|
interner: RefCell<HashMap<intern_key, ~t_box_>>,
|
||||||
|
#[cfg(not(stage0))]
|
||||||
interner: RefCell<HashMap<intern_key, ~t_box_, ::util::nodemap::FnvHasher>>,
|
interner: RefCell<HashMap<intern_key, ~t_box_, ::util::nodemap::FnvHasher>>,
|
||||||
next_id: Cell<uint>,
|
next_id: Cell<uint>,
|
||||||
cstore: @metadata::cstore::CStore,
|
cstore: @metadata::cstore::CStore,
|
||||||
|
@ -1081,12 +1091,19 @@ pub fn mk_ctxt(s: session::Session,
|
||||||
region_maps: middle::region::RegionMaps,
|
region_maps: middle::region::RegionMaps,
|
||||||
lang_items: @middle::lang_items::LanguageItems)
|
lang_items: @middle::lang_items::LanguageItems)
|
||||||
-> ctxt {
|
-> ctxt {
|
||||||
|
#[cfg(stage0)]
|
||||||
|
fn hasher() -> HashMap<intern_key, ~t_box_> {
|
||||||
|
HashMap::new()
|
||||||
|
}
|
||||||
|
#[cfg(not(stage0))]
|
||||||
|
fn hasher() -> HashMap<intern_key, ~t_box_, ::util::nodemap::FnvHasher> {
|
||||||
|
HashMap::with_hasher(::util::nodemap::FnvHasher)
|
||||||
|
}
|
||||||
@ctxt_ {
|
@ctxt_ {
|
||||||
named_region_map: named_region_map,
|
named_region_map: named_region_map,
|
||||||
item_variance_map: RefCell::new(DefIdMap::new()),
|
item_variance_map: RefCell::new(DefIdMap::new()),
|
||||||
diag: s.diagnostic(),
|
diag: s.diagnostic(),
|
||||||
interner: RefCell::new(HashMap::with_hasher(::util::nodemap::FnvHasher)),
|
interner: RefCell::new(hasher()),
|
||||||
next_id: Cell::new(primitives::LAST_PRIMITIVE_ID),
|
next_id: Cell::new(primitives::LAST_PRIMITIVE_ID),
|
||||||
cstore: s.cstore,
|
cstore: s.cstore,
|
||||||
sess: s,
|
sess: s,
|
||||||
|
|
|
@ -15,30 +15,38 @@ use std::hash::{Hasher, Hash};
|
||||||
use std::io;
|
use std::io;
|
||||||
use syntax::ast;
|
use syntax::ast;
|
||||||
|
|
||||||
|
#[cfg(not(stage0))]
|
||||||
pub type NodeMap<T> = HashMap<ast::NodeId, T, FnvHasher>;
|
pub type NodeMap<T> = HashMap<ast::NodeId, T, FnvHasher>;
|
||||||
|
#[cfg(not(stage0))]
|
||||||
pub type DefIdMap<T> = HashMap<ast::DefId, T, FnvHasher>;
|
pub type DefIdMap<T> = HashMap<ast::DefId, T, FnvHasher>;
|
||||||
|
#[cfg(not(stage0))]
|
||||||
pub type NodeSet = HashSet<ast::NodeId, FnvHasher>;
|
pub type NodeSet = HashSet<ast::NodeId, FnvHasher>;
|
||||||
|
#[cfg(not(stage0))]
|
||||||
pub type DefIdSet = HashSet<ast::DefId, FnvHasher>;
|
pub type DefIdSet = HashSet<ast::DefId, FnvHasher>;
|
||||||
|
|
||||||
// Hacks to get good names
|
// Hacks to get good names
|
||||||
|
#[cfg(not(stage0))]
|
||||||
pub mod NodeMap {
|
pub mod NodeMap {
|
||||||
use collections::HashMap;
|
use collections::HashMap;
|
||||||
pub fn new<T>() -> super::NodeMap<T> {
|
pub fn new<T>() -> super::NodeMap<T> {
|
||||||
HashMap::with_hasher(super::FnvHasher)
|
HashMap::with_hasher(super::FnvHasher)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[cfg(not(stage0))]
|
||||||
pub mod NodeSet {
|
pub mod NodeSet {
|
||||||
use collections::HashSet;
|
use collections::HashSet;
|
||||||
pub fn new() -> super::NodeSet {
|
pub fn new() -> super::NodeSet {
|
||||||
HashSet::with_hasher(super::FnvHasher)
|
HashSet::with_hasher(super::FnvHasher)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[cfg(not(stage0))]
|
||||||
pub mod DefIdMap {
|
pub mod DefIdMap {
|
||||||
use collections::HashMap;
|
use collections::HashMap;
|
||||||
pub fn new<T>() -> super::DefIdMap<T> {
|
pub fn new<T>() -> super::DefIdMap<T> {
|
||||||
HashMap::with_hasher(super::FnvHasher)
|
HashMap::with_hasher(super::FnvHasher)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[cfg(not(stage0))]
|
||||||
pub mod DefIdSet {
|
pub mod DefIdSet {
|
||||||
use collections::HashSet;
|
use collections::HashSet;
|
||||||
pub fn new() -> super::DefIdSet {
|
pub fn new() -> super::DefIdSet {
|
||||||
|
@ -46,6 +54,45 @@ pub mod DefIdSet {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(stage0)]
|
||||||
|
pub type NodeMap<T> = HashMap<ast::NodeId, T>;
|
||||||
|
#[cfg(stage0)]
|
||||||
|
pub type DefIdMap<T> = HashMap<ast::DefId, T>;
|
||||||
|
#[cfg(stage0)]
|
||||||
|
pub type NodeSet = HashSet<ast::NodeId>;
|
||||||
|
#[cfg(stage0)]
|
||||||
|
pub type DefIdSet = HashSet<ast::DefId>;
|
||||||
|
|
||||||
|
// Hacks to get good names
|
||||||
|
#[cfg(stage0)]
|
||||||
|
pub mod NodeMap {
|
||||||
|
use collections::HashMap;
|
||||||
|
pub fn new<T>() -> super::NodeMap<T> {
|
||||||
|
HashMap::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[cfg(stage0)]
|
||||||
|
pub mod NodeSet {
|
||||||
|
use collections::HashSet;
|
||||||
|
pub fn new() -> super::NodeSet {
|
||||||
|
HashSet::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[cfg(stage0)]
|
||||||
|
pub mod DefIdMap {
|
||||||
|
use collections::HashMap;
|
||||||
|
pub fn new<T>() -> super::DefIdMap<T> {
|
||||||
|
HashMap::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[cfg(stage0)]
|
||||||
|
pub mod DefIdSet {
|
||||||
|
use collections::HashSet;
|
||||||
|
pub fn new() -> super::DefIdSet {
|
||||||
|
HashSet::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A speedy hash algorithm for node ids and def ids. The hashmap in
|
/// A speedy hash algorithm for node ids and def ids. The hashmap in
|
||||||
/// libcollections by default uses SipHash which isn't quite as speedy as we
|
/// libcollections by default uses SipHash which isn't quite as speedy as we
|
||||||
/// want. In the compiler we're not really worried about DOS attempts, so we
|
/// want. In the compiler we're not really worried about DOS attempts, so we
|
||||||
|
@ -56,7 +103,7 @@ pub mod DefIdSet {
|
||||||
#[deriving(Clone)]
|
#[deriving(Clone)]
|
||||||
pub struct FnvHasher;
|
pub struct FnvHasher;
|
||||||
|
|
||||||
struct FnvState(u64);
|
pub struct FnvState(u64);
|
||||||
|
|
||||||
impl Hasher<FnvState> for FnvHasher {
|
impl Hasher<FnvState> for FnvHasher {
|
||||||
fn hash<T: Hash<FnvState>>(&self, t: &T) -> u64 {
|
fn hash<T: Hash<FnvState>>(&self, t: &T) -> u64 {
|
||||||
|
|
|
@ -283,7 +283,7 @@ pub struct ExtCtxt<'a> {
|
||||||
parse_sess: @parse::ParseSess,
|
parse_sess: @parse::ParseSess,
|
||||||
cfg: ast::CrateConfig,
|
cfg: ast::CrateConfig,
|
||||||
backtrace: Option<@ExpnInfo>,
|
backtrace: Option<@ExpnInfo>,
|
||||||
loader: &'a mut CrateLoader,
|
ecfg: expand::ExpansionConfig<'a>,
|
||||||
|
|
||||||
mod_path: Vec<ast::Ident> ,
|
mod_path: Vec<ast::Ident> ,
|
||||||
trace_mac: bool
|
trace_mac: bool
|
||||||
|
@ -291,13 +291,13 @@ pub struct ExtCtxt<'a> {
|
||||||
|
|
||||||
impl<'a> ExtCtxt<'a> {
|
impl<'a> ExtCtxt<'a> {
|
||||||
pub fn new<'a>(parse_sess: @parse::ParseSess, cfg: ast::CrateConfig,
|
pub fn new<'a>(parse_sess: @parse::ParseSess, cfg: ast::CrateConfig,
|
||||||
loader: &'a mut CrateLoader) -> ExtCtxt<'a> {
|
ecfg: expand::ExpansionConfig<'a>) -> ExtCtxt<'a> {
|
||||||
ExtCtxt {
|
ExtCtxt {
|
||||||
parse_sess: parse_sess,
|
parse_sess: parse_sess,
|
||||||
cfg: cfg,
|
cfg: cfg,
|
||||||
backtrace: None,
|
backtrace: None,
|
||||||
loader: loader,
|
|
||||||
mod_path: Vec::new(),
|
mod_path: Vec::new(),
|
||||||
|
ecfg: ecfg,
|
||||||
trace_mac: false
|
trace_mac: false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,19 +22,31 @@ pub fn expand_deriving_hash(cx: &mut ExtCtxt,
|
||||||
item: @Item,
|
item: @Item,
|
||||||
push: |@Item|) {
|
push: |@Item|) {
|
||||||
|
|
||||||
|
let (path, generics, args) = if cx.ecfg.deriving_hash_type_parameter {
|
||||||
|
(Path::new_(vec!("std", "hash", "Hash"), None,
|
||||||
|
vec!(~Literal(Path::new_local("__H"))), true),
|
||||||
|
LifetimeBounds {
|
||||||
|
lifetimes: Vec::new(),
|
||||||
|
bounds: vec!(("__H", vec!(Path::new(vec!("std", "io", "Writer"))))),
|
||||||
|
},
|
||||||
|
Path::new_local("__H"))
|
||||||
|
} else {
|
||||||
|
(Path::new(vec!("std", "hash", "Hash")),
|
||||||
|
LifetimeBounds::empty(),
|
||||||
|
Path::new(vec!("std", "hash", "sip", "SipState")))
|
||||||
|
};
|
||||||
let hash_trait_def = TraitDef {
|
let hash_trait_def = TraitDef {
|
||||||
span: span,
|
span: span,
|
||||||
attributes: Vec::new(),
|
attributes: Vec::new(),
|
||||||
path: Path::new(vec!("std", "hash", "Hash")),
|
path: path,
|
||||||
additional_bounds: Vec::new(),
|
additional_bounds: Vec::new(),
|
||||||
generics: LifetimeBounds::empty(),
|
generics: generics,
|
||||||
methods: vec!(
|
methods: vec!(
|
||||||
MethodDef {
|
MethodDef {
|
||||||
name: "hash",
|
name: "hash",
|
||||||
generics: LifetimeBounds::empty(),
|
generics: LifetimeBounds::empty(),
|
||||||
explicit_self: borrowed_explicit_self(),
|
explicit_self: borrowed_explicit_self(),
|
||||||
args: vec!(Ptr(~Literal(Path::new(vec!("std", "hash", "sip", "SipState"))),
|
args: vec!(Ptr(~Literal(args), Borrowed(None, MutMutable))),
|
||||||
Borrowed(None, MutMutable))),
|
|
||||||
ret_ty: nil_ty(),
|
ret_ty: nil_ty(),
|
||||||
inline: true,
|
inline: true,
|
||||||
const_nonmatching: false,
|
const_nonmatching: false,
|
||||||
|
|
|
@ -443,7 +443,7 @@ pub fn expand_view_item(vi: &ast::ViewItem,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_extern_macros(krate: &ast::ViewItem, fld: &mut MacroExpander) {
|
fn load_extern_macros(krate: &ast::ViewItem, fld: &mut MacroExpander) {
|
||||||
let MacroCrate { lib, cnum } = fld.cx.loader.load_crate(krate);
|
let MacroCrate { lib, cnum } = fld.cx.ecfg.loader.load_crate(krate);
|
||||||
|
|
||||||
let crate_name = match krate.node {
|
let crate_name = match krate.node {
|
||||||
ast::ViewItemExternMod(name, _, _) => name,
|
ast::ViewItemExternMod(name, _, _) => name,
|
||||||
|
@ -451,7 +451,7 @@ fn load_extern_macros(krate: &ast::ViewItem, fld: &mut MacroExpander) {
|
||||||
};
|
};
|
||||||
let name = format!("<{} macros>", token::get_ident(crate_name));
|
let name = format!("<{} macros>", token::get_ident(crate_name));
|
||||||
|
|
||||||
let exported_macros = fld.cx.loader.get_exported_macros(cnum);
|
let exported_macros = fld.cx.ecfg.loader.get_exported_macros(cnum);
|
||||||
for source in exported_macros.iter() {
|
for source in exported_macros.iter() {
|
||||||
let item = parse::parse_item_from_source_str(name.clone(),
|
let item = parse::parse_item_from_source_str(name.clone(),
|
||||||
(*source).clone(),
|
(*source).clone(),
|
||||||
|
@ -468,7 +468,7 @@ fn load_extern_macros(krate: &ast::ViewItem, fld: &mut MacroExpander) {
|
||||||
// Make sure the path contains a / or the linker will search for it.
|
// Make sure the path contains a / or the linker will search for it.
|
||||||
let path = os::make_absolute(&path);
|
let path = os::make_absolute(&path);
|
||||||
|
|
||||||
let registrar = match fld.cx.loader.get_registrar_symbol(cnum) {
|
let registrar = match fld.cx.ecfg.loader.get_registrar_symbol(cnum) {
|
||||||
Some(registrar) => registrar,
|
Some(registrar) => registrar,
|
||||||
None => return
|
None => return
|
||||||
};
|
};
|
||||||
|
@ -823,10 +823,15 @@ impl<'a> Folder for MacroExpander<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct ExpansionConfig<'a> {
|
||||||
|
loader: &'a mut CrateLoader,
|
||||||
|
deriving_hash_type_parameter: bool,
|
||||||
|
}
|
||||||
|
|
||||||
pub fn expand_crate(parse_sess: @parse::ParseSess,
|
pub fn expand_crate(parse_sess: @parse::ParseSess,
|
||||||
loader: &mut CrateLoader,
|
cfg: ExpansionConfig,
|
||||||
c: Crate) -> Crate {
|
c: Crate) -> Crate {
|
||||||
let mut cx = ExtCtxt::new(parse_sess, c.config.clone(), loader);
|
let mut cx = ExtCtxt::new(parse_sess, c.config.clone(), cfg);
|
||||||
let mut expander = MacroExpander {
|
let mut expander = MacroExpander {
|
||||||
extsbox: syntax_expander_table(),
|
extsbox: syntax_expander_table(),
|
||||||
cx: &mut cx,
|
cx: &mut cx,
|
||||||
|
@ -995,7 +1000,11 @@ mod test {
|
||||||
Vec::new(),sess);
|
Vec::new(),sess);
|
||||||
// should fail:
|
// should fail:
|
||||||
let mut loader = ErrLoader;
|
let mut loader = ErrLoader;
|
||||||
expand_crate(sess,&mut loader,crate_ast);
|
let cfg = ::syntax::ext::expand::ExpansionConfig {
|
||||||
|
loader: &mut loader,
|
||||||
|
deriving_hash_type_parameter: false,
|
||||||
|
};
|
||||||
|
expand_crate(sess,cfg,crate_ast);
|
||||||
}
|
}
|
||||||
|
|
||||||
// make sure that macros can leave scope for modules
|
// make sure that macros can leave scope for modules
|
||||||
|
@ -1010,7 +1019,11 @@ mod test {
|
||||||
Vec::new(),sess);
|
Vec::new(),sess);
|
||||||
// should fail:
|
// should fail:
|
||||||
let mut loader = ErrLoader;
|
let mut loader = ErrLoader;
|
||||||
expand_crate(sess,&mut loader,crate_ast);
|
let cfg = ::syntax::ext::expand::ExpansionConfig {
|
||||||
|
loader: &mut loader,
|
||||||
|
deriving_hash_type_parameter: false,
|
||||||
|
};
|
||||||
|
expand_crate(sess,cfg,crate_ast);
|
||||||
}
|
}
|
||||||
|
|
||||||
// macro_escape modules shouldn't cause macros to leave scope
|
// macro_escape modules shouldn't cause macros to leave scope
|
||||||
|
@ -1024,7 +1037,11 @@ mod test {
|
||||||
Vec::new(), sess);
|
Vec::new(), sess);
|
||||||
// should fail:
|
// should fail:
|
||||||
let mut loader = ErrLoader;
|
let mut loader = ErrLoader;
|
||||||
expand_crate(sess, &mut loader, crate_ast);
|
let cfg = ::syntax::ext::expand::ExpansionConfig {
|
||||||
|
loader: &mut loader,
|
||||||
|
deriving_hash_type_parameter: false,
|
||||||
|
};
|
||||||
|
expand_crate(sess, cfg, crate_ast);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test] fn test_contains_flatten (){
|
#[test] fn test_contains_flatten (){
|
||||||
|
@ -1062,7 +1079,11 @@ mod test {
|
||||||
let (crate_ast,ps) = string_to_crate_and_sess(crate_str);
|
let (crate_ast,ps) = string_to_crate_and_sess(crate_str);
|
||||||
// the cfg argument actually does matter, here...
|
// the cfg argument actually does matter, here...
|
||||||
let mut loader = ErrLoader;
|
let mut loader = ErrLoader;
|
||||||
expand_crate(ps,&mut loader,crate_ast)
|
let cfg = ::syntax::ext::expand::ExpansionConfig {
|
||||||
|
loader: &mut loader,
|
||||||
|
deriving_hash_type_parameter: false,
|
||||||
|
};
|
||||||
|
expand_crate(ps,cfg,crate_ast)
|
||||||
}
|
}
|
||||||
|
|
||||||
//fn expand_and_resolve(crate_str: @str) -> ast::crate {
|
//fn expand_and_resolve(crate_str: @str) -> ast::crate {
|
||||||
|
|
|
@ -26,7 +26,7 @@ This API is completely unstable and subject to change.
|
||||||
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
|
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
|
||||||
html_root_url = "http://static.rust-lang.org/doc/master")];
|
html_root_url = "http://static.rust-lang.org/doc/master")];
|
||||||
|
|
||||||
#[feature(macro_rules, globs, managed_boxes)];
|
#[feature(macro_rules, globs, managed_boxes, default_type_params)];
|
||||||
#[allow(unknown_features)];// Note: remove it after a snapshot.
|
#[allow(unknown_features)];// Note: remove it after a snapshot.
|
||||||
#[feature(quote)];
|
#[feature(quote)];
|
||||||
|
|
||||||
|
|
|
@ -1,75 +0,0 @@
|
||||||
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
|
||||||
// file at the top-level directory of this distribution and at
|
|
||||||
// http://rust-lang.org/COPYRIGHT.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
||||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
||||||
// option. This file may not be copied, modified, or distributed
|
|
||||||
// except according to those terms.
|
|
||||||
|
|
||||||
//! An efficient hash map for node IDs
|
|
||||||
|
|
||||||
use collections::hashmap;
|
|
||||||
use collections::{HashMap, HashSet};
|
|
||||||
use std::hash::{Hasher, Hash};
|
|
||||||
use std::iter;
|
|
||||||
use ast;
|
|
||||||
|
|
||||||
pub type NodeMap<T> = HashMap<ast::NodeId, T, NodeHasher>;
|
|
||||||
pub type DefIdMap<T> = HashMap<ast::DefId, T, NodeHasher>;
|
|
||||||
pub type NodeSet = HashSet<ast::NodeId, NodeHasher>;
|
|
||||||
pub type DefIdSet = HashSet<ast::DefId, NodeHasher>;
|
|
||||||
|
|
||||||
#[deriving(Clone)]
|
|
||||||
struct NodeHasher;
|
|
||||||
|
|
||||||
impl Hasher<u64> for NodeHasher {
|
|
||||||
fn hash<T: Hash<u64>>(&self, t: &T) -> u64 {
|
|
||||||
let mut last = 0;
|
|
||||||
t.hash(&mut last);
|
|
||||||
return last
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Hash<u64> for ast::NodeId {
|
|
||||||
fn hash(&self, state: &mut u64) {
|
|
||||||
*state = self.get() as u64;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Hash<u64> for ast::DefId {
|
|
||||||
fn hash(&self, state: &mut u64) {
|
|
||||||
let ast::DefId { krate, node } = *self;
|
|
||||||
// assert that these two types are each 32 bits
|
|
||||||
let krate: u32 = krate;
|
|
||||||
let node: u32 = node;
|
|
||||||
*state = (krate << 32) as u64 | (node as u64);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Hacks to get good names
|
|
||||||
pub mod NodeMap {
|
|
||||||
use collections::HashMap;
|
|
||||||
pub fn new<T>() -> super::NodeMap<T> {
|
|
||||||
HashMap::with_hasher(super::NodeHasher)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub mod NodeSet {
|
|
||||||
use collections::HashSet;
|
|
||||||
pub fn new() -> super::NodeSet {
|
|
||||||
HashSet::with_hasher(super::NodeHasher)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub mod DefIdMap {
|
|
||||||
use collections::HashMap;
|
|
||||||
pub fn new<T>() -> super::DefIdMap<T> {
|
|
||||||
HashMap::with_hasher(super::NodeHasher)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub mod DefIdSet {
|
|
||||||
use collections::HashSet;
|
|
||||||
pub fn new() -> super::DefIdSet {
|
|
||||||
HashSet::with_hasher(super::NodeHasher)
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Add table
Add a link
Reference in a new issue