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
This commit is contained in:
Niko Matsakis 2016-03-24 13:19:36 -04:00
parent 814477a893
commit 87debd9328
1 changed files with 52 additions and 3 deletions

View File

@ -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[..]))
}