Skip to content

Commit a87078a

Browse files
committed
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.
1 parent fbb90c3 commit a87078a

File tree

10 files changed

+61
-170
lines changed

10 files changed

+61
-170
lines changed

src/librustc/lint/context.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -532,7 +532,7 @@ impl<'a, 'tcx> Context<'a, 'tcx> {
532532
}
533533
}
534534

535-
fn visit_ids(&self, f: |&mut ast_util::IdVisitor<Context>|) {
535+
fn visit_ids(&mut self, f: |&mut ast_util::IdVisitor<Context>|) {
536536
let mut v = ast_util::IdVisitor {
537537
operation: self,
538538
pass_through_items: false,
@@ -749,7 +749,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for Context<'a, 'tcx> {
749749

750750
// Output any lints that were previously added to the session.
751751
impl<'a, 'tcx> IdVisitingOperation for Context<'a, 'tcx> {
752-
fn visit_id(&self, id: ast::NodeId) {
752+
fn visit_id(&mut self, id: ast::NodeId) {
753753
match self.tcx.sess.lints.borrow_mut().pop(&id) {
754754
None => {}
755755
Some(lints) => {

src/librustc/metadata/common.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ impl astencode_tag {
148148
pub fn from_uint(value : uint) -> Option<astencode_tag> {
149149
let is_a_tag = first_astencode_tag <= value && value <= last_astencode_tag;
150150
if !is_a_tag { None } else {
151-
Some(unsafe { mem::transmute(value) })
151+
Some(unsafe { mem::transmute::<uint, astencode_tag>(value) })
152152
}
153153
}
154154
}
@@ -247,4 +247,3 @@ pub const tag_type_param_def: uint = 0xa5;
247247

248248
pub const tag_item_generics: uint = 0xa6;
249249
pub const tag_method_ty_generics: uint = 0xa7;
250-

src/librustc/metadata/encoder.rs

+10-21
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ use serialize::Encodable;
2929
use std::cell::RefCell;
3030
use std::hash::Hash;
3131
use std::hash;
32-
use std::mem;
3332
use std::collections::HashMap;
3433
use syntax::abi;
3534
use syntax::ast::*;
@@ -1508,44 +1507,36 @@ fn my_visit_expr(_e: &Expr) { }
15081507

15091508
fn my_visit_item(i: &Item,
15101509
rbml_w: &mut Encoder,
1511-
ecx_ptr: *const int,
1510+
ecx: &EncodeContext,
15121511
index: &mut Vec<entry<i64>>) {
1513-
let mut rbml_w = unsafe { rbml_w.unsafe_clone() };
1514-
// See above
1515-
let ecx: &EncodeContext = unsafe { mem::transmute(ecx_ptr) };
15161512
ecx.tcx.map.with_path(i.id, |path| {
1517-
encode_info_for_item(ecx, &mut rbml_w, i, index, path, i.vis);
1513+
encode_info_for_item(ecx, rbml_w, i, index, path, i.vis);
15181514
});
15191515
}
15201516

15211517
fn my_visit_foreign_item(ni: &ForeignItem,
15221518
rbml_w: &mut Encoder,
1523-
ecx_ptr:*const int,
1519+
ecx: &EncodeContext,
15241520
index: &mut Vec<entry<i64>>) {
1525-
// See above
1526-
let ecx: &EncodeContext = unsafe { mem::transmute(ecx_ptr) };
15271521
debug!("writing foreign item {}::{}",
15281522
ecx.tcx.map.path_to_string(ni.id),
15291523
token::get_ident(ni.ident));
15301524

1531-
let mut rbml_w = unsafe {
1532-
rbml_w.unsafe_clone()
1533-
};
15341525
let abi = ecx.tcx.map.get_foreign_abi(ni.id);
15351526
ecx.tcx.map.with_path(ni.id, |path| {
1536-
encode_info_for_foreign_item(ecx, &mut rbml_w,
1527+
encode_info_for_foreign_item(ecx, rbml_w,
15371528
ni, index,
15381529
path, abi);
15391530
});
15401531
}
15411532

1542-
struct EncodeVisitor<'a,'b:'a> {
1533+
struct EncodeVisitor<'a, 'b:'a, 'c:'a, 'tcx:'c> {
15431534
rbml_w_for_visit_item: &'a mut Encoder<'b>,
1544-
ecx_ptr:*const int,
1535+
ecx: &'a EncodeContext<'c,'tcx>,
15451536
index: &'a mut Vec<entry<i64>>,
15461537
}
15471538

1548-
impl<'a, 'b, 'v> Visitor<'v> for EncodeVisitor<'a, 'b> {
1539+
impl<'a, 'b, 'c, 'tcx, 'v> Visitor<'v> for EncodeVisitor<'a, 'b, 'c, 'tcx> {
15491540
fn visit_expr(&mut self, ex: &Expr) {
15501541
visit::walk_expr(self, ex);
15511542
my_visit_expr(ex);
@@ -1554,14 +1545,14 @@ impl<'a, 'b, 'v> Visitor<'v> for EncodeVisitor<'a, 'b> {
15541545
visit::walk_item(self, i);
15551546
my_visit_item(i,
15561547
self.rbml_w_for_visit_item,
1557-
self.ecx_ptr,
1548+
self.ecx,
15581549
self.index);
15591550
}
15601551
fn visit_foreign_item(&mut self, ni: &ForeignItem) {
15611552
visit::walk_foreign_item(self, ni);
15621553
my_visit_foreign_item(ni,
15631554
self.rbml_w_for_visit_item,
1564-
self.ecx_ptr,
1555+
self.ecx,
15651556
self.index);
15661557
}
15671558
}
@@ -1585,11 +1576,9 @@ fn encode_info_for_items(ecx: &EncodeContext,
15851576
syntax::parse::token::special_idents::invalid,
15861577
Public);
15871578

1588-
// See comment in `encode_side_tables_for_ii` in astencode
1589-
let ecx_ptr: *const int = unsafe { mem::transmute(ecx) };
15901579
visit::walk_crate(&mut EncodeVisitor {
15911580
index: &mut index,
1592-
ecx_ptr: ecx_ptr,
1581+
ecx: ecx,
15931582
rbml_w_for_visit_item: &mut *rbml_w,
15941583
}, krate);
15951584

src/librustc/metadata/loader.rs

+11-24
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,6 @@ use std::c_str::ToCStr;
231231
use std::cmp;
232232
use std::io::fs::PathExtensions;
233233
use std::io;
234-
use std::mem;
235234
use std::ptr;
236235
use std::slice;
237236
use std::string;
@@ -287,8 +286,8 @@ pub struct Library {
287286

288287
pub struct ArchiveMetadata {
289288
_archive: ArchiveRO,
290-
// See comments in ArchiveMetadata::new for why this is static
291-
data: &'static [u8],
289+
// points into self._archive
290+
data: *const [u8],
292291
}
293292

294293
pub struct CratePaths {
@@ -709,33 +708,21 @@ pub fn note_crate_name(diag: &SpanHandler, name: &str) {
709708

710709
impl ArchiveMetadata {
711710
fn new(ar: ArchiveRO) -> Option<ArchiveMetadata> {
712-
let data: &'static [u8] = {
713-
let data = match ar.read(METADATA_FILENAME) {
714-
Some(data) => data,
715-
None => {
716-
debug!("didn't find '{}' in the archive", METADATA_FILENAME);
717-
return None;
718-
}
719-
};
720-
// This data is actually a pointer inside of the archive itself, but
721-
// we essentially want to cache it because the lookup inside the
722-
// archive is a fairly expensive operation (and it's queried for
723-
// *very* frequently). For this reason, we transmute it to the
724-
// static lifetime to put into the struct. Note that the buffer is
725-
// never actually handed out with a static lifetime, but rather the
726-
// buffer is loaned with the lifetime of this containing object.
727-
// Hence, we're guaranteed that the buffer will never be used after
728-
// this object is dead, so this is a safe operation to transmute and
729-
// store the data as a static buffer.
730-
unsafe { mem::transmute(data) }
711+
let data = match ar.read(METADATA_FILENAME) {
712+
Some(data) => data as *const [u8],
713+
None => {
714+
debug!("didn't find '{}' in the archive", METADATA_FILENAME);
715+
return None;
716+
}
731717
};
718+
732719
Some(ArchiveMetadata {
733720
_archive: ar,
734721
data: data,
735722
})
736723
}
737724

738-
pub fn as_slice<'a>(&'a self) -> &'a [u8] { self.data }
725+
pub fn as_slice<'a>(&'a self) -> &'a [u8] { unsafe { &*self.data } }
739726
}
740727

741728
// 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
798785
let csz = llvm::LLVMGetSectionSize(si.llsi) as uint;
799786
let mut found =
800787
Err(format!("metadata not found: '{}'", filename.display()));
801-
let cvbuf: *const u8 = mem::transmute(cbuf);
788+
let cvbuf: *const u8 = cbuf as *const u8;
802789
let vlen = encoder::metadata_encoding_version.len();
803790
debug!("checking {} bytes of metadata-version stamp",
804791
vlen);

src/librustc/middle/astencode.rs

+10-33
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,7 @@ use syntax::parse::token;
3838
use syntax::ptr::P;
3939
use syntax;
4040

41-
use libc;
4241
use std::io::Seek;
43-
use std::mem;
4442
use std::rc::Rc;
4543

4644
use rbml::io::SeekableMemWriter;
@@ -1128,46 +1126,25 @@ impl<'a> write_tag_and_id for Encoder<'a> {
11281126
}
11291127
}
11301128

1131-
struct SideTableEncodingIdVisitor<'a,'b:'a> {
1132-
ecx_ptr: *const libc::c_void,
1133-
new_rbml_w: &'a mut Encoder<'b>,
1129+
struct SideTableEncodingIdVisitor<'a, 'b:'a, 'c:'a, 'tcx:'c> {
1130+
ecx: &'a e::EncodeContext<'c, 'tcx>,
1131+
rbml_w: &'a mut Encoder<'b>,
11341132
}
11351133

1136-
impl<'a,'b> ast_util::IdVisitingOperation for
1137-
SideTableEncodingIdVisitor<'a,'b> {
1138-
fn visit_id(&self, id: ast::NodeId) {
1139-
// Note: this will cause a copy of rbml_w, which is bad as
1140-
// it is mutable. But I believe it's harmless since we generate
1141-
// balanced EBML.
1142-
//
1143-
// FIXME(pcwalton): Don't copy this way.
1144-
let mut new_rbml_w = unsafe {
1145-
self.new_rbml_w.unsafe_clone()
1146-
};
1147-
// See above
1148-
let ecx: &e::EncodeContext = unsafe {
1149-
mem::transmute(self.ecx_ptr)
1150-
};
1151-
encode_side_tables_for_id(ecx, &mut new_rbml_w, id)
1134+
impl<'a, 'b, 'c, 'tcx> ast_util::IdVisitingOperation for
1135+
SideTableEncodingIdVisitor<'a, 'b, 'c, 'tcx> {
1136+
fn visit_id(&mut self, id: ast::NodeId) {
1137+
encode_side_tables_for_id(self.ecx, self.rbml_w, id)
11521138
}
11531139
}
11541140

11551141
fn encode_side_tables_for_ii(ecx: &e::EncodeContext,
11561142
rbml_w: &mut Encoder,
11571143
ii: &ast::InlinedItem) {
11581144
rbml_w.start_tag(c::tag_table as uint);
1159-
let mut new_rbml_w = unsafe {
1160-
rbml_w.unsafe_clone()
1161-
};
1162-
1163-
// Because the ast visitor uses @IdVisitingOperation, I can't pass in
1164-
// ecx directly, but /I/ know that it'll be fine since the lifetime is
1165-
// tied to the CrateContext that lives throughout this entire section.
1166-
ast_util::visit_ids_for_inlined_item(ii, &SideTableEncodingIdVisitor {
1167-
ecx_ptr: unsafe {
1168-
mem::transmute(ecx)
1169-
},
1170-
new_rbml_w: &mut new_rbml_w,
1145+
ast_util::visit_ids_for_inlined_item(ii, &mut SideTableEncodingIdVisitor {
1146+
ecx: ecx,
1147+
rbml_w: rbml_w
11711148
});
11721149
rbml_w.end_tag();
11731150
}

src/librustc/middle/liveness.rs

+1-5
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,6 @@ use util::nodemap::NodeMap;
118118

119119
use std::fmt;
120120
use std::io;
121-
use std::mem::transmute;
122121
use std::rc::Rc;
123122
use std::str;
124123
use std::uint;
@@ -380,10 +379,7 @@ fn visit_fn(ir: &mut IrMaps,
380379
// swap in a new set of IR maps for this function body:
381380
let mut fn_maps = IrMaps::new(ir.tcx);
382381

383-
unsafe {
384-
debug!("creating fn_maps: {}",
385-
transmute::<&IrMaps, *const IrMaps>(&fn_maps));
386-
}
382+
debug!("creating fn_maps: {}", &fn_maps as *const IrMaps);
387383

388384
for arg in decl.inputs.iter() {
389385
pat_util::pat_bindings(&ir.tcx.def_map,

src/librustc/middle/subst.rs

+1-57
Original file line numberDiff line numberDiff line change
@@ -16,66 +16,10 @@ use middle::ty_fold::{TypeFoldable, TypeFolder};
1616
use util::ppaux::Repr;
1717

1818
use std::fmt;
19-
use std::mem;
20-
use std::raw;
21-
use std::slice::{Items, MutItems};
19+
use std::slice::Items;
2220
use std::vec::Vec;
2321
use syntax::codemap::{Span, DUMMY_SP};
2422

25-
///////////////////////////////////////////////////////////////////////////
26-
// HomogeneousTuple3 trait
27-
//
28-
// This could be moved into standard library at some point.
29-
30-
trait HomogeneousTuple3<T> {
31-
fn len(&self) -> uint;
32-
fn as_slice<'a>(&'a self) -> &'a [T];
33-
fn as_mut_slice<'a>(&'a mut self) -> &'a mut [T];
34-
fn iter<'a>(&'a self) -> Items<'a, T>;
35-
fn iter_mut<'a>(&'a mut self) -> MutItems<'a, T>;
36-
fn get<'a>(&'a self, index: uint) -> Option<&'a T>;
37-
fn get_mut<'a>(&'a mut self, index: uint) -> Option<&'a mut T>;
38-
}
39-
40-
impl<T> HomogeneousTuple3<T> for (T, T, T) {
41-
fn len(&self) -> uint {
42-
3
43-
}
44-
45-
fn as_slice<'a>(&'a self) -> &'a [T] {
46-
unsafe {
47-
let ptr: *const T = mem::transmute(self);
48-
let slice = raw::Slice { data: ptr, len: 3 };
49-
mem::transmute(slice)
50-
}
51-
}
52-
53-
fn as_mut_slice<'a>(&'a mut self) -> &'a mut [T] {
54-
unsafe {
55-
let ptr: *const T = mem::transmute(self);
56-
let slice = raw::Slice { data: ptr, len: 3 };
57-
mem::transmute(slice)
58-
}
59-
}
60-
61-
fn iter<'a>(&'a self) -> Items<'a, T> {
62-
let slice: &'a [T] = self.as_slice();
63-
slice.iter()
64-
}
65-
66-
fn iter_mut<'a>(&'a mut self) -> MutItems<'a, T> {
67-
self.as_mut_slice().iter_mut()
68-
}
69-
70-
fn get<'a>(&'a self, index: uint) -> Option<&'a T> {
71-
self.as_slice().get(index)
72-
}
73-
74-
fn get_mut<'a>(&'a mut self, index: uint) -> Option<&'a mut T> {
75-
Some(&mut self.as_mut_slice()[index]) // wrong: fallible
76-
}
77-
}
78-
7923
///////////////////////////////////////////////////////////////////////////
8024

8125
/**

src/librustc/middle/trans/type_.rs

+9-6
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ use std::collections::HashMap;
2727
use libc::c_uint;
2828

2929
#[deriving(Clone, PartialEq, Show)]
30+
#[repr(C)]
3031
pub struct Type {
3132
rf: TypeRef
3233
}
@@ -283,9 +284,10 @@ impl Type {
283284
if n_elts == 0 {
284285
return Vec::new();
285286
}
286-
let mut elts = Vec::from_elem(n_elts, 0 as TypeRef);
287-
llvm::LLVMGetStructElementTypes(self.to_ref(), &mut elts[0]);
288-
mem::transmute(elts)
287+
let mut elts = Vec::from_elem(n_elts, Type { rf: 0 as TypeRef });
288+
llvm::LLVMGetStructElementTypes(self.to_ref(),
289+
elts.as_mut_ptr() as *mut TypeRef);
290+
elts
289291
}
290292
}
291293

@@ -296,9 +298,10 @@ impl Type {
296298
pub fn func_params(&self) -> Vec<Type> {
297299
unsafe {
298300
let n_args = llvm::LLVMCountParamTypes(self.to_ref()) as uint;
299-
let args = Vec::from_elem(n_args, 0 as TypeRef);
300-
llvm::LLVMGetParamTypes(self.to_ref(), args.as_ptr());
301-
mem::transmute(args)
301+
let mut args = Vec::from_elem(n_args, Type { rf: 0 as TypeRef });
302+
llvm::LLVMGetParamTypes(self.to_ref(),
303+
args.as_mut_ptr() as *mut TypeRef);
304+
args
302305
}
303306
}
304307

src/librustc_llvm/lib.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -547,7 +547,7 @@ extern {
547547
pub fn LLVMIsFunctionVarArg(FunctionTy: TypeRef) -> Bool;
548548
pub fn LLVMGetReturnType(FunctionTy: TypeRef) -> TypeRef;
549549
pub fn LLVMCountParamTypes(FunctionTy: TypeRef) -> c_uint;
550-
pub fn LLVMGetParamTypes(FunctionTy: TypeRef, Dest: *const TypeRef);
550+
pub fn LLVMGetParamTypes(FunctionTy: TypeRef, Dest: *mut TypeRef);
551551

552552
/* Operations on struct types */
553553
pub fn LLVMStructTypeInContext(C: ContextRef,
@@ -2195,4 +2195,3 @@ pub unsafe fn static_link_hack_this_sucks() {
21952195
// Works to the above fix for #15460 to ensure LLVM dependencies that
21962196
// are only used by rustllvm don't get stripped by the linker.
21972197
mod llvmdeps;
2198-

0 commit comments

Comments
 (0)