about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2016-03-24 13:19:36 -0400
committerNiko Matsakis <niko@alum.mit.edu>2016-03-25 14:07:20 -0400
commit87debd93285e5527d17ed89ba6930fec5fd3f263 (patch)
treee8f430b22085fb691067af83e623765e657d3064
parent814477a8935bb2ee666cc74f861e21cd4d1fa57a (diff)
downloadrust-87debd93285e5527d17ed89ba6930fec5fd3f263.tar.gz
rust-87debd93285e5527d17ed89ba6930fec5fd3f263.zip
include the immediate type in the symbol name hash
the intention is to give some simple protection like link-guards
but not impede ability to upgrade dylib in place
-rw-r--r--src/librustc_trans/back/symbol_names.rs55
1 files changed, 52 insertions, 3 deletions
diff --git a/src/librustc_trans/back/symbol_names.rs b/src/librustc_trans/back/symbol_names.rs
index 81b00c3827f..13a82c0baaa 100644
--- a/src/librustc_trans/back/symbol_names.rs
+++ b/src/librustc_trans/back/symbol_names.rs
@@ -104,7 +104,7 @@ use rustc::middle::cstore;
 use rustc::middle::def_id::DefId;
 use rustc::middle::ty::{self, TypeFoldable};
 use rustc::middle::ty::item_path::{ItemPathBuffer, RootMode};
-use rustc::front::map::definitions::DefPath;
+use rustc::front::map::definitions::{DefPath, DefPathData};
 
 use std::fmt::Write;
 use syntax::parse::token::{self, InternedString};
@@ -134,7 +134,18 @@ pub fn def_path_to_string<'tcx>(tcx: &ty::TyCtxt<'tcx>, def_path: &DefPath) -> S
 }
 
 fn get_symbol_hash<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
+
+                             // path to the item this name is for
                              def_path: &DefPath,
+
+                             // type of the item, without any generic
+                             // parameters substituted; this is
+                             // included in the hash as a kind of
+                             // safeguard.
+                             item_type: ty::Ty<'tcx>,
+
+                             // values for generic type parameters,
+                             // if any.
                              parameters: &[ty::Ty<'tcx>])
                              -> String {
     debug!("get_symbol_hash(def_path={:?}, parameters={:?})",
@@ -151,6 +162,13 @@ fn get_symbol_hash<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     // truly unique path
     hash_state.input_str(&def_path_to_string(tcx, def_path));
 
+    // Include the main item-type. Note that, in this case, the
+    // assertions about `needs_subst` may not hold, but this item-type
+    // ought to be the same for every reference anyway.
+    assert!(!item_type.has_erasable_regions());
+    let encoded_item_type = tcx.sess.cstore.encode_type(tcx, item_type, def_id_to_string);
+    hash_state.input(&encoded_item_type[..]);
+
     // also include any type parameters (for generic items)
     for t in parameters {
        assert!(!t.has_erasable_regions());
@@ -185,7 +203,38 @@ fn exported_name_with_opt_suffix<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
 
     let def_path = ccx.tcx().def_path(def_id);
     assert_eq!(def_path.krate, def_id.krate);
-    let hash = get_symbol_hash(ccx, &def_path, parameters.as_slice());
+
+    // We want to compute the "type" of this item. Unfortunately, some
+    // kinds of items (e.g., closures) don't have an entry in the
+    // item-type array. So walk back up the find the closest parent
+    // that DOES have an entry.
+    let mut ty_def_id = def_id;
+    let instance_ty;
+    loop {
+        let key = ccx.tcx().def_key(ty_def_id);
+        match key.disambiguated_data.data {
+            DefPathData::TypeNs(_) |
+            DefPathData::ValueNs(_) => {
+                instance_ty = ccx.tcx().lookup_item_type(ty_def_id);
+                break;
+            }
+            _ => {
+                // if we're making a symbol for something, there ought
+                // to be a value or type-def or something in there
+                // *somewhere*
+                ty_def_id.index = key.parent.unwrap_or_else(|| {
+                    panic!("finding type for {:?}, encountered def-id {:?} with no \
+                            parent", def_id, ty_def_id);
+                });
+            }
+        }
+    }
+
+    // Erase regions because they may not be deterministic when hashed
+    // and should not matter anyhow.
+    let instance_ty = ccx.tcx().erase_regions(&instance_ty.ty);
+
+    let hash = get_symbol_hash(ccx, &def_path, instance_ty, parameters.as_slice());
 
     let mut buffer = SymbolPathBuffer {
         names: Vec::with_capacity(def_path.data.len())
@@ -239,7 +288,7 @@ pub fn internal_name_from_type_and_suffix<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>
         data: vec![],
         krate: cstore::LOCAL_CRATE,
     };
-    let hash = get_symbol_hash(ccx, &def_path, &[t]);
+    let hash = get_symbol_hash(ccx, &def_path, t, &[]);
     mangle(path.iter().cloned(), Some(&hash[..]))
 }