rollup merge of #18318 : arielb1/transmute-cleanup
This commit is contained in:
commit
3aaee490d3
@ -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;
|
||||
@ -1122,27 +1120,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)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1150,18 +1136,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;
|
||||
|
||||
|
@ -119,7 +119,7 @@ impl Name {
|
||||
pub fn as_str<'a>(&'a self) -> &'a str {
|
||||
unsafe {
|
||||
// FIXME #12938: can't use copy_lifetime since &str isn't a &T
|
||||
::std::mem::transmute(token::get_name(*self).get())
|
||||
::std::mem::transmute::<&str,&str>(token::get_name(*self).get())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -668,12 +668,12 @@ pub fn get<'a>(&'a self) -> &'a str {
|
||||
|
||||
impl BytesContainer for InternedString {
|
||||
fn container_as_bytes<'a>(&'a self) -> &'a [u8] {
|
||||
// FIXME(pcwalton): This is a workaround for the incorrect signature
|
||||
// FIXME #12938: This is a workaround for the incorrect signature
|
||||
// of `BytesContainer`, which is itself a workaround for the lack of
|
||||
// DST.
|
||||
unsafe {
|
||||
let this = self.get();
|
||||
mem::transmute(this.container_as_bytes())
|
||||
mem::transmute::<&[u8],&[u8]>(this.container_as_bytes())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -169,17 +169,14 @@ pub fn to_string(f: |&mut State| -> IoResult<()>) -> String {
|
||||
let mut s = rust_printer(box MemWriter::new());
|
||||
f(&mut s).unwrap();
|
||||
eof(&mut s.s).unwrap();
|
||||
unsafe {
|
||||
let wr = unsafe {
|
||||
// FIXME(pcwalton): A nasty function to extract the string from an `io::Writer`
|
||||
// that we "know" to be a `MemWriter` that works around the lack of checked
|
||||
// downcasts.
|
||||
let obj: TraitObject = mem::transmute_copy(&s.s.out);
|
||||
let wr: Box<MemWriter> = mem::transmute(obj.data);
|
||||
let result =
|
||||
String::from_utf8(wr.get_ref().as_slice().to_vec()).unwrap();
|
||||
mem::forget(wr);
|
||||
result.to_string()
|
||||
}
|
||||
let obj: &TraitObject = mem::transmute(&s.s.out);
|
||||
mem::transmute::<*mut (), &MemWriter>(obj.data)
|
||||
};
|
||||
String::from_utf8(wr.get_ref().to_vec()).unwrap()
|
||||
}
|
||||
|
||||
pub fn binop_to_string(op: BinOpToken) -> &'static str {
|
||||
|
Loading…
Reference in New Issue
Block a user