Skip to content

Rollup of 5 pull requests #71593

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Apr 26, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions src/liballoc/boxed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,16 @@ impl<T> Box<T> {
pub fn pin(x: T) -> Pin<Box<T>> {
(box x).into()
}

/// Converts a `Box<T>` 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<T>) -> 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<T> Box<[T]> {
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_interface/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ pub fn spawn_thread_pool<F: FnOnce() -> R + Send, R: Send>(
}

fn load_backend_from_dylib(path: &Path) -> fn() -> Box<dyn CodegenBackend> {
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);
});
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_metadata/creader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -591,7 +591,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),
};
Expand Down
47 changes: 11 additions & 36 deletions src/librustc_metadata/dynamic_lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<DynamicLibrary, String> {
let maybe_library = dl::open(filename.map(|path| path.as_os_str()));
/// Lazily open a dynamic library.
pub fn open(filename: &Path) -> Result<DynamicLibrary, String> {
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
Expand Down Expand Up @@ -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<T, F>(f: F) -> Result<T, String>
where
F: FnOnce() -> T,
Expand Down Expand Up @@ -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;
Expand All @@ -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());
Expand Down
30 changes: 1 addition & 29 deletions src/librustc_metadata/dynamic_lib/tests.rs
Original file line number Diff line number Diff line change
@@ -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() {
Expand All @@ -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."),
}
Expand Down
10 changes: 10 additions & 0 deletions src/librustc_middle/mir/interpret/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,11 @@ pub enum UndefinedBehaviorInfo {
InvalidUndefBytes(Option<Pointer>),
/// Working with a local that is not currently live.
DeadLocal,
/// Data size is not equal to target size.
ScalarSizeMismatch {
target_size: u64,
data_size: u64,
},
}

impl fmt::Debug for UndefinedBehaviorInfo {
Expand Down Expand Up @@ -421,6 +426,11 @@ impl fmt::Debug for UndefinedBehaviorInfo {
"using uninitialized data, but this operation requires initialized memory"
),
DeadLocal => write!(f, "accessing a dead local variable"),
ScalarSizeMismatch { target_size, data_size } => write!(
f,
"scalar size mismatch: expected {} bytes but got {} bytes instead",
target_size, data_size
),
}
}
}
Expand Down
7 changes: 6 additions & 1 deletion src/librustc_middle/mir/interpret/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,12 @@ impl<'tcx, Tag> Scalar<Tag> {
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!(ScalarSizeMismatch {
target_size: target_size.bytes(),
data_size: u64::from(size),
});
}
Scalar::check_data(data, size);
Ok(data)
}
Expand Down
34 changes: 13 additions & 21 deletions src/librustc_mir/transform/generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -210,8 +210,7 @@ struct TransformVisitor<'tcx> {
remap: FxHashMap<Local, (Ty<'tcx>, 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<BasicBlock, Option<_>>`.
storage_liveness: FxHashMap<BasicBlock, liveness::LiveVarSet>,
storage_liveness: IndexVec<BasicBlock, Option<liveness::LiveVarSet>>,

// A list of suspension points, generated during the transform
suspension_points: Vec<SuspensionPoint<'tcx>>,
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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);
Expand All @@ -431,7 +429,7 @@ struct LivenessInfo {

/// For every suspending block, the locals which are storage-live across
/// that suspension point.
storage_liveness: FxHashMap<BasicBlock, liveness::LiveVarSet>,
storage_liveness: IndexVec<BasicBlock, Option<liveness::LiveVarSet>>,
}

fn locals_live_across_suspend_points(
Expand Down Expand Up @@ -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() {
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -690,7 +688,7 @@ fn compute_layout<'tcx>(
) -> (
FxHashMap<Local, (Ty<'tcx>, VariantIdx, usize)>,
GeneratorLayout<'tcx>,
FxHashMap<BasicBlock, liveness::LiveVarSet>,
IndexVec<BasicBlock, Option<liveness::LiveVarSet>>,
) {
// Use a liveness analysis to compute locals which are live across a suspension point
let LivenessInfo {
Expand Down Expand Up @@ -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>(
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_plugin_impl/load.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
27 changes: 27 additions & 0 deletions src/test/mir-opt/inline/issue-58867-inline-as-ref-as-mut.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// EMIT_MIR rustc.a.Inline.after.mir
pub fn a<T>(x: &mut [T]) -> &mut [T] {
x.as_mut()
}

// EMIT_MIR rustc.b.Inline.after.mir
pub fn b<T>(x: &mut Box<T>) -> &mut T {
x.as_mut()
}

// EMIT_MIR rustc.c.Inline.after.mir
pub fn c<T>(x: &[T]) -> &[T] {
x.as_ref()
}

// EMIT_MIR rustc.d.Inline.after.mir
pub fn d<T>(x: &Box<T>) -> &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));
}
Original file line number Diff line number Diff line change
@@ -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
}
}
Loading