From 77495914a46eb2114c95ff403278f7c3edfaebb8 Mon Sep 17 00:00:00 2001 From: Alex Aktsipetrov Date: Sat, 25 Apr 2020 13:46:37 +0200 Subject: [PATCH 1/8] Replace hash map with IndexVec for liveness data. Utilize IndexVec::push to avoid redundant object creation. --- src/librustc_mir/transform/generator.rs | 34 ++++++++++--------------- 1 file changed, 13 insertions(+), 21 deletions(-) diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index 8e7302dae44..611d03405e2 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -210,8 +210,7 @@ struct TransformVisitor<'tcx> { remap: FxHashMap, VariantIdx, usize)>, // A map from a suspension point in a block to the locals which have live storage at that point - // FIXME(eddyb) This should use `IndexVec>`. - storage_liveness: FxHashMap, + storage_liveness: IndexVec>, // A list of suspension points, generated during the transform suspension_points: Vec>, @@ -338,7 +337,7 @@ impl MutVisitor<'tcx> for TransformVisitor<'tcx> { resume, resume_arg, drop, - storage_liveness: self.storage_liveness.get(&block).unwrap().clone(), + storage_liveness: self.storage_liveness[block].clone().unwrap(), }); VariantIdx::new(state) @@ -404,8 +403,7 @@ fn replace_local<'tcx>( is_block_tail: None, local_info: LocalInfo::Other, }; - let new_local = Local::new(body.local_decls.len()); - body.local_decls.push(new_decl); + let new_local = body.local_decls.push(new_decl); body.local_decls.swap(local, new_local); RenameLocalVisitor { from: local, to: new_local, tcx }.visit_body(body); @@ -431,7 +429,7 @@ struct LivenessInfo { /// For every suspending block, the locals which are storage-live across /// that suspension point. - storage_liveness: FxHashMap, + storage_liveness: IndexVec>, } fn locals_live_across_suspend_points( @@ -472,7 +470,7 @@ fn locals_live_across_suspend_points( let mut liveness = liveness::liveness_of_locals(body); liveness::dump_mir(tcx, "generator_liveness", source, body_ref, &liveness); - let mut storage_liveness_map = FxHashMap::default(); + let mut storage_liveness_map = IndexVec::from_elem(None, body.basic_blocks()); let mut live_locals_at_suspension_points = Vec::new(); for (block, data) in body.basic_blocks().iter_enumerated() { @@ -502,7 +500,7 @@ fn locals_live_across_suspend_points( // Store the storage liveness for later use so we can restore the state // after a suspension point - storage_liveness_map.insert(block, storage_liveness); + storage_liveness_map[block] = Some(storage_liveness); requires_storage_cursor.seek_before(loc); let storage_required = requires_storage_cursor.get().clone(); @@ -690,7 +688,7 @@ fn compute_layout<'tcx>( ) -> ( FxHashMap, VariantIdx, usize)>, GeneratorLayout<'tcx>, - FxHashMap, + IndexVec>, ) { // Use a liveness analysis to compute locals which are live across a suspension point let LivenessInfo { @@ -925,14 +923,12 @@ fn create_generator_drop_shim<'tcx>( } fn insert_term_block<'tcx>(body: &mut Body<'tcx>, kind: TerminatorKind<'tcx>) -> BasicBlock { - let term_block = BasicBlock::new(body.basic_blocks().len()); let source_info = source_info(body); body.basic_blocks_mut().push(BasicBlockData { statements: Vec::new(), terminator: Some(Terminator { source_info, kind }), is_cleanup: false, - }); - term_block + }) } fn insert_panic_block<'tcx>( @@ -1030,9 +1026,8 @@ fn create_generator_resume_function<'tcx>( // Poison the generator when it unwinds if can_unwind { - let poison_block = BasicBlock::new(body.basic_blocks().len()); let source_info = source_info(body); - body.basic_blocks_mut().push(BasicBlockData { + let poison_block = body.basic_blocks_mut().push(BasicBlockData { statements: vec![transform.set_discr(VariantIdx::new(POISONED), source_info)], terminator: Some(Terminator { source_info, kind: TerminatorKind::Resume }), is_cleanup: true, @@ -1105,21 +1100,19 @@ fn source_info(body: &Body<'_>) -> SourceInfo { fn insert_clean_drop(body: &mut Body<'_>) -> BasicBlock { let return_block = insert_term_block(body, TerminatorKind::Return); - // Create a block to destroy an unresumed generators. This can only destroy upvars. - let drop_clean = BasicBlock::new(body.basic_blocks().len()); let term = TerminatorKind::Drop { location: Place::from(SELF_ARG), target: return_block, unwind: None, }; let source_info = source_info(body); + + // Create a block to destroy an unresumed generators. This can only destroy upvars. body.basic_blocks_mut().push(BasicBlockData { statements: Vec::new(), terminator: Some(Terminator { source_info, kind: term }), is_cleanup: false, - }); - - drop_clean + }) } /// An operation that can be performed on a generator. @@ -1151,7 +1144,6 @@ fn create_cases<'tcx>( .filter_map(|point| { // Find the target for this suspension point, if applicable operation.target_block(point).map(|target| { - let block = BasicBlock::new(body.basic_blocks().len()); let mut statements = Vec::new(); // Create StorageLive instructions for locals with live storage @@ -1186,7 +1178,7 @@ fn create_cases<'tcx>( } // Then jump to the real target - body.basic_blocks_mut().push(BasicBlockData { + let block = body.basic_blocks_mut().push(BasicBlockData { statements, terminator: Some(Terminator { source_info, From 97983af76a3b7c180704a33246d91e9d98d2e42a Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Fri, 24 Apr 2020 18:31:42 -0400 Subject: [PATCH 2/8] Remove support for self-opening This was only used for linkage test cases, which is already covered by the run-make-fulldeps/symbol-visibility test -- which fairly extensively makes sure we're correctly exporting the right symbols at the right visibility (for various Rust crate types). --- src/librustc_interface/util.rs | 2 +- src/librustc_metadata/creader.rs | 2 +- src/librustc_metadata/dynamic_lib.rs | 47 +++++-------------- src/librustc_metadata/dynamic_lib/tests.rs | 30 +----------- src/librustc_plugin_impl/load.rs | 2 +- .../extern-fn-reachable/main.rs | 2 +- .../auxiliary/linkage-visibility.rs | 35 -------------- src/test/ui-fulldeps/linkage-visibility.rs | 13 ----- 8 files changed, 16 insertions(+), 117 deletions(-) delete mode 100644 src/test/ui-fulldeps/auxiliary/linkage-visibility.rs delete mode 100644 src/test/ui-fulldeps/linkage-visibility.rs diff --git a/src/librustc_interface/util.rs b/src/librustc_interface/util.rs index 02bf1aded3b..8439ac6c9e5 100644 --- a/src/librustc_interface/util.rs +++ b/src/librustc_interface/util.rs @@ -205,7 +205,7 @@ pub fn spawn_thread_pool R + Send, R: Send>( } fn load_backend_from_dylib(path: &Path) -> fn() -> Box { - let lib = DynamicLibrary::open(Some(path)).unwrap_or_else(|err| { + let lib = DynamicLibrary::open(path).unwrap_or_else(|err| { let err = format!("couldn't load codegen backend {:?}: {:?}", path, err); early_error(ErrorOutputType::default(), &err); }); diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index fe8fbd50627..f3c4eca5fde 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -585,7 +585,7 @@ impl<'a> CrateLoader<'a> { // Make sure the path contains a / or the linker will search for it. let path = env::current_dir().unwrap().join(path); - let lib = match DynamicLibrary::open(Some(&path)) { + let lib = match DynamicLibrary::open(&path) { Ok(lib) => lib, Err(err) => self.sess.span_fatal(span, &err), }; diff --git a/src/librustc_metadata/dynamic_lib.rs b/src/librustc_metadata/dynamic_lib.rs index 3e78a585235..ce19240a009 100644 --- a/src/librustc_metadata/dynamic_lib.rs +++ b/src/librustc_metadata/dynamic_lib.rs @@ -16,10 +16,9 @@ impl Drop for DynamicLibrary { } impl DynamicLibrary { - /// Lazily open a dynamic library. When passed None it gives a - /// handle to the calling process - pub fn open(filename: Option<&Path>) -> Result { - let maybe_library = dl::open(filename.map(|path| path.as_os_str())); + /// Lazily open a dynamic library. + pub fn open(filename: &Path) -> Result { + let maybe_library = dl::open(filename.as_os_str()); // The dynamic library must not be constructed if there is // an error opening the library so the destructor does not @@ -57,24 +56,13 @@ mod dl { use std::ptr; use std::str; - pub(super) fn open(filename: Option<&OsStr>) -> Result<*mut u8, String> { + pub(super) fn open(filename: &OsStr) -> Result<*mut u8, String> { check_for_errors_in(|| unsafe { - match filename { - Some(filename) => open_external(filename), - None => open_internal(), - } + let s = CString::new(filename.as_bytes()).unwrap(); + libc::dlopen(s.as_ptr(), libc::RTLD_LAZY) as *mut u8 }) } - unsafe fn open_external(filename: &OsStr) -> *mut u8 { - let s = CString::new(filename.as_bytes()).unwrap(); - libc::dlopen(s.as_ptr(), libc::RTLD_LAZY) as *mut u8 - } - - unsafe fn open_internal() -> *mut u8 { - libc::dlopen(ptr::null(), libc::RTLD_LAZY) as *mut u8 - } - fn check_for_errors_in(f: F) -> Result where F: FnOnce() -> T, @@ -124,10 +112,10 @@ mod dl { use winapi::shared::minwindef::HMODULE; use winapi::um::errhandlingapi::SetThreadErrorMode; - use winapi::um::libloaderapi::{FreeLibrary, GetModuleHandleExW, GetProcAddress, LoadLibraryW}; + use winapi::um::libloaderapi::{FreeLibrary, GetProcAddress, LoadLibraryW}; use winapi::um::winbase::SEM_FAILCRITICALERRORS; - pub(super) fn open(filename: Option<&OsStr>) -> Result<*mut u8, String> { + pub(super) fn open(filename: &OsStr) -> Result<*mut u8, String> { // disable "dll load failed" error dialog. let prev_error_mode = unsafe { let new_error_mode = SEM_FAILCRITICALERRORS; @@ -139,22 +127,9 @@ mod dl { prev_error_mode }; - let result = match filename { - Some(filename) => { - let filename_str: Vec<_> = filename.encode_wide().chain(Some(0)).collect(); - let result = unsafe { LoadLibraryW(filename_str.as_ptr()) } as *mut u8; - ptr_result(result) - } - None => { - let mut handle = ptr::null_mut(); - let succeeded = unsafe { GetModuleHandleExW(0, ptr::null(), &mut handle) }; - if succeeded == 0 { - Err(io::Error::last_os_error().to_string()) - } else { - Ok(handle as *mut u8) - } - } - }; + let filename_str: Vec<_> = filename.encode_wide().chain(Some(0)).collect(); + let result = unsafe { LoadLibraryW(filename_str.as_ptr()) } as *mut u8; + let result = ptr_result(result); unsafe { SetThreadErrorMode(prev_error_mode, ptr::null_mut()); diff --git a/src/librustc_metadata/dynamic_lib/tests.rs b/src/librustc_metadata/dynamic_lib/tests.rs index cbf2b181e3c..7090bbf61c7 100644 --- a/src/librustc_metadata/dynamic_lib/tests.rs +++ b/src/librustc_metadata/dynamic_lib/tests.rs @@ -1,32 +1,4 @@ use super::*; -use std::mem; - -#[test] -fn test_loading_atoi() { - if cfg!(windows) { - return; - } - - // The C library does not need to be loaded since it is already linked in - let lib = match DynamicLibrary::open(None) { - Err(error) => panic!("Could not load self as module: {}", error), - Ok(lib) => lib, - }; - - let atoi: extern "C" fn(*const libc::c_char) -> libc::c_int = unsafe { - match lib.symbol("atoi") { - Err(error) => panic!("Could not load function atoi: {}", error), - Ok(atoi) => mem::transmute::<*mut u8, _>(atoi), - } - }; - - let argument = CString::new("1383428980").unwrap(); - let expected_result = 0x52757374; - let result = atoi(argument.as_ptr()); - if result != expected_result { - panic!("atoi({:?}) != {} but equaled {} instead", argument, expected_result, result) - } -} #[test] fn test_errors_do_not_crash() { @@ -39,7 +11,7 @@ fn test_errors_do_not_crash() { // Open /dev/null as a library to get an error, and make sure // that only causes an error, and not a crash. let path = Path::new("/dev/null"); - match DynamicLibrary::open(Some(&path)) { + match DynamicLibrary::open(&path) { Err(_) => {} Ok(_) => panic!("Successfully opened the empty library."), } diff --git a/src/librustc_plugin_impl/load.rs b/src/librustc_plugin_impl/load.rs index f41bc44d177..f48d2b6c8b5 100644 --- a/src/librustc_plugin_impl/load.rs +++ b/src/librustc_plugin_impl/load.rs @@ -76,7 +76,7 @@ fn dylink_registrar( // Make sure the path contains a / or the linker will search for it. let path = env::current_dir().unwrap().join(&path); - let lib = match DynamicLibrary::open(Some(&path)) { + let lib = match DynamicLibrary::open(&path) { Ok(lib) => lib, // this is fatal: there are almost certainly macros we need // inside this crate, so continue would spew "macro undefined" diff --git a/src/test/run-make-fulldeps/extern-fn-reachable/main.rs b/src/test/run-make-fulldeps/extern-fn-reachable/main.rs index a9d28d1bebe..c1de6477585 100644 --- a/src/test/run-make-fulldeps/extern-fn-reachable/main.rs +++ b/src/test/run-make-fulldeps/extern-fn-reachable/main.rs @@ -8,7 +8,7 @@ use std::path::Path; pub fn main() { unsafe { let path = Path::new("libdylib.so"); - let a = DynamicLibrary::open(Some(&path)).unwrap(); + let a = DynamicLibrary::open(&path).unwrap(); assert!(a.symbol::("fun1").is_ok()); assert!(a.symbol::("fun2").is_ok()); assert!(a.symbol::("fun3").is_ok()); diff --git a/src/test/ui-fulldeps/auxiliary/linkage-visibility.rs b/src/test/ui-fulldeps/auxiliary/linkage-visibility.rs deleted file mode 100644 index 837ed1f002f..00000000000 --- a/src/test/ui-fulldeps/auxiliary/linkage-visibility.rs +++ /dev/null @@ -1,35 +0,0 @@ -// ignore-musl - dlsym doesn't see symbols without "-C link-arg=-Wl,--export-dynamic" - -#![feature(rustc_private)] - -extern crate rustc_metadata; - -use rustc_metadata::dynamic_lib::DynamicLibrary; - -#[no_mangle] -pub fn foo() { - bar(); -} - -pub fn foo2() { - fn bar2() { - bar(); - } - bar2(); -} - -#[no_mangle] -fn bar() {} - -#[allow(dead_code)] -#[no_mangle] -fn baz() {} - -pub fn test() { - let lib = DynamicLibrary::open(None).unwrap(); - unsafe { - assert!(lib.symbol::("foo").is_ok()); - assert!(lib.symbol::("baz").is_ok()); - assert!(lib.symbol::("bar").is_ok()); - } -} diff --git a/src/test/ui-fulldeps/linkage-visibility.rs b/src/test/ui-fulldeps/linkage-visibility.rs deleted file mode 100644 index ae46fbc4e8a..00000000000 --- a/src/test/ui-fulldeps/linkage-visibility.rs +++ /dev/null @@ -1,13 +0,0 @@ -// run-pass -// aux-build:linkage-visibility.rs -// ignore-android: FIXME(#10356) -// ignore-windows: std::dynamic_lib does not work on Windows well -// ignore-emscripten no dynamic linking - -extern crate linkage_visibility as foo; - -pub fn main() { - foo::test(); - foo::foo2::(); - foo::foo(); -} From 91462db9f1c1b5db941c22efb64e7ec01d472911 Mon Sep 17 00:00:00 2001 From: Samrat Man Singh Date: Sun, 26 Apr 2020 08:58:22 +0530 Subject: [PATCH 3/8] [miri] Throw UB if target size and data size don't match If an extern C function is defined as ``` extern "C" { fn malloc(size: u32) -> *mut std::ffi::c_void; } ``` on a 64-bit machine(ie. pointer sizes don't match), throw an undefined behaviour. --- src/librustc_middle/mir/interpret/error.rs | 10 ++++++++++ src/librustc_middle/mir/interpret/value.rs | 7 ++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/librustc_middle/mir/interpret/error.rs b/src/librustc_middle/mir/interpret/error.rs index 2510dbcea0b..71a9382bc65 100644 --- a/src/librustc_middle/mir/interpret/error.rs +++ b/src/librustc_middle/mir/interpret/error.rs @@ -361,6 +361,11 @@ pub enum UndefinedBehaviorInfo { InvalidUndefBytes(Option), /// Working with a local that is not currently live. DeadLocal, + /// Data size is not equal to target size + ArgumentSizeMismatch { + target_size: u64, + data_size: u64, + }, } impl fmt::Debug for UndefinedBehaviorInfo { @@ -422,6 +427,11 @@ impl fmt::Debug for UndefinedBehaviorInfo { "using uninitialized data, but this operation requires initialized memory" ), DeadLocal => write!(f, "accessing a dead local variable"), + ArgumentSizeMismatch { target_size, data_size } => write!( + f, + "argument size mismatch: expected {} bytes but got {} bytes instead", + target_size, data_size + ), } } } diff --git a/src/librustc_middle/mir/interpret/value.rs b/src/librustc_middle/mir/interpret/value.rs index f3c1c87dad4..c11e5001508 100644 --- a/src/librustc_middle/mir/interpret/value.rs +++ b/src/librustc_middle/mir/interpret/value.rs @@ -393,7 +393,12 @@ impl<'tcx, Tag> Scalar { assert_ne!(target_size.bytes(), 0, "you should never look at the bits of a ZST"); match self { Scalar::Raw { data, size } => { - assert_eq!(target_size.bytes(), u64::from(size)); + if target_size.bytes() != u64::from(size) { + throw_ub!(ArgumentSizeMismatch { + target_size: target_size.bytes(), + data_size: u64::from(size) + }); + } Scalar::check_data(data, size); Ok(data) } From cf61a562896e3abded4891719884c6acc18b5039 Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Sun, 26 Apr 2020 12:43:00 +0200 Subject: [PATCH 4/8] check that `AsRef` and `AsMut` are inlined --- .../issue-58867-inline-as-ref-as-mut.rs | 27 +++++++++++++++ .../rustc.a.Inline.after.mir | 30 ++++++++++++++++ .../rustc.b.Inline.after.mir | 34 +++++++++++++++++++ .../rustc.c.Inline.after.mir | 22 ++++++++++++ .../rustc.d.Inline.after.mir | 26 ++++++++++++++ 5 files changed, 139 insertions(+) create mode 100644 src/test/mir-opt/inline/issue-58867-inline-as-ref-as-mut.rs create mode 100644 src/test/mir-opt/inline/issue-58867-inline-as-ref-as-mut/rustc.a.Inline.after.mir create mode 100644 src/test/mir-opt/inline/issue-58867-inline-as-ref-as-mut/rustc.b.Inline.after.mir create mode 100644 src/test/mir-opt/inline/issue-58867-inline-as-ref-as-mut/rustc.c.Inline.after.mir create mode 100644 src/test/mir-opt/inline/issue-58867-inline-as-ref-as-mut/rustc.d.Inline.after.mir diff --git a/src/test/mir-opt/inline/issue-58867-inline-as-ref-as-mut.rs b/src/test/mir-opt/inline/issue-58867-inline-as-ref-as-mut.rs new file mode 100644 index 00000000000..317705f7612 --- /dev/null +++ b/src/test/mir-opt/inline/issue-58867-inline-as-ref-as-mut.rs @@ -0,0 +1,27 @@ +// EMIT_MIR rustc.a.Inline.after.mir +pub fn a(x: &mut [T]) -> &mut [T] { + x.as_mut() +} + +// EMIT_MIR rustc.b.Inline.after.mir +pub fn b(x: &mut Box) -> &mut T { + x.as_mut() +} + +// EMIT_MIR rustc.c.Inline.after.mir +pub fn c(x: &[T]) -> &[T] { + x.as_ref() +} + +// EMIT_MIR rustc.d.Inline.after.mir +pub fn d(x: &Box) -> &T { + x.as_ref() +} + +fn main() { + let mut boxed = Box::new(1); + println!("{:?}", a(&mut [1])); + println!("{:?}", b(&mut boxed)); + println!("{:?}", c(&[1])); + println!("{:?}", d(&boxed)); +} diff --git a/src/test/mir-opt/inline/issue-58867-inline-as-ref-as-mut/rustc.a.Inline.after.mir b/src/test/mir-opt/inline/issue-58867-inline-as-ref-as-mut/rustc.a.Inline.after.mir new file mode 100644 index 00000000000..c5d44cbafac --- /dev/null +++ b/src/test/mir-opt/inline/issue-58867-inline-as-ref-as-mut/rustc.a.Inline.after.mir @@ -0,0 +1,30 @@ +// MIR for `a` after Inline + +fn a(_1: &mut [T]) -> &mut [T] { + debug x => _1; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:2:13: 2:14 + let mut _0: &mut [T]; // return place in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:2:29: 2:37 + let mut _2: &mut [T]; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:5: 3:15 + let mut _3: &mut [T]; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:5: 3:15 + let mut _4: &mut [T]; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:5: 3:6 + scope 1 { + debug self => _4; // in scope 1 at $SRC_DIR/libcore/convert/mod.rs:LL:COL + let mut _5: &mut [T]; // in scope 1 at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:5: 3:15 + } + + bb0: { + StorageLive(_2); // bb0[0]: scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:5: 3:15 + StorageLive(_3); // bb0[1]: scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:5: 3:15 + StorageLive(_4); // bb0[2]: scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:5: 3:6 + _4 = &mut (*_1); // bb0[3]: scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:5: 3:6 + StorageLive(_5); // bb0[4]: scope 1 at $SRC_DIR/libcore/convert/mod.rs:LL:COL + _5 = _4; // bb0[5]: scope 1 at $SRC_DIR/libcore/convert/mod.rs:LL:COL + _3 = _5; // bb0[6]: scope 1 at $SRC_DIR/libcore/convert/mod.rs:LL:COL + StorageDead(_5); // bb0[7]: scope 1 at $SRC_DIR/libcore/convert/mod.rs:LL:COL + _2 = &mut (*_3); // bb0[8]: scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:5: 3:15 + StorageDead(_4); // bb0[9]: scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:14: 3:15 + _0 = &mut (*_2); // bb0[10]: scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:5: 3:15 + StorageDead(_3); // bb0[11]: scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:4:1: 4:2 + StorageDead(_2); // bb0[12]: scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:4:1: 4:2 + return; // bb0[13]: scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:4:2: 4:2 + } +} diff --git a/src/test/mir-opt/inline/issue-58867-inline-as-ref-as-mut/rustc.b.Inline.after.mir b/src/test/mir-opt/inline/issue-58867-inline-as-ref-as-mut/rustc.b.Inline.after.mir new file mode 100644 index 00000000000..8384b949b95 --- /dev/null +++ b/src/test/mir-opt/inline/issue-58867-inline-as-ref-as-mut/rustc.b.Inline.after.mir @@ -0,0 +1,34 @@ +// MIR for `b` after Inline + +fn b(_1: &mut std::boxed::Box) -> &mut T { + debug x => _1; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:7:13: 7:14 + let mut _0: &mut T; // return place in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:7:32: 7:38 + let mut _2: &mut T; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:8:5: 8:15 + let mut _3: &mut T; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:8:5: 8:15 + let mut _4: &mut std::boxed::Box; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:8:5: 8:6 + scope 1 { + debug self => _4; // in scope 1 at $SRC_DIR/liballoc/boxed.rs:LL:COL + let mut _5: &mut T; // in scope 1 at $DIR/issue-58867-inline-as-ref-as-mut.rs:8:5: 8:15 + let mut _6: &mut T; // in scope 1 at $DIR/issue-58867-inline-as-ref-as-mut.rs:8:5: 8:15 + } + + bb0: { + StorageLive(_2); // bb0[0]: scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:8:5: 8:15 + StorageLive(_3); // bb0[1]: scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:8:5: 8:15 + StorageLive(_4); // bb0[2]: scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:8:5: 8:6 + _4 = &mut (*_1); // bb0[3]: scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:8:5: 8:6 + StorageLive(_5); // bb0[4]: scope 1 at $SRC_DIR/liballoc/boxed.rs:LL:COL + StorageLive(_6); // bb0[5]: scope 1 at $SRC_DIR/liballoc/boxed.rs:LL:COL + _6 = &mut (*(*_4)); // bb0[6]: scope 1 at $SRC_DIR/liballoc/boxed.rs:LL:COL + _5 = _6; // bb0[7]: scope 1 at $SRC_DIR/liballoc/boxed.rs:LL:COL + _3 = _5; // bb0[8]: scope 1 at $SRC_DIR/liballoc/boxed.rs:LL:COL + StorageDead(_6); // bb0[9]: scope 1 at $SRC_DIR/liballoc/boxed.rs:LL:COL + StorageDead(_5); // bb0[10]: scope 1 at $SRC_DIR/liballoc/boxed.rs:LL:COL + _2 = &mut (*_3); // bb0[11]: scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:8:5: 8:15 + StorageDead(_4); // bb0[12]: scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:8:14: 8:15 + _0 = &mut (*_2); // bb0[13]: scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:8:5: 8:15 + StorageDead(_3); // bb0[14]: scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:9:1: 9:2 + StorageDead(_2); // bb0[15]: scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:9:1: 9:2 + return; // bb0[16]: scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:9:2: 9:2 + } +} diff --git a/src/test/mir-opt/inline/issue-58867-inline-as-ref-as-mut/rustc.c.Inline.after.mir b/src/test/mir-opt/inline/issue-58867-inline-as-ref-as-mut/rustc.c.Inline.after.mir new file mode 100644 index 00000000000..5adb4a68312 --- /dev/null +++ b/src/test/mir-opt/inline/issue-58867-inline-as-ref-as-mut/rustc.c.Inline.after.mir @@ -0,0 +1,22 @@ +// MIR for `c` after Inline + +fn c(_1: &[T]) -> &[T] { + debug x => _1; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:12:13: 12:14 + let mut _0: &[T]; // return place in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:12:25: 12:29 + let _2: &[T]; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:13:5: 13:15 + let mut _3: &[T]; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:13:5: 13:6 + scope 1 { + debug self => _3; // in scope 1 at $SRC_DIR/libcore/convert/mod.rs:LL:COL + } + + bb0: { + StorageLive(_2); // bb0[0]: scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:13:5: 13:15 + StorageLive(_3); // bb0[1]: scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:13:5: 13:6 + _3 = &(*_1); // bb0[2]: scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:13:5: 13:6 + _2 = _3; // bb0[3]: scope 1 at $SRC_DIR/libcore/convert/mod.rs:LL:COL + _0 = &(*_2); // bb0[4]: scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:13:5: 13:15 + StorageDead(_3); // bb0[5]: scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:13:14: 13:15 + StorageDead(_2); // bb0[6]: scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:14:1: 14:2 + return; // bb0[7]: scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:14:2: 14:2 + } +} diff --git a/src/test/mir-opt/inline/issue-58867-inline-as-ref-as-mut/rustc.d.Inline.after.mir b/src/test/mir-opt/inline/issue-58867-inline-as-ref-as-mut/rustc.d.Inline.after.mir new file mode 100644 index 00000000000..d4d62dd788e --- /dev/null +++ b/src/test/mir-opt/inline/issue-58867-inline-as-ref-as-mut/rustc.d.Inline.after.mir @@ -0,0 +1,26 @@ +// MIR for `d` after Inline + +fn d(_1: &std::boxed::Box) -> &T { + debug x => _1; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:17:13: 17:14 + let mut _0: &T; // return place in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:17:28: 17:30 + let _2: &T; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:18:5: 18:15 + let mut _3: &std::boxed::Box; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:18:5: 18:6 + scope 1 { + debug self => _3; // in scope 1 at $SRC_DIR/liballoc/boxed.rs:LL:COL + let _4: &T; // in scope 1 at $DIR/issue-58867-inline-as-ref-as-mut.rs:18:5: 18:15 + } + + bb0: { + StorageLive(_2); // bb0[0]: scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:18:5: 18:15 + StorageLive(_3); // bb0[1]: scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:18:5: 18:6 + _3 = &(*_1); // bb0[2]: scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:18:5: 18:6 + StorageLive(_4); // bb0[3]: scope 1 at $SRC_DIR/liballoc/boxed.rs:LL:COL + _4 = &(*(*_3)); // bb0[4]: scope 1 at $SRC_DIR/liballoc/boxed.rs:LL:COL + _2 = _4; // bb0[5]: scope 1 at $SRC_DIR/liballoc/boxed.rs:LL:COL + StorageDead(_4); // bb0[6]: scope 1 at $SRC_DIR/liballoc/boxed.rs:LL:COL + _0 = &(*_2); // bb0[7]: scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:18:5: 18:15 + StorageDead(_3); // bb0[8]: scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:18:14: 18:15 + StorageDead(_2); // bb0[9]: scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:19:1: 19:2 + return; // bb0[10]: scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:19:2: 19:2 + } +} From 6f31f05aaf8e89f87e01052ba61fa04613b0a090 Mon Sep 17 00:00:00 2001 From: Elichai Turkel Date: Wed, 22 Apr 2020 12:39:29 +0300 Subject: [PATCH 5/8] Add a function to turn Box into Box<[T]> (into_boxed_slice) --- src/liballoc/boxed.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index db7420954a0..5419491fc23 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -239,6 +239,16 @@ impl Box { pub fn pin(x: T) -> Pin> { (box x).into() } + + /// Converts a `Box` into a `Box<[T]>` + /// + /// This conversion does not allocate on the heap and happens in place. + /// + #[unstable(feature = "box_into_boxed_slice", issue = "71582")] + pub fn into_boxed_slice(boxed: Box) -> Box<[T]> { + // *mut T and *mut [T; 1] have the same size and alignment + unsafe { Box::from_raw(Box::into_raw(boxed) as *mut [T; 1] as *mut [T]) } + } } impl Box<[T]> { From 0228ca0c7d07f92d449209fa2eeda9eb72e68f63 Mon Sep 17 00:00:00 2001 From: Elichai Turkel Date: Wed, 22 Apr 2020 17:23:20 +0300 Subject: [PATCH 6/8] Add success and fail tests for into_boxed_slice --- src/test/ui/box-into-boxed-slice-fail.rs | 15 +++++++ src/test/ui/box-into-boxed-slice-fail.stderr | 43 ++++++++++++++++++++ src/test/ui/box-into-boxed-slice.rs | 11 +++++ 3 files changed, 69 insertions(+) create mode 100644 src/test/ui/box-into-boxed-slice-fail.rs create mode 100644 src/test/ui/box-into-boxed-slice-fail.stderr create mode 100644 src/test/ui/box-into-boxed-slice.rs diff --git a/src/test/ui/box-into-boxed-slice-fail.rs b/src/test/ui/box-into-boxed-slice-fail.rs new file mode 100644 index 00000000000..5f8a3fd9d6a --- /dev/null +++ b/src/test/ui/box-into-boxed-slice-fail.rs @@ -0,0 +1,15 @@ +// ignore-tidy-linelength +#![feature(box_into_boxed_slice)] + +use std::boxed::Box; +use std::fmt::Debug; +fn main() { + let boxed_slice = Box::new([1,2,3]) as Box<[u8]>; + let _ = Box::into_boxed_slice(boxed_slice); + //~^ ERROR the size for values of type `[u8]` cannot be known at compilation time + //~^^ ERROR the size for values of type `[u8]` cannot be known at compilation time + let boxed_trait: Box = Box::new(5u8); + let _ = Box::into_boxed_slice(boxed_trait); + //~^ ERROR the size for values of type `dyn std::fmt::Debug` cannot be known at compilation time + //~^^ ERROR the size for values of type `dyn std::fmt::Debug` cannot be known at compilation time +} diff --git a/src/test/ui/box-into-boxed-slice-fail.stderr b/src/test/ui/box-into-boxed-slice-fail.stderr new file mode 100644 index 00000000000..dfc4999958a --- /dev/null +++ b/src/test/ui/box-into-boxed-slice-fail.stderr @@ -0,0 +1,43 @@ +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/box-into-boxed-slice-fail.rs:8:35 + | +LL | let _ = Box::into_boxed_slice(boxed_slice); + | ^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `std::marker::Sized` is not implemented for `[u8]` + = note: to learn more, visit + = note: required by `std::boxed::Box::::into_boxed_slice` + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/box-into-boxed-slice-fail.rs:8:13 + | +LL | let _ = Box::into_boxed_slice(boxed_slice); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `std::marker::Sized` is not implemented for `[u8]` + = note: to learn more, visit + = note: slice and array elements must have `Sized` type + +error[E0277]: the size for values of type `dyn std::fmt::Debug` cannot be known at compilation time + --> $DIR/box-into-boxed-slice-fail.rs:12:35 + | +LL | let _ = Box::into_boxed_slice(boxed_trait); + | ^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `std::marker::Sized` is not implemented for `dyn std::fmt::Debug` + = note: to learn more, visit + = note: required by `std::boxed::Box::::into_boxed_slice` + +error[E0277]: the size for values of type `dyn std::fmt::Debug` cannot be known at compilation time + --> $DIR/box-into-boxed-slice-fail.rs:12:13 + | +LL | let _ = Box::into_boxed_slice(boxed_trait); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `std::marker::Sized` is not implemented for `dyn std::fmt::Debug` + = note: to learn more, visit + = note: slice and array elements must have `Sized` type + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/box-into-boxed-slice.rs b/src/test/ui/box-into-boxed-slice.rs new file mode 100644 index 00000000000..61b3d915253 --- /dev/null +++ b/src/test/ui/box-into-boxed-slice.rs @@ -0,0 +1,11 @@ +// run-pass +#![feature(box_into_boxed_slice)] + +use std::boxed::Box; +fn main() { + assert_eq!(Box::into_boxed_slice(Box::new(5u8)), Box::new([5u8]) as Box<[u8]>); + assert_eq!(Box::into_boxed_slice(Box::new([25u8])), Box::new([[25u8]]) as Box<[[u8; 1]]>); + let a: Box<[Box<[u8; 1]>]> = Box::into_boxed_slice(Box::new(Box::new([5u8]))); + let b: Box<[Box<[u8; 1]>]> = Box::new([Box::new([5u8])]); + assert_eq!(a, b); +} From b8af409a51138d46951d4fc49d3d2edd3346ecd5 Mon Sep 17 00:00:00 2001 From: Samrat Man Singh Date: Sun, 26 Apr 2020 20:11:14 +0530 Subject: [PATCH 7/8] Rename ArgumentSizeMismatch to ScalarSizeMismatch --- src/librustc_middle/mir/interpret/error.rs | 6 +++--- src/librustc_middle/mir/interpret/value.rs | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/librustc_middle/mir/interpret/error.rs b/src/librustc_middle/mir/interpret/error.rs index 71a9382bc65..875b514e8c8 100644 --- a/src/librustc_middle/mir/interpret/error.rs +++ b/src/librustc_middle/mir/interpret/error.rs @@ -362,7 +362,7 @@ pub enum UndefinedBehaviorInfo { /// Working with a local that is not currently live. DeadLocal, /// Data size is not equal to target size - ArgumentSizeMismatch { + ScalarSizeMismatch { target_size: u64, data_size: u64, }, @@ -427,9 +427,9 @@ impl fmt::Debug for UndefinedBehaviorInfo { "using uninitialized data, but this operation requires initialized memory" ), DeadLocal => write!(f, "accessing a dead local variable"), - ArgumentSizeMismatch { target_size, data_size } => write!( + ScalarSizeMismatch { target_size, data_size } => write!( f, - "argument size mismatch: expected {} bytes but got {} bytes instead", + "scalar size mismatch: expected {} bytes but got {} bytes instead", target_size, data_size ), } diff --git a/src/librustc_middle/mir/interpret/value.rs b/src/librustc_middle/mir/interpret/value.rs index c11e5001508..6e013f75ed7 100644 --- a/src/librustc_middle/mir/interpret/value.rs +++ b/src/librustc_middle/mir/interpret/value.rs @@ -394,9 +394,9 @@ impl<'tcx, Tag> Scalar { match self { Scalar::Raw { data, size } => { if target_size.bytes() != u64::from(size) { - throw_ub!(ArgumentSizeMismatch { + throw_ub!(ScalarSizeMismatch { target_size: target_size.bytes(), - data_size: u64::from(size) + data_size: u64::from(size), }); } Scalar::check_data(data, size); From c8d8c42d1ce10d945bcd8cbff3ac9858fc909abc Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 26 Apr 2020 18:44:38 +0200 Subject: [PATCH 8/8] Adjust style --- src/librustc_middle/mir/interpret/error.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_middle/mir/interpret/error.rs b/src/librustc_middle/mir/interpret/error.rs index 875b514e8c8..785aadc11fa 100644 --- a/src/librustc_middle/mir/interpret/error.rs +++ b/src/librustc_middle/mir/interpret/error.rs @@ -361,7 +361,7 @@ pub enum UndefinedBehaviorInfo { InvalidUndefBytes(Option), /// Working with a local that is not currently live. DeadLocal, - /// Data size is not equal to target size + /// Data size is not equal to target size. ScalarSizeMismatch { target_size: u64, data_size: u64,