提交 a87078a2 编写于 作者: A Ariel Ben-Yehuda

Clean-up transmutes in librustc

None of them would break by implementation-defined struct layout, but
one would break with strict lifetime aliasing, and the rest are just
ugly code.
上级 fbb90c34
......@@ -532,7 +532,7 @@ fn with_lint_attrs(&mut self,
}
}
fn visit_ids(&self, f: |&mut ast_util::IdVisitor<Context>|) {
fn visit_ids(&mut self, f: |&mut ast_util::IdVisitor<Context>|) {
let mut v = ast_util::IdVisitor {
operation: self,
pass_through_items: false,
......@@ -749,7 +749,7 @@ fn visit_attribute(&mut self, attr: &ast::Attribute) {
// Output any lints that were previously added to the session.
impl<'a, 'tcx> IdVisitingOperation for Context<'a, 'tcx> {
fn visit_id(&self, id: ast::NodeId) {
fn visit_id(&mut self, id: ast::NodeId) {
match self.tcx.sess.lints.borrow_mut().pop(&id) {
None => {}
Some(lints) => {
......
......@@ -148,7 +148,7 @@ impl astencode_tag {
pub fn from_uint(value : uint) -> Option<astencode_tag> {
let is_a_tag = first_astencode_tag <= value && value <= last_astencode_tag;
if !is_a_tag { None } else {
Some(unsafe { mem::transmute(value) })
Some(unsafe { mem::transmute::<uint, astencode_tag>(value) })
}
}
}
......@@ -247,4 +247,3 @@ pub struct LinkMeta {
pub const tag_item_generics: uint = 0xa6;
pub const tag_method_ty_generics: uint = 0xa7;
......@@ -29,7 +29,6 @@
use std::cell::RefCell;
use std::hash::Hash;
use std::hash;
use std::mem;
use std::collections::HashMap;
use syntax::abi;
use syntax::ast::*;
......@@ -1508,44 +1507,36 @@ fn my_visit_expr(_e: &Expr) { }
fn my_visit_item(i: &Item,
rbml_w: &mut Encoder,
ecx_ptr: *const int,
ecx: &EncodeContext,
index: &mut Vec<entry<i64>>) {
let mut rbml_w = unsafe { rbml_w.unsafe_clone() };
// See above
let ecx: &EncodeContext = unsafe { mem::transmute(ecx_ptr) };
ecx.tcx.map.with_path(i.id, |path| {
encode_info_for_item(ecx, &mut rbml_w, i, index, path, i.vis);
encode_info_for_item(ecx, rbml_w, i, index, path, i.vis);
});
}
fn my_visit_foreign_item(ni: &ForeignItem,
rbml_w: &mut Encoder,
ecx_ptr:*const int,
ecx: &EncodeContext,
index: &mut Vec<entry<i64>>) {
// See above
let ecx: &EncodeContext = unsafe { mem::transmute(ecx_ptr) };
debug!("writing foreign item {}::{}",
ecx.tcx.map.path_to_string(ni.id),
token::get_ident(ni.ident));
let mut rbml_w = unsafe {
rbml_w.unsafe_clone()
};
let abi = ecx.tcx.map.get_foreign_abi(ni.id);
ecx.tcx.map.with_path(ni.id, |path| {
encode_info_for_foreign_item(ecx, &mut rbml_w,
encode_info_for_foreign_item(ecx, rbml_w,
ni, index,
path, abi);
});
}
struct EncodeVisitor<'a,'b:'a> {
struct EncodeVisitor<'a, 'b:'a, 'c:'a, 'tcx:'c> {
rbml_w_for_visit_item: &'a mut Encoder<'b>,
ecx_ptr:*const int,
ecx: &'a EncodeContext<'c,'tcx>,
index: &'a mut Vec<entry<i64>>,
}
impl<'a, 'b, 'v> Visitor<'v> for EncodeVisitor<'a, 'b> {
impl<'a, 'b, 'c, 'tcx, 'v> Visitor<'v> for EncodeVisitor<'a, 'b, 'c, 'tcx> {
fn visit_expr(&mut self, ex: &Expr) {
visit::walk_expr(self, ex);
my_visit_expr(ex);
......@@ -1554,14 +1545,14 @@ fn visit_item(&mut self, i: &Item) {
visit::walk_item(self, i);
my_visit_item(i,
self.rbml_w_for_visit_item,
self.ecx_ptr,
self.ecx,
self.index);
}
fn visit_foreign_item(&mut self, ni: &ForeignItem) {
visit::walk_foreign_item(self, ni);
my_visit_foreign_item(ni,
self.rbml_w_for_visit_item,
self.ecx_ptr,
self.ecx,
self.index);
}
}
......@@ -1585,11 +1576,9 @@ fn encode_info_for_items(ecx: &EncodeContext,
syntax::parse::token::special_idents::invalid,
Public);
// See comment in `encode_side_tables_for_ii` in astencode
let ecx_ptr: *const int = unsafe { mem::transmute(ecx) };
visit::walk_crate(&mut EncodeVisitor {
index: &mut index,
ecx_ptr: ecx_ptr,
ecx: ecx,
rbml_w_for_visit_item: &mut *rbml_w,
}, krate);
......
......@@ -231,7 +231,6 @@
use std::cmp;
use std::io::fs::PathExtensions;
use std::io;
use std::mem;
use std::ptr;
use std::slice;
use std::string;
......@@ -287,8 +286,8 @@ pub struct Library {
pub struct ArchiveMetadata {
_archive: ArchiveRO,
// See comments in ArchiveMetadata::new for why this is static
data: &'static [u8],
// points into self._archive
data: *const [u8],
}
pub struct CratePaths {
......@@ -709,33 +708,21 @@ pub fn note_crate_name(diag: &SpanHandler, name: &str) {
impl ArchiveMetadata {
fn new(ar: ArchiveRO) -> Option<ArchiveMetadata> {
let data: &'static [u8] = {
let data = match ar.read(METADATA_FILENAME) {
Some(data) => data,
None => {
debug!("didn't find '{}' in the archive", METADATA_FILENAME);
return None;
}
};
// This data is actually a pointer inside of the archive itself, but
// we essentially want to cache it because the lookup inside the
// archive is a fairly expensive operation (and it's queried for
// *very* frequently). For this reason, we transmute it to the
// static lifetime to put into the struct. Note that the buffer is
// never actually handed out with a static lifetime, but rather the
// buffer is loaned with the lifetime of this containing object.
// Hence, we're guaranteed that the buffer will never be used after
// this object is dead, so this is a safe operation to transmute and
// store the data as a static buffer.
unsafe { mem::transmute(data) }
let data = match ar.read(METADATA_FILENAME) {
Some(data) => data as *const [u8],
None => {
debug!("didn't find '{}' in the archive", METADATA_FILENAME);
return None;
}
};
Some(ArchiveMetadata {
_archive: ar,
data: data,
})
}
pub fn as_slice<'a>(&'a self) -> &'a [u8] { self.data }
pub fn as_slice<'a>(&'a self) -> &'a [u8] { unsafe { &*self.data } }
}
// Just a small wrapper to time how long reading metadata takes.
......@@ -798,7 +785,7 @@ fn get_metadata_section_imp(os: abi::Os, filename: &Path) -> Result<MetadataBlob
let csz = llvm::LLVMGetSectionSize(si.llsi) as uint;
let mut found =
Err(format!("metadata not found: '{}'", filename.display()));
let cvbuf: *const u8 = mem::transmute(cbuf);
let cvbuf: *const u8 = cbuf as *const u8;
let vlen = encoder::metadata_encoding_version.len();
debug!("checking {} bytes of metadata-version stamp",
vlen);
......
......@@ -38,9 +38,7 @@
use syntax::ptr::P;
use syntax;
use libc;
use std::io::Seek;
use std::mem;
use std::rc::Rc;
use rbml::io::SeekableMemWriter;
......@@ -1128,27 +1126,15 @@ fn id(&mut self, id: ast::NodeId) {
}
}
struct SideTableEncodingIdVisitor<'a,'b:'a> {
ecx_ptr: *const libc::c_void,
new_rbml_w: &'a mut Encoder<'b>,
struct SideTableEncodingIdVisitor<'a, 'b:'a, 'c:'a, 'tcx:'c> {
ecx: &'a e::EncodeContext<'c, 'tcx>,
rbml_w: &'a mut Encoder<'b>,
}
impl<'a,'b> ast_util::IdVisitingOperation for
SideTableEncodingIdVisitor<'a,'b> {
fn visit_id(&self, id: ast::NodeId) {
// Note: this will cause a copy of rbml_w, which is bad as
// it is mutable. But I believe it's harmless since we generate
// balanced EBML.
//
// FIXME(pcwalton): Don't copy this way.
let mut new_rbml_w = unsafe {
self.new_rbml_w.unsafe_clone()
};
// See above
let ecx: &e::EncodeContext = unsafe {
mem::transmute(self.ecx_ptr)
};
encode_side_tables_for_id(ecx, &mut new_rbml_w, id)
impl<'a, 'b, 'c, 'tcx> ast_util::IdVisitingOperation for
SideTableEncodingIdVisitor<'a, 'b, 'c, 'tcx> {
fn visit_id(&mut self, id: ast::NodeId) {
encode_side_tables_for_id(self.ecx, self.rbml_w, id)
}
}
......@@ -1156,18 +1142,9 @@ fn encode_side_tables_for_ii(ecx: &e::EncodeContext,
rbml_w: &mut Encoder,
ii: &ast::InlinedItem) {
rbml_w.start_tag(c::tag_table as uint);
let mut new_rbml_w = unsafe {
rbml_w.unsafe_clone()
};
// Because the ast visitor uses @IdVisitingOperation, I can't pass in
// ecx directly, but /I/ know that it'll be fine since the lifetime is
// tied to the CrateContext that lives throughout this entire section.
ast_util::visit_ids_for_inlined_item(ii, &SideTableEncodingIdVisitor {
ecx_ptr: unsafe {
mem::transmute(ecx)
},
new_rbml_w: &mut new_rbml_w,
ast_util::visit_ids_for_inlined_item(ii, &mut SideTableEncodingIdVisitor {
ecx: ecx,
rbml_w: rbml_w
});
rbml_w.end_tag();
}
......
......@@ -118,7 +118,6 @@
use std::fmt;
use std::io;
use std::mem::transmute;
use std::rc::Rc;
use std::str;
use std::uint;
......@@ -380,10 +379,7 @@ fn visit_fn(ir: &mut IrMaps,
// swap in a new set of IR maps for this function body:
let mut fn_maps = IrMaps::new(ir.tcx);
unsafe {
debug!("creating fn_maps: {}",
transmute::<&IrMaps, *const IrMaps>(&fn_maps));
}
debug!("creating fn_maps: {}", &fn_maps as *const IrMaps);
for arg in decl.inputs.iter() {
pat_util::pat_bindings(&ir.tcx.def_map,
......
......@@ -16,66 +16,10 @@
use util::ppaux::Repr;
use std::fmt;
use std::mem;
use std::raw;
use std::slice::{Items, MutItems};
use std::slice::Items;
use std::vec::Vec;
use syntax::codemap::{Span, DUMMY_SP};
///////////////////////////////////////////////////////////////////////////
// HomogeneousTuple3 trait
//
// This could be moved into standard library at some point.
trait HomogeneousTuple3<T> {
fn len(&self) -> uint;
fn as_slice<'a>(&'a self) -> &'a [T];
fn as_mut_slice<'a>(&'a mut self) -> &'a mut [T];
fn iter<'a>(&'a self) -> Items<'a, T>;
fn iter_mut<'a>(&'a mut self) -> MutItems<'a, T>;
fn get<'a>(&'a self, index: uint) -> Option<&'a T>;
fn get_mut<'a>(&'a mut self, index: uint) -> Option<&'a mut T>;
}
impl<T> HomogeneousTuple3<T> for (T, T, T) {
fn len(&self) -> uint {
3
}
fn as_slice<'a>(&'a self) -> &'a [T] {
unsafe {
let ptr: *const T = mem::transmute(self);
let slice = raw::Slice { data: ptr, len: 3 };
mem::transmute(slice)
}
}
fn as_mut_slice<'a>(&'a mut self) -> &'a mut [T] {
unsafe {
let ptr: *const T = mem::transmute(self);
let slice = raw::Slice { data: ptr, len: 3 };
mem::transmute(slice)
}
}
fn iter<'a>(&'a self) -> Items<'a, T> {
let slice: &'a [T] = self.as_slice();
slice.iter()
}
fn iter_mut<'a>(&'a mut self) -> MutItems<'a, T> {
self.as_mut_slice().iter_mut()
}
fn get<'a>(&'a self, index: uint) -> Option<&'a T> {
self.as_slice().get(index)
}
fn get_mut<'a>(&'a mut self, index: uint) -> Option<&'a mut T> {
Some(&mut self.as_mut_slice()[index]) // wrong: fallible
}
}
///////////////////////////////////////////////////////////////////////////
/**
......
......@@ -27,6 +27,7 @@
use libc::c_uint;
#[deriving(Clone, PartialEq, Show)]
#[repr(C)]
pub struct Type {
rf: TypeRef
}
......@@ -283,9 +284,10 @@ pub fn field_types(&self) -> Vec<Type> {
if n_elts == 0 {
return Vec::new();
}
let mut elts = Vec::from_elem(n_elts, 0 as TypeRef);
llvm::LLVMGetStructElementTypes(self.to_ref(), &mut elts[0]);
mem::transmute(elts)
let mut elts = Vec::from_elem(n_elts, Type { rf: 0 as TypeRef });
llvm::LLVMGetStructElementTypes(self.to_ref(),
elts.as_mut_ptr() as *mut TypeRef);
elts
}
}
......@@ -296,9 +298,10 @@ pub fn return_type(&self) -> Type {
pub fn func_params(&self) -> Vec<Type> {
unsafe {
let n_args = llvm::LLVMCountParamTypes(self.to_ref()) as uint;
let args = Vec::from_elem(n_args, 0 as TypeRef);
llvm::LLVMGetParamTypes(self.to_ref(), args.as_ptr());
mem::transmute(args)
let mut args = Vec::from_elem(n_args, Type { rf: 0 as TypeRef });
llvm::LLVMGetParamTypes(self.to_ref(),
args.as_mut_ptr() as *mut TypeRef);
args
}
}
......
......@@ -547,7 +547,7 @@ pub fn LLVMFunctionType(ReturnType: TypeRef,
pub fn LLVMIsFunctionVarArg(FunctionTy: TypeRef) -> Bool;
pub fn LLVMGetReturnType(FunctionTy: TypeRef) -> TypeRef;
pub fn LLVMCountParamTypes(FunctionTy: TypeRef) -> c_uint;
pub fn LLVMGetParamTypes(FunctionTy: TypeRef, Dest: *const TypeRef);
pub fn LLVMGetParamTypes(FunctionTy: TypeRef, Dest: *mut TypeRef);
/* Operations on struct types */
pub fn LLVMStructTypeInContext(C: ContextRef,
......@@ -2195,4 +2195,3 @@ pub unsafe fn static_link_hack_this_sucks() {
// Works to the above fix for #15460 to ensure LLVM dependencies that
// are only used by rustllvm don't get stripped by the linker.
mod llvmdeps;
......@@ -21,7 +21,6 @@
use visit::Visitor;
use visit;
use std::cell::Cell;
use std::cmp;
use std::u32;
......@@ -333,20 +332,20 @@ pub fn add(&mut self, id: NodeId) {
}
pub trait IdVisitingOperation {
fn visit_id(&self, node_id: NodeId);
fn visit_id(&mut self, node_id: NodeId);
}
/// A visitor that applies its operation to all of the node IDs
/// in a visitable thing.
pub struct IdVisitor<'a, O:'a> {
pub operation: &'a O,
pub operation: &'a mut O,
pub pass_through_items: bool,
pub visited_outermost: bool,
}
impl<'a, O: IdVisitingOperation> IdVisitor<'a, O> {
fn visit_generics_helper(&self, generics: &Generics) {
fn visit_generics_helper(&mut self, generics: &Generics) {
for type_parameter in generics.ty_params.iter() {
self.operation.visit_id(type_parameter.id)
}
......@@ -540,7 +539,7 @@ fn visit_lifetime_decl(&mut self, def: &'v LifetimeDef) {
}
pub fn visit_ids_for_inlined_item<O: IdVisitingOperation>(item: &InlinedItem,
operation: &O) {
operation: &mut O) {
let mut id_visitor = IdVisitor {
operation: operation,
pass_through_items: true,
......@@ -551,23 +550,21 @@ pub fn visit_ids_for_inlined_item<O: IdVisitingOperation>(item: &InlinedItem,
}
struct IdRangeComputingVisitor {
result: Cell<IdRange>,
result: IdRange,
}
impl IdVisitingOperation for IdRangeComputingVisitor {
fn visit_id(&self, id: NodeId) {
let mut id_range = self.result.get();
id_range.add(id);
self.result.set(id_range)
fn visit_id(&mut self, id: NodeId) {
self.result.add(id);
}
}
pub fn compute_id_range_for_inlined_item(item: &InlinedItem) -> IdRange {
let visitor = IdRangeComputingVisitor {
result: Cell::new(IdRange::max())
let mut visitor = IdRangeComputingVisitor {
result: IdRange::max()
};
visit_ids_for_inlined_item(item, &visitor);
visitor.result.get()
visit_ids_for_inlined_item(item, &mut visitor);
visitor.result
}
pub fn compute_id_range_for_fn_body(fk: visit::FnKind,
......@@ -582,16 +579,16 @@ pub fn compute_id_range_for_fn_body(fk: visit::FnKind,
* ignoring nested items.
*/
let visitor = IdRangeComputingVisitor {
result: Cell::new(IdRange::max())
let mut visitor = IdRangeComputingVisitor {
result: IdRange::max()
};
let mut id_visitor = IdVisitor {
operation: &visitor,
operation: &mut visitor,
pass_through_items: false,
visited_outermost: false,
};
id_visitor.visit_fn(fk, decl, body, sp, id);
visitor.result.get()
id_visitor.operation.result
}
pub fn walk_pat(pat: &Pat, it: |&Pat| -> bool) -> bool {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册