]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc/middle/typeck/mod.rs
use TotalEq for HashMap
[rust.git] / src / librustc / middle / typeck / mod.rs
index d4e2660b4a01a92e8a5b844f18cd5dff077c9b10..67db5b7f39620f12c220e1b3478d384bb4a70cca 100644 (file)
 use util::common::time;
 use util::ppaux::Repr;
 use util::ppaux;
+use util::nodemap::{DefIdMap, FnvHashMap};
 
 use std::cell::RefCell;
-use collections::HashMap;
 use std::rc::Rc;
 use collections::List;
-use collections::list;
 use syntax::codemap::Span;
 use syntax::print::pprust::*;
 use syntax::{ast, ast_map, abi};
@@ -93,22 +92,22 @@ pub enum param_index {
 }
 
 #[deriving(Clone, Encodable, Decodable)]
-pub enum method_origin {
+pub enum MethodOrigin {
     // fully statically resolved method
-    method_static(ast::DefId),
+    MethodStatic(ast::DefId),
 
     // method invoked on a type parameter with a bounded trait
-    method_param(method_param),
+    MethodParam(MethodParam),
 
     // method invoked on a trait instance
-    method_object(method_object),
+    MethodObject(MethodObject),
 
 }
 
 // details for a method invoked with a receiver whose type is a type parameter
 // with a bounded trait.
 #[deriving(Clone, Encodable, Decodable)]
-pub struct method_param {
+pub struct MethodParam {
     // the trait containing the method to be invoked
     trait_id: ast::DefId,
 
@@ -125,7 +124,7 @@ pub struct method_param {
 
 // details for a method invoked with a receiver whose type is an object
 #[deriving(Clone, Encodable, Decodable)]
-pub struct method_object {
+pub struct MethodObject {
     // the (super)trait containing the method to be invoked
     trait_id: ast::DefId,
 
@@ -142,13 +141,42 @@ pub struct method_object {
     real_index: uint,
 }
 
+#[deriving(Clone)]
+pub struct MethodCallee {
+    origin: MethodOrigin,
+    ty: ty::t,
+    substs: ty::substs
+}
+
+#[deriving(Clone, Eq, TotalEq, Hash, Show)]
+pub struct MethodCall {
+    expr_id: ast::NodeId,
+    autoderef: u32
+}
+
+impl MethodCall {
+    pub fn expr(id: ast::NodeId) -> MethodCall {
+        MethodCall {
+            expr_id: id,
+            autoderef: 0
+        }
+    }
+
+    pub fn autoderef(expr_id: ast::NodeId, autoderef: u32) -> MethodCall {
+        MethodCall {
+            expr_id: expr_id,
+            autoderef: 1 + autoderef
+        }
+    }
+}
+
 // maps from an expression id that corresponds to a method call to the details
 // of the method to be invoked
-pub type method_map = @RefCell<HashMap<ast::NodeId, method_origin>>;
+pub type MethodMap = @RefCell<FnvHashMap<MethodCall, MethodCallee>>;
 
-pub type vtable_param_res = @~[vtable_origin];
+pub type vtable_param_res = @Vec<vtable_origin> ;
 // Resolutions for bounds of all parameters, left to right, for a given path.
-pub type vtable_res = @~[vtable_param_res];
+pub type vtable_res = @Vec<vtable_param_res> ;
 
 #[deriving(Clone)]
 pub enum vtable_origin {
@@ -157,7 +185,7 @@ pub enum vtable_origin {
       from whence comes the vtable, and tys are the type substs.
       vtable_res is the vtable itself
      */
-    vtable_static(ast::DefId, ~[ty::t], vtable_res),
+    vtable_static(ast::DefId, Vec<ty::t> , vtable_res),
 
     /*
       Dynamic vtable, comes from a parameter that has a bound on it:
@@ -171,7 +199,7 @@ fn foo<T:quux,baz,bar>(a: T) -- a's vtable would have a
 }
 
 impl Repr for vtable_origin {
-    fn repr(&self, tcx: ty::ctxt) -> ~str {
+    fn repr(&self, tcx: &ty::ctxt) -> ~str {
         match *self {
             vtable_static(def_id, ref tys, ref vtable_res) => {
                 format!("vtable_static({:?}:{}, {}, {})",
@@ -188,10 +216,10 @@ fn repr(&self, tcx: ty::ctxt) -> ~str {
     }
 }
 
-pub type vtable_map = @RefCell<HashMap<ast::NodeId, vtable_res>>;
+pub type vtable_map = @RefCell<FnvHashMap<MethodCall, vtable_res>>;
 
 
-// Information about the vtable resolutions for for a trait impl.
+// Information about the vtable resolutions for a trait impl.
 // Mostly the information is important for implementing default
 // methods.
 #[deriving(Clone)]
@@ -203,43 +231,41 @@ pub struct impl_res {
 }
 
 impl Repr for impl_res {
-    fn repr(&self, tcx: ty::ctxt) -> ~str {
+    fn repr(&self, tcx: &ty::ctxt) -> ~str {
         format!("impl_res \\{trait_vtables={}, self_vtables={}\\}",
              self.trait_vtables.repr(tcx),
              self.self_vtables.repr(tcx))
     }
 }
 
-pub type impl_vtable_map = RefCell<HashMap<ast::DefId, impl_res>>;
+pub type impl_vtable_map = RefCell<DefIdMap<impl_res>>;
 
-pub struct CrateCtxt {
+pub struct CrateCtxt<'a> {
     // A mapping from method call sites to traits that have that method.
     trait_map: resolve::TraitMap,
-    method_map: method_map,
+    method_map: MethodMap,
     vtable_map: vtable_map,
-    tcx: ty::ctxt
+    tcx: &'a ty::ctxt
 }
 
 // Functions that write types into the node type table
-pub fn write_ty_to_tcx(tcx: ty::ctxt, node_id: ast::NodeId, ty: ty::t) {
+pub fn write_ty_to_tcx(tcx: &ty::ctxt, node_id: ast::NodeId, ty: ty::t) {
     debug!("write_ty_to_tcx({}, {})", node_id, ppaux::ty_to_str(tcx, ty));
     assert!(!ty::type_needs_infer(ty));
-    let mut node_types = tcx.node_types.borrow_mut();
-    node_types.get().insert(node_id as uint, ty);
+    tcx.node_types.borrow_mut().insert(node_id as uint, ty);
 }
-pub fn write_substs_to_tcx(tcx: ty::ctxt,
+pub fn write_substs_to_tcx(tcx: &ty::ctxt,
                            node_id: ast::NodeId,
-                           substs: ~[ty::t]) {
+                           substs: Vec<ty::t> ) {
     if substs.len() > 0u {
         debug!("write_substs_to_tcx({}, {:?})", node_id,
                substs.map(|t| ppaux::ty_to_str(tcx, *t)));
         assert!(substs.iter().all(|t| !ty::type_needs_infer(*t)));
 
-        let mut node_type_substs = tcx.node_type_substs.borrow_mut();
-        node_type_substs.get().insert(node_id, substs);
+        tcx.node_type_substs.borrow_mut().insert(node_id, substs);
     }
 }
-pub fn write_tpt_to_tcx(tcx: ty::ctxt,
+pub fn write_tpt_to_tcx(tcx: &ty::ctxt,
                         node_id: ast::NodeId,
                         tpt: &ty::ty_param_substs_and_ty) {
     write_ty_to_tcx(tcx, node_id, tpt.ty);
@@ -248,9 +274,8 @@ pub fn write_tpt_to_tcx(tcx: ty::ctxt,
     }
 }
 
-pub fn lookup_def_tcx(tcx: ty::ctxt, sp: Span, id: ast::NodeId) -> ast::Def {
-    let def_map = tcx.def_map.borrow();
-    match def_map.get().find(&id) {
+pub fn lookup_def_tcx(tcx:&ty::ctxt, sp: Span, id: ast::NodeId) -> ast::Def {
+    match tcx.def_map.borrow().find(&id) {
         Some(&x) => x,
         _ => {
             tcx.sess.span_fatal(sp, "internal error looking up a definition")
@@ -265,13 +290,13 @@ pub fn lookup_def_ccx(ccx: &CrateCtxt, sp: Span, id: ast::NodeId)
 
 pub fn no_params(t: ty::t) -> ty::ty_param_bounds_and_ty {
     ty::ty_param_bounds_and_ty {
-        generics: ty::Generics {type_param_defs: Rc::new(~[]),
-                                region_param_defs: Rc::new(~[])},
+        generics: ty::Generics {type_param_defs: Rc::new(Vec::new()),
+                                region_param_defs: Rc::new(Vec::new())},
         ty: t
     }
 }
 
-pub fn require_same_types(tcx: ty::ctxt,
+pub fn require_same_types(tcx: &ty::ctxt,
                           maybe_infcx: Option<&infer::InferCtxt>,
                           t1_is_expected: bool,
                           span: Span,
@@ -304,23 +329,18 @@ pub fn require_same_types(tcx: ty::ctxt,
 // corresponding ty::Region
 pub type isr_alist = @List<(ty::BoundRegion, ty::Region)>;
 
-trait get_and_find_region {
-    fn get(&self, br: ty::BoundRegion) -> ty::Region;
-    fn find(&self, br: ty::BoundRegion) -> Option<ty::Region>;
+trait get_region<'a, T:'static> {
+    fn get(&'a self, br: ty::BoundRegion) -> ty::Region;
 }
 
-impl get_and_find_region for isr_alist {
-    fn get(&self, br: ty::BoundRegion) -> ty::Region {
-        self.find(br).unwrap()
-    }
-
-    fn find(&self, br: ty::BoundRegion) -> Option<ty::Region> {
-        let mut ret = None;
-        list::each(*self, |isr| {
+impl<'a, T:'static> get_region <'a, T> for isr_alist {
+    fn get(&'a self, br: ty::BoundRegion) -> ty::Region {
+        let mut region = None;
+        for isr in self.iter() {
             let (isr_br, isr_r) = *isr;
-            if isr_br == br { ret = Some(isr_r); false } else { true }
-        });
-        ret
+            if isr_br == br { region = Some(isr_r); break; }
+        };
+        region.unwrap()
     }
 }
 
@@ -351,7 +371,7 @@ fn check_main_fn_ty(ccx: &CrateCtxt,
                 abis: abi::AbiSet::Rust(),
                 sig: ty::FnSig {
                     binder_id: main_id,
-                    inputs: ~[],
+                    inputs: Vec::new(),
                     output: ty::mk_nil(),
                     variadic: false
                 }
@@ -397,10 +417,10 @@ fn check_start_fn_ty(ccx: &CrateCtxt,
                 abis: abi::AbiSet::Rust(),
                 sig: ty::FnSig {
                     binder_id: start_id,
-                    inputs: ~[
+                    inputs: vec!(
                         ty::mk_int(),
                         ty::mk_imm_ptr(tcx, ty::mk_imm_ptr(tcx, ty::mk_u8()))
-                    ],
+                    ),
                     output: ty::mk_int(),
                     variadic: false
                 }
@@ -433,20 +453,20 @@ fn check_for_entry_fn(ccx: &CrateCtxt) {
     }
 }
 
-pub fn check_crate(tcx: ty::ctxt,
+pub fn check_crate(tcx: &ty::ctxt,
                    trait_map: resolve::TraitMap,
                    krate: &ast::Crate)
-                -> (method_map, vtable_map) {
+                -> (MethodMap, vtable_map) {
     let time_passes = tcx.sess.time_passes();
-    let ccx = @CrateCtxt {
+    let ccx = CrateCtxt {
         trait_map: trait_map,
-        method_map: @RefCell::new(HashMap::new()),
-        vtable_map: @RefCell::new(HashMap::new()),
+        method_map: @RefCell::new(FnvHashMap::new()),
+        vtable_map: @RefCell::new(FnvHashMap::new()),
         tcx: tcx
     };
 
     time(time_passes, "type collecting", (), |_|
-        collect::collect_item_types(ccx, krate));
+        collect::collect_item_types(&ccx, krate));
 
     // this ensures that later parts of type checking can assume that items
     // have valid types and not error
@@ -456,12 +476,12 @@ pub fn check_crate(tcx: ty::ctxt,
          variance::infer_variance(tcx, krate));
 
     time(time_passes, "coherence checking", (), |_|
-        coherence::check_coherence(ccx, krate));
+        coherence::check_coherence(&ccx, krate));
 
     time(time_passes, "type checking", (), |_|
-        check::check_item_types(ccx, krate));
+        check::check_item_types(&ccx, krate));
 
-    check_for_entry_fn(ccx);
+    check_for_entry_fn(&ccx);
     tcx.sess.abort_if_errors();
     (ccx.method_map, ccx.vtable_map)
 }