diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index b6bb11d07ef04..2e792b6053ea3 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -18,7 +18,7 @@ use std::borrow::Cow; use std::env; -use std::fs::{self, File}; +use std::fs; use std::io::BufReader; use std::io::prelude::*; use std::path::{Path, PathBuf}; @@ -707,7 +707,7 @@ impl Step for CodegenBackend { } let stamp = codegen_backend_stamp(builder, compiler, target, backend); let codegen_backend = codegen_backend.to_str().unwrap(); - t!(t!(File::create(&stamp)).write_all(codegen_backend.as_bytes())); + t!(fs::write(&stamp, &codegen_backend)); } } @@ -796,8 +796,7 @@ fn copy_codegen_backends_to_sysroot(builder: &Builder, for backend in builder.config.rust_codegen_backends.iter() { let stamp = codegen_backend_stamp(builder, compiler, target, *backend); - let mut dylib = String::new(); - t!(t!(File::open(&stamp)).read_to_string(&mut dylib)); + let dylib = t!(fs::read_to_string(&stamp)); let file = Path::new(&dylib); let filename = file.file_name().unwrap().to_str().unwrap(); // change `librustc_codegen_llvm-xxxxxx.so` to `librustc_codegen_llvm-llvm.so` @@ -1137,10 +1136,7 @@ pub fn run_cargo(builder: &Builder, // contents (the list of files to copy) is different or if any dep's mtime // is newer then we rewrite the stamp file. deps.sort(); - let mut stamp_contents = Vec::new(); - if let Ok(mut f) = File::open(stamp) { - t!(f.read_to_end(&mut stamp_contents)); - } + let stamp_contents = fs::read(stamp); let stamp_mtime = mtime(&stamp); let mut new_contents = Vec::new(); let mut max = None; @@ -1156,7 +1152,10 @@ pub fn run_cargo(builder: &Builder, } let max = max.unwrap(); let max_path = max_path.unwrap(); - if stamp_contents == new_contents && max <= stamp_mtime { + let contents_equal = stamp_contents + .map(|contents| contents == new_contents) + .unwrap_or_default(); + if contents_equal && max <= stamp_mtime { builder.verbose(&format!("not updating {:?}; contents equal and {:?} <= {:?}", stamp, max, stamp_mtime)); return deps @@ -1166,7 +1165,7 @@ pub fn run_cargo(builder: &Builder, } else { builder.verbose(&format!("updating {:?} as deps changed", stamp)); } - t!(t!(File::create(stamp)).write_all(&new_contents)); + t!(fs::write(&stamp, &new_contents)); deps } diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 0f249eee00022..dd8cca5999bd3 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -15,8 +15,7 @@ use std::collections::{HashMap, HashSet}; use std::env; -use std::fs::{self, File}; -use std::io::prelude::*; +use std::fs; use std::path::{Path, PathBuf}; use std::process; use std::cmp; @@ -414,9 +413,7 @@ impl Config { config.run_host_only = !(flags.host.is_empty() && !flags.target.is_empty()); let toml = file.map(|file| { - let mut f = t!(File::open(&file)); - let mut contents = String::new(); - t!(f.read_to_string(&mut contents)); + let contents = t!(fs::read_to_string(&file)); match toml::from_str(&contents) { Ok(table) => table, Err(err) => { diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index cd8d5642b2570..68aed59074638 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -19,8 +19,8 @@ //! pieces of `rustup.rs`! use std::env; -use std::fs::{self, File}; -use std::io::{Read, Write}; +use std::fs; +use std::io::Write; use std::path::{PathBuf, Path}; use std::process::{Command, Stdio}; @@ -1510,8 +1510,7 @@ impl Step for Extended { } let xform = |p: &Path| { - let mut contents = String::new(); - t!(t!(File::open(p)).read_to_string(&mut contents)); + let mut contents = t!(fs::read_to_string(p)); if rls_installer.is_none() { contents = filter(&contents, "rls"); } @@ -1522,8 +1521,8 @@ impl Step for Extended { contents = filter(&contents, "rustfmt"); } let ret = tmp.join(p.file_name().unwrap()); - t!(t!(File::create(&ret)).write_all(contents.as_bytes())); - return ret + t!(fs::write(&ret, &contents)); + ret }; if target.contains("apple-darwin") { @@ -1868,8 +1867,7 @@ impl Step for HashSign { let file = builder.config.dist_gpg_password_file.as_ref().unwrap_or_else(|| { panic!("\n\nfailed to specify `dist.gpg-password-file` in `config.toml`\n\n") }); - let mut pass = String::new(); - t!(t!(File::open(&file)).read_to_string(&mut pass)); + let pass = t!(fs::read_to_string(&file)); let today = output(Command::new("date").arg("+%Y-%m-%d")); diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index f9b19ffb10d69..4fb17bc51f213 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -18,8 +18,7 @@ //! `rustdoc`. use std::collections::HashSet; -use std::fs::{self, File}; -use std::io::prelude::*; +use std::fs; use std::io; use std::path::{PathBuf, Path}; @@ -378,12 +377,11 @@ impl Step for Standalone { let version_info = out.join("version_info.html"); if !builder.config.dry_run && !up_to_date(&version_input, &version_info) { - let mut info = String::new(); - t!(t!(File::open(&version_input)).read_to_string(&mut info)); - let info = info.replace("VERSION", &builder.rust_release()) - .replace("SHORT_HASH", builder.rust_info.sha_short().unwrap_or("")) - .replace("STAMP", builder.rust_info.sha().unwrap_or("")); - t!(t!(File::create(&version_info)).write_all(info.as_bytes())); + let info = t!(fs::read_to_string(&version_input)) + .replace("VERSION", &builder.rust_release()) + .replace("SHORT_HASH", builder.rust_info.sha_short().unwrap_or("")) + .replace("STAMP", builder.rust_info.sha().unwrap_or("")); + t!(fs::write(&version_info, &info)); } for file in t!(fs::read_dir(builder.src.join("src/doc"))) { diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 2832f5bebddd6..a62830da4bb61 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -1067,9 +1067,8 @@ impl Build { /// Returns the `a.b.c` version that the given package is at. fn release_num(&self, package: &str) -> String { - let mut toml = String::new(); let toml_file_name = self.src.join(&format!("src/tools/{}/Cargo.toml", package)); - t!(t!(File::open(toml_file_name)).read_to_string(&mut toml)); + let toml = t!(fs::read_to_string(&toml_file_name)); for line in toml.lines() { let prefix = "version = \""; let suffix = "\""; @@ -1151,8 +1150,7 @@ impl Build { } let mut paths = Vec::new(); - let mut contents = Vec::new(); - t!(t!(File::open(stamp)).read_to_end(&mut contents)); + let contents = t!(fs::read(stamp)); // This is the method we use for extracting paths from the stamp file passed to us. See // run_cargo for more information (in compile.rs). for part in contents.split(|b| *b == 0) { diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index 448967ef0c2e1..150b6bea18064 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -21,7 +21,6 @@ use std::env; use std::ffi::OsString; use std::fs::{self, File}; -use std::io::{Read, Write}; use std::path::{Path, PathBuf}; use std::process::Command; @@ -75,8 +74,7 @@ impl Step for Llvm { } let rebuild_trigger = builder.src.join("src/rustllvm/llvm-rebuild-trigger"); - let mut rebuild_trigger_contents = String::new(); - t!(t!(File::open(&rebuild_trigger)).read_to_string(&mut rebuild_trigger_contents)); + let rebuild_trigger_contents = t!(fs::read_to_string(&rebuild_trigger)); let (out_dir, llvm_config_ret_dir) = if emscripten { let dir = builder.emscripten_llvm_out(target); @@ -93,8 +91,7 @@ impl Step for Llvm { let build_llvm_config = llvm_config_ret_dir .join(exe("llvm-config", &*builder.config.build)); if done_stamp.exists() { - let mut done_contents = String::new(); - t!(t!(File::open(&done_stamp)).read_to_string(&mut done_contents)); + let done_contents = t!(fs::read_to_string(&done_stamp)); // If LLVM was already built previously and contents of the rebuild-trigger file // didn't change from the previous build, then no action is required. @@ -261,7 +258,7 @@ impl Step for Llvm { cfg.build(); - t!(t!(File::create(&done_stamp)).write_all(rebuild_trigger_contents.as_bytes())); + t!(fs::write(&done_stamp, &rebuild_trigger_contents)); build_llvm_config } diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/sanity.rs index 15d3bccba09cc..7a9e6d4fd387b 100644 --- a/src/bootstrap/sanity.rs +++ b/src/bootstrap/sanity.rs @@ -21,8 +21,7 @@ use std::collections::HashMap; use std::env; use std::ffi::{OsString, OsStr}; -use std::fs::{self, File}; -use std::io::Read; +use std::fs; use std::path::PathBuf; use std::process::Command; @@ -235,9 +234,7 @@ $ pacman -R cmake && pacman -S mingw-w64-x86_64-cmake } if build.config.channel == "stable" { - let mut stage0 = String::new(); - t!(t!(File::open(build.src.join("src/stage0.txt"))) - .read_to_string(&mut stage0)); + let stage0 = t!(fs::read_to_string(build.src.join("src/stage0.txt"))); if stage0.contains("\ndev:") { panic!("bootstrapping from a dev compiler in a stable release, but \ should only be bootstrapping from a released compiler!"); diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index e55773011df8e..056e6ca3403c4 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -16,8 +16,7 @@ use std::env; use std::ffi::OsString; use std::fmt; -use std::fs::{self, File}; -use std::io::Read; +use std::fs; use std::iter; use std::path::{Path, PathBuf}; use std::process::Command; @@ -1418,10 +1417,8 @@ impl Step for ErrorIndex { } fn markdown_test(builder: &Builder, compiler: Compiler, markdown: &Path) -> bool { - match File::open(markdown) { - Ok(mut file) => { - let mut contents = String::new(); - t!(file.read_to_string(&mut contents)); + match fs::read_to_string(markdown) { + Ok(contents) => { if !contents.contains("```") { return true; } diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs index 8d009101ce7da..0b25d911a299c 100644 --- a/src/liballoc/string.rs +++ b/src/liballoc/string.rs @@ -618,6 +618,8 @@ impl String { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn from_utf16(v: &[u16]) -> Result { + // This isn't done via collect::>() for performance reasons. + // FIXME: the function can be simplified again when #48994 is closed. let mut ret = String::with_capacity(v.len()); for c in decode_utf16(v.iter().cloned()) { if let Ok(c) = c { diff --git a/src/libcore/array.rs b/src/libcore/array.rs index 3d24f8902bd83..26e7a79d35df6 100644 --- a/src/libcore/array.rs +++ b/src/libcore/array.rs @@ -148,6 +148,15 @@ macro_rules! array_impls { } } + #[unstable(feature = "try_from", issue = "33417")] + impl<'a, T> TryFrom<&'a [T]> for [T; $N] where T: Copy { + type Error = TryFromSliceError; + + fn try_from(slice: &[T]) -> Result<[T; $N], TryFromSliceError> { + <&Self>::try_from(slice).map(|r| *r) + } + } + #[unstable(feature = "try_from", issue = "33417")] impl<'a, T> TryFrom<&'a [T]> for &'a [T; $N] { type Error = TryFromSliceError; diff --git a/src/libcore/convert.rs b/src/libcore/convert.rs index dbc28ef7cf6a9..2d4813718f41a 100644 --- a/src/libcore/convert.rs +++ b/src/libcore/convert.rs @@ -327,7 +327,8 @@ pub trait Into: Sized { /// An example usage for error handling: /// /// ``` -/// use std::io::{self, Read}; +/// use std::fs; +/// use std::io; /// use std::num; /// /// enum CliError { @@ -348,9 +349,7 @@ pub trait Into: Sized { /// } /// /// fn open_and_parse_file(file_name: &str) -> Result { -/// let mut file = std::fs::File::open("test")?; -/// let mut contents = String::new(); -/// file.read_to_string(&mut contents)?; +/// let mut contents = fs::read_to_string(&file_name)?; /// let num: i32 = contents.trim().parse()?; /// Ok(num) /// } diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 57b5903c9d39f..46c098c8236a0 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -1989,6 +1989,19 @@ big endian. ``` let value = ", stringify!($SelfT), "::from_be_bytes(", $be_bytes, "); assert_eq!(value, ", $swap_op, "); +``` + +When starting from a slice rather than an array, fallible conversion APIs can be used: + +``` +#![feature(try_from)] +use std::convert::TryInto; + +fn read_be_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), " { + let (int_bytes, rest) = input.split_at(std::mem::size_of::<", stringify!($SelfT), ">()); + *input = rest; + ", stringify!($SelfT), "::from_be_bytes(int_bytes.try_into().unwrap()) +} ```"), #[stable(feature = "int_to_from_bytes", since = "1.32.0")] #[rustc_const_unstable(feature = "const_int_conversion")] @@ -2008,6 +2021,19 @@ little endian. ``` let value = ", stringify!($SelfT), "::from_le_bytes(", $le_bytes, "); assert_eq!(value, ", $swap_op, "); +``` + +When starting from a slice rather than an array, fallible conversion APIs can be used: + +``` +#![feature(try_from)] +use std::convert::TryInto; + +fn read_be_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), " { + let (int_bytes, rest) = input.split_at(std::mem::size_of::<", stringify!($SelfT), ">()); + *input = rest; + ", stringify!($SelfT), "::from_be_bytes(int_bytes.try_into().unwrap()) +} ```"), #[stable(feature = "int_to_from_bytes", since = "1.32.0")] #[rustc_const_unstable(feature = "const_int_conversion")] @@ -2037,6 +2063,19 @@ let value = ", stringify!($SelfT), "::from_ne_bytes(if cfg!(target_endian = \"bi ", $le_bytes, " }); assert_eq!(value, ", $swap_op, "); +``` + +When starting from a slice rather than an array, fallible conversion APIs can be used: + +``` +#![feature(try_from)] +use std::convert::TryInto; + +fn read_be_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), " { + let (int_bytes, rest) = input.split_at(std::mem::size_of::<", stringify!($SelfT), ">()); + *input = rest; + ", stringify!($SelfT), "::from_be_bytes(int_bytes.try_into().unwrap()) +} ```"), #[stable(feature = "int_to_from_bytes", since = "1.32.0")] #[rustc_const_unstable(feature = "const_int_conversion")] @@ -3719,6 +3758,19 @@ big endian. ``` let value = ", stringify!($SelfT), "::from_be_bytes(", $be_bytes, "); assert_eq!(value, ", $swap_op, "); +``` + +When starting from a slice rather than an array, fallible conversion APIs can be used: + +``` +#![feature(try_from)] +use std::convert::TryInto; + +fn read_be_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), " { + let (int_bytes, rest) = input.split_at(std::mem::size_of::<", stringify!($SelfT), ">()); + *input = rest; + ", stringify!($SelfT), "::from_be_bytes(int_bytes.try_into().unwrap()) +} ```"), #[stable(feature = "int_to_from_bytes", since = "1.32.0")] #[rustc_const_unstable(feature = "const_int_conversion")] @@ -3738,6 +3790,19 @@ little endian. ``` let value = ", stringify!($SelfT), "::from_le_bytes(", $le_bytes, "); assert_eq!(value, ", $swap_op, "); +``` + +When starting from a slice rather than an array, fallible conversion APIs can be used: + +``` +#![feature(try_from)] +use std::convert::TryInto; + +fn read_be_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), " { + let (int_bytes, rest) = input.split_at(std::mem::size_of::<", stringify!($SelfT), ">()); + *input = rest; + ", stringify!($SelfT), "::from_be_bytes(int_bytes.try_into().unwrap()) +} ```"), #[stable(feature = "int_to_from_bytes", since = "1.32.0")] #[rustc_const_unstable(feature = "const_int_conversion")] @@ -3767,6 +3832,19 @@ let value = ", stringify!($SelfT), "::from_ne_bytes(if cfg!(target_endian = \"bi ", $le_bytes, " }); assert_eq!(value, ", $swap_op, "); +``` + +When starting from a slice rather than an array, fallible conversion APIs can be used: + +``` +#![feature(try_from)] +use std::convert::TryInto; + +fn read_be_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), " { + let (int_bytes, rest) = input.split_at(std::mem::size_of::<", stringify!($SelfT), ">()); + *input = rest; + ", stringify!($SelfT), "::from_be_bytes(int_bytes.try_into().unwrap()) +} ```"), #[stable(feature = "int_to_from_bytes", since = "1.32.0")] #[rustc_const_unstable(feature = "const_int_conversion")] diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index 947b67e4e9af3..d3a74ed2a6856 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -189,12 +189,22 @@ pub use intrinsics::write_bytes; /// i.e., you do not usually have to worry about such issues unless you call `drop_in_place` /// manually. #[stable(feature = "drop_in_place", since = "1.8.0")] +#[inline(always)] +pub unsafe fn drop_in_place(to_drop: *mut T) { + real_drop_in_place(&mut *to_drop) +} + +// The real `drop_in_place` -- the one that gets called implicitly when variables go +// out of scope -- should have a safe reference and not a raw pointer as argument +// type. When we drop a local variable, we access it with a pointer that behaves +// like a safe reference; transmuting that to a raw pointer does not mean we can +// actually access it with raw pointers. #[lang = "drop_in_place"] #[allow(unconditional_recursion)] -pub unsafe fn drop_in_place(to_drop: *mut T) { +unsafe fn real_drop_in_place(to_drop: &mut T) { // Code here does not matter - this is replaced by the // real drop glue by the compiler. - drop_in_place(to_drop); + real_drop_in_place(to_drop) } /// Creates a null raw pointer. diff --git a/src/librustc/infer/lexical_region_resolve/graphviz.rs b/src/librustc/infer/lexical_region_resolve/graphviz.rs index a210d63f129e3..512e57d810aa4 100644 --- a/src/librustc/infer/lexical_region_resolve/graphviz.rs +++ b/src/librustc/infer/lexical_region_resolve/graphviz.rs @@ -31,9 +31,8 @@ use std::borrow::Cow; use std::collections::hash_map::Entry::Vacant; use std::collections::btree_map::BTreeMap; use std::env; -use std::fs::File; +use std::fs; use std::io; -use std::io::prelude::*; use std::sync::atomic::{AtomicBool, Ordering}; fn print_help_message() { @@ -268,5 +267,5 @@ fn dump_region_data_to<'a, 'gcx, 'tcx>(region_rels: &RegionRelations<'a, 'gcx, ' debug!("dump_region_data calling render"); let mut v = Vec::new(); dot::render(&g, &mut v).unwrap(); - File::create(path).and_then(|mut f| f.write_all(&v)) + fs::write(path, &v) } diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs index 0009a517dd1db..ab0094df0e219 100644 --- a/src/librustc/middle/reachable.rs +++ b/src/librustc/middle/reachable.rs @@ -117,8 +117,9 @@ impl<'a, 'tcx> Visitor<'tcx> for ReachableContext<'a, 'tcx> { self.reachable_symbols.insert(node_id); } Some(def) => { - let def_id = def.def_id(); - if let Some(node_id) = self.tcx.hir.as_local_node_id(def_id) { + if let Some((node_id, def_id)) = def.opt_def_id().and_then(|def_id| { + self.tcx.hir.as_local_node_id(def_id).map(|node_id| (node_id, def_id)) + }) { if self.def_id_represents_local_inlined_item(def_id) { self.worklist.push(node_id); } else { diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index 6ff450508d136..07054ee99af76 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -1573,7 +1573,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { .collect(); // ensure that we issue lints in a repeatable order - def_ids.sort_by_key(|&def_id| self.tcx.def_path_hash(def_id)); + def_ids.sort_by_cached_key(|&def_id| self.tcx.def_path_hash(def_id)); for def_id in def_ids { debug!( diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 3fd22793a08a0..480d4a8e48f0e 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -1286,8 +1286,6 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "print some performance-related statistics"), hir_stats: bool = (false, parse_bool, [UNTRACKED], "print some statistics about AST and HIR"), - mir_stats: bool = (false, parse_bool, [UNTRACKED], - "print some statistics about MIR"), always_encode_mir: bool = (false, parse_bool, [TRACKED], "encode MIR of all functions into the crate metadata"), osx_rpath_install_name: bool = (false, parse_bool, [TRACKED], diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs index c79fa3861234f..2909daf22b3ba 100644 --- a/src/librustc/traits/object_safety.rs +++ b/src/librustc/traits/object_safety.rs @@ -409,7 +409,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> { .collect::>(); // existential predicates need to be in a specific order - associated_types.sort_by_key(|item| self.def_path_hash(item.def_id)); + associated_types.sort_by_cached_key(|item| self.def_path_hash(item.def_id)); let projection_predicates = associated_types.into_iter().map(|item| { ty::ExistentialPredicate::Projection(ty::ExistentialProjection { diff --git a/src/librustc_codegen_llvm/back/write.rs b/src/librustc_codegen_llvm/back/write.rs index 7945d381760a1..4eb920324bd00 100644 --- a/src/librustc_codegen_llvm/back/write.rs +++ b/src/librustc_codegen_llvm/back/write.rs @@ -23,7 +23,7 @@ use llvm_util; use ModuleLlvm; use rustc_codegen_ssa::{ModuleCodegen, CompiledModule}; use rustc::util::common::time_ext; -use rustc_fs_util::{path2cstr, link_or_copy}; +use rustc_fs_util::{path_to_c_string, link_or_copy}; use rustc_data_structures::small_c_str::SmallCStr; use errors::{self, Handler, FatalError}; use type_::Type; @@ -80,7 +80,7 @@ pub fn write_output_file( output: &Path, file_type: llvm::FileType) -> Result<(), FatalError> { unsafe { - let output_c = path2cstr(output); + let output_c = path_to_c_string(output); let result = llvm::LLVMRustWriteOutputFile(target, pm, m, output_c.as_ptr(), file_type); if result.into_result().is_err() { let msg = format!("could not write output to {}", output.display()); @@ -211,7 +211,7 @@ pub(crate) fn save_temp_bitcode( let ext = format!("{}.bc", name); let cgu = Some(&module.name[..]); let path = cgcx.output_filenames.temp_path_ext(&ext, cgu); - let cstr = path2cstr(&path); + let cstr = path_to_c_string(&path); let llmod = module.module_llvm.llmod(); llvm::LLVMWriteBitcodeToFile(llmod, cstr.as_ptr()); } @@ -324,7 +324,7 @@ pub(crate) unsafe fn optimize(cgcx: &CodegenContext, if config.emit_no_opt_bc { let out = cgcx.output_filenames.temp_path_ext("no-opt.bc", module_name); - let out = path2cstr(&out); + let out = path_to_c_string(&out); llvm::LLVMWriteBitcodeToFile(llmod, out.as_ptr()); } @@ -530,7 +530,7 @@ pub(crate) unsafe fn codegen(cgcx: &CodegenContext, || -> Result<(), FatalError> { if config.emit_ir { let out = cgcx.output_filenames.temp_path(OutputType::LlvmAssembly, module_name); - let out = path2cstr(&out); + let out = path_to_c_string(&out); extern "C" fn demangle_callback(input_ptr: *const c_char, input_len: size_t, diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs index 81f2769800d2f..47e92fbe87d31 100644 --- a/src/librustc_codegen_llvm/debuginfo/metadata.rs +++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs @@ -39,7 +39,7 @@ use rustc::ty::layout::{self, Align, HasDataLayout, Integer, IntegerExt, LayoutO PrimitiveExt, Size, TyLayout}; use rustc::session::config; use rustc::util::nodemap::FxHashMap; -use rustc_fs_util::path2cstr; +use rustc_fs_util::path_to_c_string; use rustc_data_structures::small_c_str::SmallCStr; use libc::{c_uint, c_longlong}; @@ -892,7 +892,7 @@ pub fn compile_unit_metadata(tcx: TyCtxt, }; fn path_to_mdstring(llcx: &'ll llvm::Context, path: &Path) -> &'ll Value { - let path_str = path2cstr(path); + let path_str = path_to_c_string(path); unsafe { llvm::LLVMMDStringInContext(llcx, path_str.as_ptr(), diff --git a/src/librustc_codegen_llvm/llvm/archive_ro.rs b/src/librustc_codegen_llvm/llvm/archive_ro.rs index 2a77f256e3a0c..d5c73fecf814a 100644 --- a/src/librustc_codegen_llvm/llvm/archive_ro.rs +++ b/src/librustc_codegen_llvm/llvm/archive_ro.rs @@ -10,10 +10,10 @@ //! A wrapper around LLVM's archive (.a) code -use std::ffi::CString; use std::path::Path; use std::slice; use std::str; +use rustc_fs_util::path_to_c_string; pub struct ArchiveRO { pub raw: &'static mut super::Archive, @@ -38,24 +38,12 @@ impl ArchiveRO { /// raised. pub fn open(dst: &Path) -> Result { return unsafe { - let s = path2cstr(dst); + let s = path_to_c_string(dst); let ar = super::LLVMRustOpenArchive(s.as_ptr()).ok_or_else(|| { super::last_error().unwrap_or_else(|| "failed to open archive".to_owned()) })?; Ok(ArchiveRO { raw: ar }) }; - - #[cfg(unix)] - fn path2cstr(p: &Path) -> CString { - use std::os::unix::prelude::*; - use std::ffi::OsStr; - let p: &OsStr = p.as_ref(); - CString::new(p.as_bytes()).unwrap() - } - #[cfg(windows)] - fn path2cstr(p: &Path) -> CString { - CString::new(p.to_str().unwrap()).unwrap() - } } pub fn iter(&self) -> Iter { diff --git a/src/librustc_codegen_llvm/metadata.rs b/src/librustc_codegen_llvm/metadata.rs index 7752465d885bb..5605f64c2e72c 100644 --- a/src/librustc_codegen_llvm/metadata.rs +++ b/src/librustc_codegen_llvm/metadata.rs @@ -18,7 +18,7 @@ use rustc_data_structures::owning_ref::OwningRef; use std::path::Path; use std::ptr; use std::slice; -use rustc_fs_util::path2cstr; +use rustc_fs_util::path_to_c_string; pub use rustc_data_structures::sync::MetadataRef; @@ -57,7 +57,7 @@ impl MetadataLoader for LlvmMetadataLoader { filename: &Path) -> Result { unsafe { - let buf = path2cstr(filename); + let buf = path_to_c_string(filename); let mb = llvm::LLVMRustCreateMemoryBufferWithContentsOfFile(buf.as_ptr()) .ok_or_else(|| format!("error reading library: '{}'", filename.display()))?; let of = ObjectFile::new(mb) diff --git a/src/librustc_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs index b0575b841d5d5..24a70dc797771 100644 --- a/src/librustc_codegen_ssa/back/link.rs +++ b/src/librustc_codegen_ssa/back/link.rs @@ -161,7 +161,11 @@ pub fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) { LinkerFlavor::Lld(_) => "lld", }), flavor)), (Some(linker), None) => { - let stem = linker.file_stem().and_then(|stem| stem.to_str()).unwrap_or_else(|| { + let stem = if linker.extension().and_then(|ext| ext.to_str()) == Some("exe") { + linker.file_stem().and_then(|stem| stem.to_str()) + } else { + linker.to_str() + }.unwrap_or_else(|| { sess.fatal("couldn't extract file stem from specified linker"); }).to_owned(); diff --git a/src/librustc_codegen_utils/codegen_backend.rs b/src/librustc_codegen_utils/codegen_backend.rs index 046f0cccfee05..f1f798e770089 100644 --- a/src/librustc_codegen_utils/codegen_backend.rs +++ b/src/librustc_codegen_utils/codegen_backend.rs @@ -22,8 +22,8 @@ #![feature(box_syntax)] use std::any::Any; -use std::io::{self, Write}; -use std::fs::File; +use std::io::Write; +use std::fs; use std::path::Path; use std::sync::{mpsc, Arc}; @@ -81,12 +81,8 @@ pub struct NoLlvmMetadataLoader; impl MetadataLoader for NoLlvmMetadataLoader { fn get_rlib_metadata(&self, _: &Target, filename: &Path) -> Result { - let mut file = File::open(filename) - .map_err(|e| format!("metadata file open err: {:?}", e))?; - - let mut buf = Vec::new(); - io::copy(&mut file, &mut buf).unwrap(); - let buf: OwningRef, [u8]> = OwningRef::new(buf).into(); + let buf = fs::read(filename).map_err(|e| format!("metadata file open err: {:?}", e))?; + let buf: OwningRef, [u8]> = OwningRef::new(buf); return Ok(rustc_erase_owner!(buf.map_owner_box())); } @@ -212,8 +208,7 @@ impl CodegenBackend for MetadataOnlyCodegenBackend { } else { &ongoing_codegen.metadata.raw_data }; - let mut file = File::create(&output_name).unwrap(); - file.write_all(metadata).unwrap(); + fs::write(&output_name, metadata).unwrap(); } sess.abort_if_errors(); diff --git a/src/librustc_fs_util/lib.rs b/src/librustc_fs_util/lib.rs index ffe420b109d3e..1b0ff4f861c7b 100644 --- a/src/librustc_fs_util/lib.rs +++ b/src/librustc_fs_util/lib.rs @@ -116,13 +116,13 @@ pub fn rename_or_copy_remove, Q: AsRef>(p: P, } #[cfg(unix)] -pub fn path2cstr(p: &Path) -> CString { - use std::os::unix::prelude::*; +pub fn path_to_c_string(p: &Path) -> CString { + use std::os::unix::ffi::OsStrExt; use std::ffi::OsStr; let p: &OsStr = p.as_ref(); CString::new(p.as_bytes()).unwrap() } #[cfg(windows)] -pub fn path2cstr(p: &Path) -> CString { +pub fn path_to_c_string(p: &Path) -> CString { CString::new(p.to_str().unwrap()).unwrap() } diff --git a/src/librustc_mir/interpret/terminator.rs b/src/librustc_mir/interpret/terminator.rs index 617d204fe1042..300f3d639b588 100644 --- a/src/librustc_mir/interpret/terminator.rs +++ b/src/librustc_mir/interpret/terminator.rs @@ -182,6 +182,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> } fn check_argument_compat( + rust_abi: bool, caller: TyLayout<'tcx>, callee: TyLayout<'tcx>, ) -> bool { @@ -189,13 +190,20 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> // No question return true; } + if !rust_abi { + // Don't risk anything + return false; + } // Compare layout match (&caller.abi, &callee.abi) { + // Different valid ranges are okay (once we enforce validity, + // that will take care to make it UB to leave the range, just + // like for transmute). (layout::Abi::Scalar(ref caller), layout::Abi::Scalar(ref callee)) => - // Different valid ranges are okay (once we enforce validity, - // that will take care to make it UB to leave the range, just - // like for transmute). caller.value == callee.value, + (layout::Abi::ScalarPair(ref caller1, ref caller2), + layout::Abi::ScalarPair(ref callee1, ref callee2)) => + caller1.value == callee1.value && caller2.value == callee2.value, // Be conservative _ => false } @@ -204,22 +212,22 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> /// Pass a single argument, checking the types for compatibility. fn pass_argument( &mut self, - skip_zst: bool, + rust_abi: bool, caller_arg: &mut impl Iterator>, callee_arg: PlaceTy<'tcx, M::PointerTag>, ) -> EvalResult<'tcx> { - if skip_zst && callee_arg.layout.is_zst() { + if rust_abi && callee_arg.layout.is_zst() { // Nothing to do. trace!("Skipping callee ZST"); return Ok(()); } let caller_arg = caller_arg.next() .ok_or_else(|| EvalErrorKind::FunctionArgCountMismatch)?; - if skip_zst { + if rust_abi { debug_assert!(!caller_arg.layout.is_zst(), "ZSTs must have been already filtered out"); } // Now, check - if !Self::check_argument_compat(caller_arg.layout, callee_arg.layout) { + if !Self::check_argument_compat(rust_abi, caller_arg.layout, callee_arg.layout) { return err!(FunctionArgMismatch(caller_arg.layout.ty, callee_arg.layout.ty)); } // We allow some transmutes here @@ -319,7 +327,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> // Figure out how to pass which arguments. // We have two iterators: Where the arguments come from, // and where they go to. - let skip_zst = match caller_abi { + let rust_abi = match caller_abi { Abi::Rust | Abi::RustCall => true, _ => false }; @@ -344,7 +352,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> }; // Skip ZSTs let mut caller_iter = caller_args.iter() - .filter(|op| !skip_zst || !op.layout.is_zst()) + .filter(|op| !rust_abi || !op.layout.is_zst()) .map(|op| *op); // Now we have to spread them out across the callee's locals, @@ -359,11 +367,11 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> // Must be a tuple for i in 0..dest.layout.fields.count() { let dest = self.place_field(dest, i as u64)?; - self.pass_argument(skip_zst, &mut caller_iter, dest)?; + self.pass_argument(rust_abi, &mut caller_iter, dest)?; } } else { // Normal argument - self.pass_argument(skip_zst, &mut caller_iter, dest)?; + self.pass_argument(rust_abi, &mut caller_iter, dest)?; } } // Now we should have no more caller args @@ -374,7 +382,11 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> // Don't forget to check the return type! if let Some(caller_ret) = dest { let callee_ret = self.eval_place(&mir::Place::Local(mir::RETURN_PLACE))?; - if !Self::check_argument_compat(caller_ret.layout, callee_ret.layout) { + if !Self::check_argument_compat( + rust_abi, + caller_ret.layout, + callee_ret.layout, + ) { return err!(FunctionRetMismatch( caller_ret.layout.ty, callee_ret.layout.ty )); diff --git a/src/librustc_mir/monomorphize/partitioning.rs b/src/librustc_mir/monomorphize/partitioning.rs index 6dba020120f84..3a6ee6da42215 100644 --- a/src/librustc_mir/monomorphize/partitioning.rs +++ b/src/librustc_mir/monomorphize/partitioning.rs @@ -985,7 +985,7 @@ fn collect_and_partition_mono_items<'a, 'tcx>( output.push_str(" @@"); let mut empty = Vec::new(); let cgus = item_to_cgus.get_mut(i).unwrap_or(&mut empty); - cgus.as_mut_slice().sort_by_key(|&(ref name, _)| name.clone()); + cgus.as_mut_slice().sort_by_cached_key(|&(ref name, _)| name.clone()); cgus.dedup(); for &(ref cgu_name, (linkage, _)) in cgus.iter() { output.push_str(" "); diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index 93bf1b3e36e38..04079319a7877 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -226,8 +226,13 @@ fn build_drop_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // The first argument (index 0), but add 1 for the return value. let dropee_ptr = Place::Local(Local::new(1+0)); if tcx.sess.opts.debugging_opts.mir_emit_retag { - // We use raw ptr operations, better prepare the alias tracking for that + // Function arguments should be retagged mir.basic_blocks_mut()[START_BLOCK].statements.insert(0, Statement { + source_info, + kind: StatementKind::Retag { fn_entry: true, place: dropee_ptr.clone() }, + }); + // We use raw ptr operations, better prepare the alias tracking for that + mir.basic_blocks_mut()[START_BLOCK].statements.insert(1, Statement { source_info, kind: StatementKind::EscapeToRaw(Operand::Copy(dropee_ptr.clone())), }) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index b46efb20d8f6b..6a7b351540fdd 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -778,10 +778,7 @@ fn write_shared( let mut themes: FxHashSet = FxHashSet::default(); for entry in &cx.shared.themes { - let mut content = Vec::with_capacity(100000); - - let mut f = try_err!(File::open(&entry), &entry); - try_err!(f.read_to_end(&mut content), &entry); + let content = try_err!(fs::read(&entry), &entry); let theme = try_none!(try_none!(entry.file_stem(), &entry).to_str(), &entry); let extension = try_none!(try_none!(entry.extension(), &entry).to_str(), &entry); write(cx.dst.join(format!("{}{}.{}", theme, cx.shared.resource_suffix, extension)), @@ -874,10 +871,7 @@ themePicker.onblur = handleThemeButtonsBlur; if !options.enable_minification { try_err!(fs::copy(css, out), css); } else { - let mut f = try_err!(File::open(css), css); - let mut buffer = String::with_capacity(1000); - - try_err!(f.read_to_string(&mut buffer), css); + let buffer = try_err!(fs::read_to_string(css), css); write_minify(out, &buffer, options.enable_minification)?; } } @@ -2016,8 +2010,7 @@ impl Context { if !buf.is_empty() { try_err!(this.shared.ensure_dir(&this.dst), &this.dst); let joint_dst = this.dst.join("index.html"); - let mut dst = try_err!(File::create(&joint_dst), &joint_dst); - try_err!(dst.write_all(&buf), &joint_dst); + try_err!(fs::write(&joint_dst, buf), &joint_dst); } let m = match item.inner { @@ -2051,8 +2044,7 @@ impl Context { let file_name = &item_path(item_type, name); try_err!(self.shared.ensure_dir(&self.dst), &self.dst); let joint_dst = self.dst.join(file_name); - let mut dst = try_err!(File::create(&joint_dst), &joint_dst); - try_err!(dst.write_all(&buf), &joint_dst); + try_err!(fs::write(&joint_dst, buf), &joint_dst); if !self.render_redirect_pages { all.append(full_path(self, &item), &item_type); diff --git a/src/librustdoc/theme.rs b/src/librustdoc/theme.rs index 55a11d1976599..206a72cebfef8 100644 --- a/src/librustdoc/theme.rs +++ b/src/librustdoc/theme.rs @@ -9,9 +9,8 @@ // except according to those terms. use rustc_data_structures::fx::FxHashSet; -use std::fs::File; +use std::fs; use std::hash::{Hash, Hasher}; -use std::io::Read; use std::path::Path; use errors::Handler; @@ -278,12 +277,9 @@ pub fn get_differences(against: &CssPath, other: &CssPath, v: &mut Vec) pub fn test_theme_against>(f: &P, against: &CssPath, diag: &Handler) -> (bool, Vec) { - let mut file = try_something!(File::open(f), diag, (false, Vec::new())); - let mut data = Vec::with_capacity(1000); - - try_something!(file.read_to_end(&mut data), diag, (false, Vec::new())); + let data = try_something!(fs::read(f), diag, (false, vec![])); let paths = load_css_paths(&data); - let mut ret = Vec::new(); + let mut ret = vec![]; get_differences(against, &paths, &mut ret); (true, ret) } diff --git a/src/libserialize/collection_impls.rs b/src/libserialize/collection_impls.rs index 3e028d755c6d4..cbd642dd6ad91 100644 --- a/src/libserialize/collection_impls.rs +++ b/src/libserialize/collection_impls.rs @@ -86,7 +86,7 @@ impl Encodable for VecDeque { impl Decodable for VecDeque { fn decode(d: &mut D) -> Result, D::Error> { d.read_seq(|d, len| { - let mut deque: VecDeque = VecDeque::new(); + let mut deque: VecDeque = VecDeque::with_capacity(len); for i in 0..len { deque.push_back(d.read_seq_elt(i, |d| Decodable::decode(d))?); } diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index cc8af70a050c9..e2913f399fdb9 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -34,8 +34,8 @@ use tokenstream::{TokenStream, TokenTree}; use visit::{self, Visitor}; use rustc_data_structures::fx::FxHashMap; -use std::fs::File; -use std::io::Read; +use std::fs; +use std::io::ErrorKind; use std::{iter, mem}; use std::rc::Rc; use std::path::PathBuf; @@ -1201,50 +1201,62 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { impl<'a, 'b> Folder for InvocationCollector<'a, 'b> { fn fold_expr(&mut self, expr: P) -> P { - let mut expr = self.cfg.configure_expr(expr).into_inner(); - expr.node = self.cfg.configure_expr_kind(expr.node); - - // ignore derives so they remain unused - let (attr, expr, after_derive) = self.classify_nonitem(expr); - - if attr.is_some() { - // collect the invoc regardless of whether or not attributes are permitted here - // expansion will eat the attribute so it won't error later - attr.as_ref().map(|a| self.cfg.maybe_emit_expr_attr_err(a)); - - // AstFragmentKind::Expr requires the macro to emit an expression - return self.collect_attr(attr, vec![], Annotatable::Expr(P(expr)), - AstFragmentKind::Expr, after_derive).make_expr(); - } + let expr = self.cfg.configure_expr(expr); + expr.map(|mut expr| { + expr.node = self.cfg.configure_expr_kind(expr.node); + + // ignore derives so they remain unused + let (attr, expr, after_derive) = self.classify_nonitem(expr); + + if attr.is_some() { + // Collect the invoc regardless of whether or not attributes are permitted here + // expansion will eat the attribute so it won't error later. + attr.as_ref().map(|a| self.cfg.maybe_emit_expr_attr_err(a)); + + // AstFragmentKind::Expr requires the macro to emit an expression. + return self.collect_attr(attr, vec![], Annotatable::Expr(P(expr)), + AstFragmentKind::Expr, after_derive) + .make_expr() + .into_inner() + } - if let ast::ExprKind::Mac(mac) = expr.node { - self.check_attributes(&expr.attrs); - self.collect_bang(mac, expr.span, AstFragmentKind::Expr).make_expr() - } else { - P(noop_fold_expr(expr, self)) - } + if let ast::ExprKind::Mac(mac) = expr.node { + self.check_attributes(&expr.attrs); + self.collect_bang(mac, expr.span, AstFragmentKind::Expr) + .make_expr() + .into_inner() + } else { + noop_fold_expr(expr, self) + } + }) } fn fold_opt_expr(&mut self, expr: P) -> Option> { - let mut expr = configure!(self, expr).into_inner(); - expr.node = self.cfg.configure_expr_kind(expr.node); + let expr = configure!(self, expr); + expr.filter_map(|mut expr| { + expr.node = self.cfg.configure_expr_kind(expr.node); - // ignore derives so they remain unused - let (attr, expr, after_derive) = self.classify_nonitem(expr); + // Ignore derives so they remain unused. + let (attr, expr, after_derive) = self.classify_nonitem(expr); - if attr.is_some() { - attr.as_ref().map(|a| self.cfg.maybe_emit_expr_attr_err(a)); + if attr.is_some() { + attr.as_ref().map(|a| self.cfg.maybe_emit_expr_attr_err(a)); - return self.collect_attr(attr, vec![], Annotatable::Expr(P(expr)), - AstFragmentKind::OptExpr, after_derive).make_opt_expr(); - } + return self.collect_attr(attr, vec![], Annotatable::Expr(P(expr)), + AstFragmentKind::OptExpr, after_derive) + .make_opt_expr() + .map(|expr| expr.into_inner()) + } - if let ast::ExprKind::Mac(mac) = expr.node { - self.check_attributes(&expr.attrs); - self.collect_bang(mac, expr.span, AstFragmentKind::OptExpr).make_opt_expr() - } else { - Some(P(noop_fold_expr(expr, self))) - } + if let ast::ExprKind::Mac(mac) = expr.node { + self.check_attributes(&expr.attrs); + self.collect_bang(mac, expr.span, AstFragmentKind::OptExpr) + .make_opt_expr() + .map(|expr| expr.into_inner()) + } else { + Some(noop_fold_expr(expr, self)) + } + }) } fn fold_pat(&mut self, pat: P) -> P { @@ -1507,20 +1519,8 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> { return noop_fold_attribute(at, self); } - let mut buf = vec![]; let filename = self.cx.root_path.join(file.to_string()); - - match File::open(&filename).and_then(|mut f| f.read_to_end(&mut buf)) { - Ok(..) => {} - Err(e) => { - self.cx.span_err(at.span, - &format!("couldn't read {}: {}", - filename.display(), - e)); - } - } - - match String::from_utf8(buf) { + match fs::read_to_string(&filename) { Ok(src) => { let src_interned = Symbol::intern(&src); @@ -1530,21 +1530,34 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> { let include_info = vec![ dummy_spanned(ast::NestedMetaItemKind::MetaItem( - attr::mk_name_value_item_str(Ident::from_str("file"), - dummy_spanned(file)))), + attr::mk_name_value_item_str( + Ident::from_str("file"), + dummy_spanned(file), + ), + )), dummy_spanned(ast::NestedMetaItemKind::MetaItem( - attr::mk_name_value_item_str(Ident::from_str("contents"), - dummy_spanned(src_interned)))), + attr::mk_name_value_item_str( + Ident::from_str("contents"), + dummy_spanned(src_interned), + ), + )), ]; let include_ident = Ident::from_str("include"); let item = attr::mk_list_item(DUMMY_SP, include_ident, include_info); items.push(dummy_spanned(ast::NestedMetaItemKind::MetaItem(item))); } - Err(_) => { - self.cx.span_err(at.span, - &format!("{} wasn't a utf-8 file", - filename.display())); + Err(ref e) if e.kind() == ErrorKind::InvalidData => { + self.cx.span_err( + at.span, + &format!("{} wasn't a utf-8 file", filename.display()), + ); + } + Err(e) => { + self.cx.span_err( + at.span, + &format!("couldn't read {}: {}", filename.display(), e), + ); } } } else { diff --git a/src/libsyntax/ext/source_util.rs b/src/libsyntax/ext/source_util.rs index e1ba8897a47f4..a7875b0ba0506 100644 --- a/src/libsyntax/ext/source_util.rs +++ b/src/libsyntax/ext/source_util.rs @@ -21,8 +21,8 @@ use smallvec::SmallVec; use symbol::Symbol; use tokenstream; -use std::fs::File; -use std::io::prelude::*; +use std::fs; +use std::io::ErrorKind; use std::path::PathBuf; use rustc_data_structures::sync::Lrc; @@ -137,18 +137,7 @@ pub fn expand_include_str(cx: &mut ExtCtxt, sp: Span, tts: &[tokenstream::TokenT None => return DummyResult::expr(sp) }; let file = res_rel_file(cx, sp, file); - let mut bytes = Vec::new(); - match File::open(&file).and_then(|mut f| f.read_to_end(&mut bytes)) { - Ok(..) => {} - Err(e) => { - cx.span_err(sp, - &format!("couldn't read {}: {}", - file.display(), - e)); - return DummyResult::expr(sp); - } - }; - match String::from_utf8(bytes) { + match fs::read_to_string(&file) { Ok(src) => { let interned_src = Symbol::intern(&src); @@ -157,11 +146,13 @@ pub fn expand_include_str(cx: &mut ExtCtxt, sp: Span, tts: &[tokenstream::TokenT cx.source_map().new_source_file(file.into(), src); base::MacEager::expr(cx.expr_str(sp, interned_src)) + }, + Err(ref e) if e.kind() == ErrorKind::InvalidData => { + cx.span_err(sp, &format!("{} wasn't a utf-8 file", file.display())); + DummyResult::expr(sp) } - Err(_) => { - cx.span_err(sp, - &format!("{} wasn't a utf-8 file", - file.display())); + Err(e) => { + cx.span_err(sp, &format!("couldn't read {}: {}", file.display(), e)); DummyResult::expr(sp) } } @@ -174,20 +165,18 @@ pub fn expand_include_bytes(cx: &mut ExtCtxt, sp: Span, tts: &[tokenstream::Toke None => return DummyResult::expr(sp) }; let file = res_rel_file(cx, sp, file); - let mut bytes = Vec::new(); - match File::open(&file).and_then(|mut f| f.read_to_end(&mut bytes)) { - Err(e) => { - cx.span_err(sp, - &format!("couldn't read {}: {}", file.display(), e)); - DummyResult::expr(sp) - } - Ok(..) => { + match fs::read(&file) { + Ok(bytes) => { // Add this input file to the code map to make it available as // dependency information, but don't enter it's contents cx.source_map().new_source_file(file.into(), String::new()); base::MacEager::expr(cx.expr_lit(sp, ast::LitKind::ByteStr(Lrc::new(bytes)))) } + Err(e) => { + cx.span_err(sp, &format!("couldn't read {}: {}", file.display(), e)); + DummyResult::expr(sp) + } } } diff --git a/src/libsyntax/ptr.rs b/src/libsyntax/ptr.rs index bb47d9b535bef..9fbc64758da4d 100644 --- a/src/libsyntax/ptr.rs +++ b/src/libsyntax/ptr.rs @@ -72,7 +72,7 @@ impl P { *self.ptr } - /// Transform the inner value, consuming `self` and producing a new `P`. + /// Produce a new `P` from `self` without reallocating. pub fn map(mut self, f: F) -> P where F: FnOnce(T) -> T, { @@ -88,8 +88,30 @@ impl P { ptr::write(p, f(ptr::read(p))); // Recreate self from the raw pointer. - P { - ptr: Box::from_raw(p) + P { ptr: Box::from_raw(p) } + } + } + + /// Optionally produce a new `P` from `self` without reallocating. + pub fn filter_map(mut self, f: F) -> Option> where + F: FnOnce(T) -> Option, + { + let p: *mut T = &mut *self.ptr; + + // Leak self in case of panic. + // FIXME(eddyb) Use some sort of "free guard" that + // only deallocates, without dropping the pointee, + // in case the call the `f` below ends in a panic. + mem::forget(self); + + unsafe { + if let Some(v) = f(ptr::read(p)) { + ptr::write(p, v); + + // Recreate self from the raw pointer. + Some(P { ptr: Box::from_raw(p) }) + } else { + None } } } diff --git a/src/libsyntax/source_map.rs b/src/libsyntax/source_map.rs index e8cacc3b5aff3..ff158b8369cb7 100644 --- a/src/libsyntax/source_map.rs +++ b/src/libsyntax/source_map.rs @@ -31,7 +31,7 @@ use std::path::{Path, PathBuf}; use std::env; use std::fs; -use std::io::{self, Read}; +use std::io; use errors::SourceMapper; /// Return the span itself if it doesn't come from a macro expansion, @@ -96,9 +96,7 @@ impl FileLoader for RealFileLoader { } fn read_file(&self, path: &Path) -> io::Result { - let mut src = String::new(); - fs::File::open(path)?.read_to_string(&mut src)?; - Ok(src) + fs::read_to_string(path) } } diff --git a/src/test/codegen-units/item-collection/drop_in_place_intrinsic.rs b/src/test/codegen-units/item-collection/drop_in_place_intrinsic.rs index cec88f1c6a245..1793a311f968a 100644 --- a/src/test/codegen-units/item-collection/drop_in_place_intrinsic.rs +++ b/src/test/codegen-units/item-collection/drop_in_place_intrinsic.rs @@ -14,7 +14,7 @@ #![feature(start)] -//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0] @@ drop_in_place_intrinsic-cgu.0[Internal] +//~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0] @@ drop_in_place_intrinsic-cgu.0[Internal] struct StructWithDtor(u32); impl Drop for StructWithDtor { @@ -26,7 +26,7 @@ impl Drop for StructWithDtor { #[start] fn start(_: isize, _: *const *const u8) -> isize { - //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<[drop_in_place_intrinsic::StructWithDtor[0]; 2]> @@ drop_in_place_intrinsic-cgu.0[Internal] + //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<[drop_in_place_intrinsic::StructWithDtor[0]; 2]> @@ drop_in_place_intrinsic-cgu.0[Internal] let x = [StructWithDtor(0), StructWithDtor(1)]; drop_slice_in_place(&x); @@ -41,6 +41,7 @@ fn drop_slice_in_place(x: &[StructWithDtor]) { // not have drop-glue for the unsized [StructWithDtor]. This has to be // generated though when the drop_in_place() intrinsic is used. //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<[drop_in_place_intrinsic::StructWithDtor[0]]> @@ drop_in_place_intrinsic-cgu.0[Internal] + //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<[drop_in_place_intrinsic::StructWithDtor[0]]> @@ drop_in_place_intrinsic-cgu.0[Internal] ::std::ptr::drop_in_place(x as *const _ as *mut [StructWithDtor]); } } diff --git a/src/test/codegen-units/item-collection/generic-drop-glue.rs b/src/test/codegen-units/item-collection/generic-drop-glue.rs index 5afa519bc5902..4ae5832ec4ed4 100644 --- a/src/test/codegen-units/item-collection/generic-drop-glue.rs +++ b/src/test/codegen-units/item-collection/generic-drop-glue.rs @@ -47,7 +47,7 @@ enum EnumNoDrop { struct NonGenericNoDrop(i32); struct NonGenericWithDrop(i32); -//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0] @@ generic_drop_glue-cgu.0[Internal] +//~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0] @@ generic_drop_glue-cgu.0[Internal] impl Drop for NonGenericWithDrop { //~ MONO_ITEM fn generic_drop_glue::{{impl}}[2]::drop[0] @@ -57,11 +57,11 @@ impl Drop for NonGenericWithDrop { //~ MONO_ITEM fn generic_drop_glue::start[0] #[start] fn start(_: isize, _: *const *const u8) -> isize { - //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]> @@ generic_drop_glue-cgu.0[Internal] + //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]> @@ generic_drop_glue-cgu.0[Internal] //~ MONO_ITEM fn generic_drop_glue::{{impl}}[0]::drop[0] let _ = StructWithDrop { x: 0i8, y: 'a' }.x; - //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]> @@ generic_drop_glue-cgu.0[Internal] + //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]> @@ generic_drop_glue-cgu.0[Internal] //~ MONO_ITEM fn generic_drop_glue::{{impl}}[0]::drop[0]<&str, generic_drop_glue::NonGenericNoDrop[0]> let _ = StructWithDrop { x: "&str", y: NonGenericNoDrop(0) }.y; @@ -70,17 +70,17 @@ fn start(_: isize, _: *const *const u8) -> isize { // This is supposed to generate drop-glue because it contains a field that // needs to be dropped. - //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]> @@ generic_drop_glue-cgu.0[Internal] + //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]> @@ generic_drop_glue-cgu.0[Internal] let _ = StructNoDrop { x: NonGenericWithDrop(0), y: 0f64 }.y; - //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]> @@ generic_drop_glue-cgu.0[Internal] + //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]> @@ generic_drop_glue-cgu.0[Internal] //~ MONO_ITEM fn generic_drop_glue::{{impl}}[1]::drop[0] let _ = match EnumWithDrop::A::(0) { EnumWithDrop::A(x) => x, EnumWithDrop::B(x) => x as i32 }; - //~MONO_ITEM fn core::ptr[0]::drop_in_place[0]> @@ generic_drop_glue-cgu.0[Internal] + //~MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]> @@ generic_drop_glue-cgu.0[Internal] //~ MONO_ITEM fn generic_drop_glue::{{impl}}[1]::drop[0] let _ = match EnumWithDrop::B::(1.0) { EnumWithDrop::A(x) => x, diff --git a/src/test/codegen-units/item-collection/instantiation-through-vtable.rs b/src/test/codegen-units/item-collection/instantiation-through-vtable.rs index d09d343a8458e..bfa67b16d0e63 100644 --- a/src/test/codegen-units/item-collection/instantiation-through-vtable.rs +++ b/src/test/codegen-units/item-collection/instantiation-through-vtable.rs @@ -34,13 +34,13 @@ impl Trait for Struct { fn start(_: isize, _: *const *const u8) -> isize { let s1 = Struct { _a: 0u32 }; - //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]> @@ instantiation_through_vtable-cgu.0[Internal] + //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]> @@ instantiation_through_vtable-cgu.0[Internal] //~ MONO_ITEM fn instantiation_through_vtable::{{impl}}[0]::foo[0] //~ MONO_ITEM fn instantiation_through_vtable::{{impl}}[0]::bar[0] let _ = &s1 as &Trait; let s1 = Struct { _a: 0u64 }; - //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]> @@ instantiation_through_vtable-cgu.0[Internal] + //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]> @@ instantiation_through_vtable-cgu.0[Internal] //~ MONO_ITEM fn instantiation_through_vtable::{{impl}}[0]::foo[0] //~ MONO_ITEM fn instantiation_through_vtable::{{impl}}[0]::bar[0] let _ = &s1 as &Trait; diff --git a/src/test/codegen-units/item-collection/non-generic-drop-glue.rs b/src/test/codegen-units/item-collection/non-generic-drop-glue.rs index a939dd56cda5b..2d72383391daa 100644 --- a/src/test/codegen-units/item-collection/non-generic-drop-glue.rs +++ b/src/test/codegen-units/item-collection/non-generic-drop-glue.rs @@ -15,7 +15,7 @@ #![deny(dead_code)] #![feature(start)] -//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0] @@ non_generic_drop_glue-cgu.0[Internal] +//~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0] @@ non_generic_drop_glue-cgu.0[Internal] struct StructWithDrop { x: i32 } @@ -29,7 +29,7 @@ struct StructNoDrop { x: i32 } -//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0] @@ non_generic_drop_glue-cgu.0[Internal] +//~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0] @@ non_generic_drop_glue-cgu.0[Internal] enum EnumWithDrop { A(i32) } diff --git a/src/test/codegen-units/item-collection/transitive-drop-glue.rs b/src/test/codegen-units/item-collection/transitive-drop-glue.rs index 7bbc9b6d0fbc9..d90171726b2c6 100644 --- a/src/test/codegen-units/item-collection/transitive-drop-glue.rs +++ b/src/test/codegen-units/item-collection/transitive-drop-glue.rs @@ -15,11 +15,11 @@ #![deny(dead_code)] #![feature(start)] -//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0] @@ transitive_drop_glue-cgu.0[Internal] +//~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0] @@ transitive_drop_glue-cgu.0[Internal] struct Root(Intermediate); -//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0] @@ transitive_drop_glue-cgu.0[Internal] +//~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0] @@ transitive_drop_glue-cgu.0[Internal] struct Intermediate(Leaf); -//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0] @@ transitive_drop_glue-cgu.0[Internal] +//~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0] @@ transitive_drop_glue-cgu.0[Internal] struct Leaf; impl Drop for Leaf { @@ -40,15 +40,15 @@ impl Drop for LeafGen { fn start(_: isize, _: *const *const u8) -> isize { let _ = Root(Intermediate(Leaf)); - //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]> @@ transitive_drop_glue-cgu.0[Internal] - //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]> @@ transitive_drop_glue-cgu.0[Internal] - //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]> @@ transitive_drop_glue-cgu.0[Internal] + //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]> @@ transitive_drop_glue-cgu.0[Internal] + //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]> @@ transitive_drop_glue-cgu.0[Internal] + //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]> @@ transitive_drop_glue-cgu.0[Internal] //~ MONO_ITEM fn transitive_drop_glue::{{impl}}[1]::drop[0] let _ = RootGen(IntermediateGen(LeafGen(0u32))); - //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]> @@ transitive_drop_glue-cgu.0[Internal] - //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]> @@ transitive_drop_glue-cgu.0[Internal] - //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]> @@ transitive_drop_glue-cgu.0[Internal] + //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]> @@ transitive_drop_glue-cgu.0[Internal] + //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]> @@ transitive_drop_glue-cgu.0[Internal] + //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]> @@ transitive_drop_glue-cgu.0[Internal] //~ MONO_ITEM fn transitive_drop_glue::{{impl}}[1]::drop[0] let _ = RootGen(IntermediateGen(LeafGen(0i16))); diff --git a/src/test/codegen-units/item-collection/tuple-drop-glue.rs b/src/test/codegen-units/item-collection/tuple-drop-glue.rs index 865570ccfa55a..e94af0c2989b2 100644 --- a/src/test/codegen-units/item-collection/tuple-drop-glue.rs +++ b/src/test/codegen-units/item-collection/tuple-drop-glue.rs @@ -15,7 +15,7 @@ #![deny(dead_code)] #![feature(start)] -//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0] @@ tuple_drop_glue-cgu.0[Internal] +//~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0] @@ tuple_drop_glue-cgu.0[Internal] struct Dropped; impl Drop for Dropped { @@ -26,11 +26,11 @@ impl Drop for Dropped { //~ MONO_ITEM fn tuple_drop_glue::start[0] #[start] fn start(_: isize, _: *const *const u8) -> isize { - //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<(u32, tuple_drop_glue::Dropped[0])> @@ tuple_drop_glue-cgu.0[Internal] + //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<(u32, tuple_drop_glue::Dropped[0])> @@ tuple_drop_glue-cgu.0[Internal] let x = (0u32, Dropped); - //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<(i16, (tuple_drop_glue::Dropped[0], bool))> @@ tuple_drop_glue-cgu.0[Internal] - //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<(tuple_drop_glue::Dropped[0], bool)> @@ tuple_drop_glue-cgu.0[Internal] + //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<(i16, (tuple_drop_glue::Dropped[0], bool))> @@ tuple_drop_glue-cgu.0[Internal] + //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<(tuple_drop_glue::Dropped[0], bool)> @@ tuple_drop_glue-cgu.0[Internal] let x = (0i16, (Dropped, true)); 0 diff --git a/src/test/codegen-units/item-collection/unsizing.rs b/src/test/codegen-units/item-collection/unsizing.rs index 5e9a3258c7adf..c85f7fc1bdd8d 100644 --- a/src/test/codegen-units/item-collection/unsizing.rs +++ b/src/test/codegen-units/item-collection/unsizing.rs @@ -59,13 +59,13 @@ impl, U: ?Sized> CoerceUnsized> for Wrapper fn start(_: isize, _: *const *const u8) -> isize { // simple case let bool_sized = &true; - //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0] @@ unsizing-cgu.0[Internal] + //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0] @@ unsizing-cgu.0[Internal] //~ MONO_ITEM fn unsizing::{{impl}}[0]::foo[0] let _bool_unsized = bool_sized as &Trait; let char_sized = &'a'; - //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0] @@ unsizing-cgu.0[Internal] + //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0] @@ unsizing-cgu.0[Internal] //~ MONO_ITEM fn unsizing::{{impl}}[1]::foo[0] let _char_unsized = char_sized as &Trait; @@ -75,13 +75,13 @@ fn start(_: isize, _: *const *const u8) -> isize { _b: 2, _c: 3.0f64 }; - //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0] @@ unsizing-cgu.0[Internal] + //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0] @@ unsizing-cgu.0[Internal] //~ MONO_ITEM fn unsizing::{{impl}}[2]::foo[0] let _struct_unsized = struct_sized as &Struct; // custom coercion let wrapper_sized = Wrapper(&0u32); - //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0] @@ unsizing-cgu.0[Internal] + //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0] @@ unsizing-cgu.0[Internal] //~ MONO_ITEM fn unsizing::{{impl}}[3]::foo[0] let _wrapper_sized = wrapper_sized as Wrapper; diff --git a/src/test/codegen-units/partitioning/extern-drop-glue.rs b/src/test/codegen-units/partitioning/extern-drop-glue.rs index cbad3a638840c..87b4430b4cab6 100644 --- a/src/test/codegen-units/partitioning/extern-drop-glue.rs +++ b/src/test/codegen-units/partitioning/extern-drop-glue.rs @@ -21,14 +21,14 @@ // aux-build:cgu_extern_drop_glue.rs extern crate cgu_extern_drop_glue; -//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0] @@ extern_drop_glue[Internal] extern_drop_glue-mod1[Internal] +//~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0] @@ extern_drop_glue[Internal] extern_drop_glue-mod1[Internal] struct LocalStruct(cgu_extern_drop_glue::Struct); //~ MONO_ITEM fn extern_drop_glue::user[0] @@ extern_drop_glue[External] pub fn user() { - //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0] @@ extern_drop_glue[Internal] + //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0] @@ extern_drop_glue[Internal] let _ = LocalStruct(cgu_extern_drop_glue::Struct(0)); } @@ -40,7 +40,7 @@ pub mod mod1 { //~ MONO_ITEM fn extern_drop_glue::mod1[0]::user[0] @@ extern_drop_glue-mod1[External] pub fn user() { - //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0] @@ extern_drop_glue-mod1[Internal] + //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0] @@ extern_drop_glue-mod1[Internal] let _ = LocalStruct(cgu_extern_drop_glue::Struct(0)); } } diff --git a/src/test/codegen-units/partitioning/local-drop-glue.rs b/src/test/codegen-units/partitioning/local-drop-glue.rs index 98729d99ea950..e09eb318708e1 100644 --- a/src/test/codegen-units/partitioning/local-drop-glue.rs +++ b/src/test/codegen-units/partitioning/local-drop-glue.rs @@ -17,7 +17,7 @@ #![allow(dead_code)] #![crate_type="rlib"] -//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0] @@ local_drop_glue[Internal] local_drop_glue-mod1[Internal] +//~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0] @@ local_drop_glue[Internal] local_drop_glue-mod1[Internal] struct Struct { _a: u32 } @@ -27,7 +27,7 @@ impl Drop for Struct { fn drop(&mut self) {} } -//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0] @@ local_drop_glue[Internal] +//~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0] @@ local_drop_glue[Internal] struct Outer { _a: Struct } @@ -46,10 +46,10 @@ pub mod mod1 { use super::Struct; - //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0] @@ local_drop_glue-mod1[Internal] + //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0] @@ local_drop_glue-mod1[Internal] struct Struct2 { _a: Struct, - //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<(u32, local_drop_glue::Struct[0])> @@ local_drop_glue-mod1[Internal] + //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<(u32, local_drop_glue::Struct[0])> @@ local_drop_glue-mod1[Internal] _b: (u32, Struct), } diff --git a/src/test/codegen-units/partitioning/vtable-through-const.rs b/src/test/codegen-units/partitioning/vtable-through-const.rs index ebda08a29f66d..459c6b6f15410 100644 --- a/src/test/codegen-units/partitioning/vtable-through-const.rs +++ b/src/test/codegen-units/partitioning/vtable-through-const.rs @@ -76,7 +76,7 @@ mod mod1 { //~ MONO_ITEM fn vtable_through_const::start[0] #[start] fn start(_: isize, _: *const *const u8) -> isize { - //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0] @@ vtable_through_const[Internal] + //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0] @@ vtable_through_const[Internal] // Since Trait1::do_something() is instantiated via its default implementation, // it is considered a generic and is instantiated here only because it is diff --git a/src/test/run-make/llvm-outputs/Makefile b/src/test/run-make/llvm-outputs/Makefile new file mode 100644 index 0000000000000..d7f67577b04ce --- /dev/null +++ b/src/test/run-make/llvm-outputs/Makefile @@ -0,0 +1,5 @@ +-include ../../run-make-fulldeps/tools.mk + +all: + echo 'fn main() {}' | $(BARE_RUSTC) - --out-dir=$(TMPDIR)/random_directory_that_does_not_exist_ir/ --emit=llvm-ir + echo 'fn main() {}' | $(BARE_RUSTC) - --out-dir=$(TMPDIR)/random_directory_that_does_not_exist_bc/ --emit=llvm-bc diff --git a/src/test/ui/issues/issue-56202.rs b/src/test/ui/issues/issue-56202.rs new file mode 100644 index 0000000000000..c80c372c9e2ea --- /dev/null +++ b/src/test/ui/issues/issue-56202.rs @@ -0,0 +1,15 @@ +#![feature(self_struct_ctor)] + +trait FooTrait {} + +trait BarTrait { + fn foo(_: T) -> Self; +} + +struct FooStruct(u32); + +impl BarTrait for FooStruct { + fn foo(_: T) -> Self { + Self(u32::default()) + } +} diff --git a/src/test/ui/issues/issue-56202.stderr b/src/test/ui/issues/issue-56202.stderr new file mode 100644 index 0000000000000..3007b08450298 --- /dev/null +++ b/src/test/ui/issues/issue-56202.stderr @@ -0,0 +1,7 @@ +error[E0601]: `main` function not found in crate `issue_56202` + | + = note: consider adding a `main` function to `$DIR/issue-56202.rs` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0601`. diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index bf95b31ae3ca4..d9834f9f0a004 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -606,7 +606,7 @@ impl Builder { let filename = path.file_name().unwrap().to_str().unwrap(); let sha256 = self.output.join(format!("{}.sha256", filename)); - t!(t!(File::create(&sha256)).write_all(&sha.stdout)); + t!(fs::write(&sha256, &sha.stdout)); let stdout = String::from_utf8_lossy(&sha.stdout); stdout.split_whitespace().next().unwrap().to_string() @@ -643,7 +643,7 @@ impl Builder { fn write(&self, contents: &str, channel_name: &str, suffix: &str) { let dst = self.output.join(format!("channel-rust-{}{}", channel_name, suffix)); - t!(t!(File::create(&dst)).write_all(contents.as_bytes())); + t!(fs::write(&dst, contents)); self.hash(&dst); self.sign(&dst); } diff --git a/src/tools/cargotest/main.rs b/src/tools/cargotest/main.rs index 5b717c45254cc..ab74e7b7a7fd8 100644 --- a/src/tools/cargotest/main.rs +++ b/src/tools/cargotest/main.rs @@ -11,8 +11,7 @@ use std::env; use std::process::Command; use std::path::{Path, PathBuf}; -use std::fs::File; -use std::io::Write; +use std::fs; struct Test { repo: &'static str, @@ -91,10 +90,7 @@ fn test_repo(cargo: &Path, out_dir: &Path, test: &Test) { println!("testing {}", test.repo); let dir = clone_repo(test, out_dir); if let Some(lockfile) = test.lock { - File::create(&dir.join("Cargo.lock")) - .expect("") - .write_all(lockfile.as_bytes()) - .expect(""); + fs::write(&dir.join("Cargo.lock"), lockfile).unwrap(); } if !run_cargo_test(cargo, &dir, test.packages) { panic!("tests failed for {}", test.repo); diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index f63950b448a14..65f6bff7eaf55 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -38,7 +38,7 @@ use getopts::Options; use std::env; use std::ffi::OsString; use std::fs; -use std::io::{self, Read}; +use std::io::{self, ErrorKind}; use std::path::{Path, PathBuf}; use std::process::Command; use test::ColorConfig; @@ -686,13 +686,11 @@ fn up_to_date( ) -> bool { let stamp_name = stamp(config, testpaths, revision); // Check hash. - let mut f = match fs::File::open(&stamp_name) { + let contents = match fs::read_to_string(&stamp_name) { Ok(f) => f, + Err(ref e) if e.kind() == ErrorKind::InvalidData => panic!("Can't read stamp contents"), Err(_) => return true, }; - let mut contents = String::new(); - f.read_to_string(&mut contents) - .expect("Can't read stamp contents"); let expected_hash = runtest::compute_stamp_hash(config); if contents != expected_hash { return true; diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 399f9f577edf5..f7a3348b771d1 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -458,11 +458,7 @@ impl<'test> TestCx<'test> { None => 2, }; - let mut src = String::new(); - File::open(&self.testpaths.file) - .unwrap() - .read_to_string(&mut src) - .unwrap(); + let src = fs::read_to_string(&self.testpaths.file).unwrap(); let mut srcs = vec![src]; let mut round = 0; @@ -500,12 +496,7 @@ impl<'test> TestCx<'test> { let mut expected = match self.props.pp_exact { Some(ref file) => { let filepath = self.testpaths.file.parent().unwrap().join(file); - let mut s = String::new(); - File::open(&filepath) - .unwrap() - .read_to_string(&mut s) - .unwrap(); - s + fs::read_to_string(&filepath).unwrap() } None => srcs[srcs.len() - 2].clone(), }; @@ -1949,10 +1940,7 @@ impl<'test> TestCx<'test> { fn dump_output_file(&self, out: &str, extension: &str) { let outfile = self.make_out_name(extension); - File::create(&outfile) - .unwrap() - .write_all(out.as_bytes()) - .unwrap(); + fs::write(&outfile, out).unwrap(); } /// Create a filename for output with the given extension. Example: @@ -2149,11 +2137,7 @@ impl<'test> TestCx<'test> { path: &P, mut other_files: Option<&mut Vec>, ) -> Vec { - let mut file = - fs::File::open(path).expect("markdown_test_output_check_entry File::open failed"); - let mut content = String::new(); - file.read_to_string(&mut content) - .expect("markdown_test_output_check_entry read_to_string failed"); + let content = fs::read_to_string(&path).unwrap(); let mut ignore = false; content .lines() @@ -2824,11 +2808,7 @@ impl<'test> TestCx<'test> { } fn check_mir_dump(&self) { - let mut test_file_contents = String::new(); - fs::File::open(self.testpaths.file.clone()) - .unwrap() - .read_to_string(&mut test_file_contents) - .unwrap(); + let test_file_contents = fs::read_to_string(&self.testpaths.file).unwrap(); if let Some(idx) = test_file_contents.find("// END RUST SOURCE") { let (_, tests_text) = test_file_contents.split_at(idx + "// END_RUST SOURCE".len()); let tests_text_str = String::from(tests_text); @@ -2892,9 +2872,7 @@ impl<'test> TestCx<'test> { } self.check_mir_test_timestamp(test_name, &output_file); - let mut dumped_file = fs::File::open(output_file.clone()).unwrap(); - let mut dumped_string = String::new(); - dumped_file.read_to_string(&mut dumped_string).unwrap(); + let dumped_string = fs::read_to_string(&output_file).unwrap(); let mut dumped_lines = dumped_string .lines() .map(|l| nocomment_mir_line(l)) @@ -3106,19 +3084,13 @@ impl<'test> TestCx<'test> { } fn load_expected_output_from_path(&self, path: &Path) -> Result { - let mut result = String::new(); - match File::open(path).and_then(|mut f| f.read_to_string(&mut result)) { - Ok(_) => Ok(result), - Err(e) => Err(format!( - "failed to load expected output from `{}`: {}", - path.display(), - e - )), - } + fs::read_to_string(path).map_err(|err| { + format!("failed to load expected output from `{}`: {}", path.display(), err) + }) } fn delete_file(&self, file: &PathBuf) { - if let Err(e) = ::std::fs::remove_file(file) { + if let Err(e) = fs::remove_file(file) { self.fatal(&format!( "failed to delete `{}`: {}", file.display(), @@ -3180,16 +3152,13 @@ impl<'test> TestCx<'test> { for output_file in &files { if actual.is_empty() { self.delete_file(output_file); - } else { - match File::create(&output_file).and_then(|mut f| f.write_all(actual.as_bytes())) { - Ok(()) => {} - Err(e) => self.fatal(&format!( - "failed to write {} to `{}`: {}", - kind, - output_file.display(), - e - )), - } + } else if let Err(err) = fs::write(&output_file, &actual) { + self.fatal(&format!( + "failed to write {} to `{}`: {}", + kind, + output_file.display(), + err, + )); } } @@ -3241,9 +3210,8 @@ impl<'test> TestCx<'test> { } fn create_stamp(&self) { - let mut f = File::create(::stamp(&self.config, self.testpaths, self.revision)).unwrap(); - f.write_all(compute_stamp_hash(&self.config).as_bytes()) - .unwrap(); + let stamp = ::stamp(&self.config, self.testpaths, self.revision); + fs::write(&stamp, compute_stamp_hash(&self.config)).unwrap(); } } diff --git a/src/tools/error_index_generator/main.rs b/src/tools/error_index_generator/main.rs index a5556e1d570eb..03add412b6451 100644 --- a/src/tools/error_index_generator/main.rs +++ b/src/tools/error_index_generator/main.rs @@ -18,8 +18,8 @@ extern crate serialize as rustc_serialize; use std::collections::BTreeMap; use std::env; use std::error::Error; -use std::fs::{read_dir, File}; -use std::io::{Read, Write}; +use std::fs::{self, read_dir, File}; +use std::io::Write; use std::path::Path; use std::path::PathBuf; use std::cell::RefCell; @@ -210,8 +210,7 @@ fn load_all_errors(metadata_dir: &Path) -> Result Result<(PathBuf, String), LoadError> { - let mut contents = String::new(); + let contents; let pretty_file = PathBuf::from(file.strip_prefix(root).unwrap_or(&file)); let maybe_redirect = match cache.entry(pretty_file.clone()) { @@ -297,14 +296,13 @@ fn load_file(cache: &mut Cache, None } Entry::Vacant(entry) => { - let mut fp = File::open(file).map_err(|err| { + contents = fs::read_to_string(&file).map_err(|err| { if let FromRedirect(true) = redirect { LoadError::BrokenRedirect(file.to_path_buf(), err) } else { LoadError::IOError(err) } })?; - fp.read_to_string(&mut contents).map_err(|err| LoadError::IOError(err))?; let maybe = maybe_redirect(&contents); if maybe.is_some() { diff --git a/src/tools/tidy/src/bins.rs b/src/tools/tidy/src/bins.rs index f6e42c8dc17b1..ae930555d0912 100644 --- a/src/tools/tidy/src/bins.rs +++ b/src/tools/tidy/src/bins.rs @@ -24,13 +24,10 @@ pub fn check(_path: &Path, _bad: &mut bool) {} #[cfg(unix)] pub fn check(path: &Path, bad: &mut bool) { use std::fs; - use std::io::Read; use std::process::{Command, Stdio}; use std::os::unix::prelude::*; - if let Ok(mut file) = fs::File::open("/proc/version") { - let mut contents = String::new(); - file.read_to_string(&mut contents).unwrap(); + if let Ok(contents) = fs::read_to_string("/proc/version") { // Probably on Windows Linux Subsystem or Docker via VirtualBox, // all files will be marked as executable, so skip checking. if contents.contains("Microsoft") || contents.contains("boot2docker") { diff --git a/src/tools/tidy/src/cargo.rs b/src/tools/tidy/src/cargo.rs index 466d2fa0d2bd6..ac7e968dff76c 100644 --- a/src/tools/tidy/src/cargo.rs +++ b/src/tools/tidy/src/cargo.rs @@ -15,8 +15,7 @@ //! `extern crate` declarations. This should help us keep the DAG correctly //! structured through various refactorings to prune out unnecessary edges. -use std::io::prelude::*; -use std::fs::File; +use std::fs; use std::path::Path; pub fn check(path: &Path, bad: &mut bool) { @@ -41,10 +40,8 @@ pub fn check(path: &Path, bad: &mut bool) { // Verify that the dependencies in Cargo.toml at `tomlfile` are sync'd with the // `extern crate` annotations in the lib.rs at `libfile`. fn verify(tomlfile: &Path, libfile: &Path, bad: &mut bool) { - let mut toml = String::new(); - let mut librs = String::new(); - t!(t!(File::open(tomlfile)).read_to_string(&mut toml)); - t!(t!(File::open(libfile)).read_to_string(&mut librs)); + let toml = t!(fs::read_to_string(&tomlfile)); + let librs = t!(fs::read_to_string(&libfile)); if toml.contains("name = \"bootstrap\"") { return diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index a40ae8894d5e7..7aad6bfd15e7c 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -11,8 +11,7 @@ //! Check license of third-party deps by inspecting vendor use std::collections::{BTreeSet, HashSet, HashMap}; -use std::fs::File; -use std::io::Read; +use std::fs; use std::path::Path; use std::process::Command; @@ -261,8 +260,7 @@ fn check_license(path: &Path) -> bool { if !path.exists() { panic!("{} does not exist", path.display()); } - let mut contents = String::new(); - t!(t!(File::open(path)).read_to_string(&mut contents)); + let contents = t!(fs::read_to_string(&path)); let mut found_license = false; for line in contents.lines() { diff --git a/src/tools/tidy/src/extdeps.rs b/src/tools/tidy/src/extdeps.rs index a78d2d4ee4e15..377a7c33d75ae 100644 --- a/src/tools/tidy/src/extdeps.rs +++ b/src/tools/tidy/src/extdeps.rs @@ -10,8 +10,7 @@ // ! Check for external package sources. Allow only vendorable packages. -use std::fs::File; -use std::io::Read; +use std::fs; use std::path::Path; /// List of whitelisted sources for packages @@ -25,8 +24,7 @@ pub fn check(path: &Path, bad: &mut bool) { let path = path.join("../Cargo.lock"); // open and read the whole file - let mut cargo_lock = String::new(); - t!(t!(File::open(path)).read_to_string(&mut cargo_lock)); + let cargo_lock = t!(fs::read_to_string(&path)); // process each line for line in cargo_lock.lines() { diff --git a/src/tools/tidy/src/features.rs b/src/tools/tidy/src/features.rs index 85b123e4af51f..b0bd5ba8dbdbd 100644 --- a/src/tools/tidy/src/features.rs +++ b/src/tools/tidy/src/features.rs @@ -20,7 +20,7 @@ use std::collections::HashMap; use std::fmt; -use std::fs::File; +use std::fs::{self, File}; use std::io::prelude::*; use std::path::Path; @@ -183,9 +183,7 @@ fn test_filen_gate(filen_underscore: &str, features: &mut Features) -> bool { } pub fn collect_lang_features(base_src_path: &Path, bad: &mut bool) -> Features { - let mut contents = String::new(); - let path = base_src_path.join("libsyntax/feature_gate.rs"); - t!(t!(File::open(path)).read_to_string(&mut contents)); + let contents = t!(fs::read_to_string(base_src_path.join("libsyntax/feature_gate.rs"))); // we allow rustc-internal features to omit a tracking issue. // these features must be marked with `// rustc internal` in its own group.