Skip to content

Commit e83f756

Browse files
committed
Auto merge of #71593 - Dylan-DPC:rollup-ms7j94u, r=Dylan-DPC
Rollup of 5 pull requests Successful merges: - #71421 (Add a function to turn Box<T> into Box<[T]>) - #71537 (Remove support for self-opening) - #71551 (Minor refactoring around IndexVec usage in generator transformation) - #71569 ([miri] Throw UB if target size and data size don't match) - #71576 (check that `AsRef` and `AsMut` are inlined) Failed merges: - #71558 (Cleanup and document `-Z tls-model` ) r? @ghost
2 parents 7f3b3df + 962cae0 commit e83f756

File tree

20 files changed

+263
-139
lines changed

20 files changed

+263
-139
lines changed

src/liballoc/boxed.rs

+10
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,16 @@ impl<T> Box<T> {
239239
pub fn pin(x: T) -> Pin<Box<T>> {
240240
(box x).into()
241241
}
242+
243+
/// Converts a `Box<T>` into a `Box<[T]>`
244+
///
245+
/// This conversion does not allocate on the heap and happens in place.
246+
///
247+
#[unstable(feature = "box_into_boxed_slice", issue = "71582")]
248+
pub fn into_boxed_slice(boxed: Box<T>) -> Box<[T]> {
249+
// *mut T and *mut [T; 1] have the same size and alignment
250+
unsafe { Box::from_raw(Box::into_raw(boxed) as *mut [T; 1] as *mut [T]) }
251+
}
242252
}
243253

244254
impl<T> Box<[T]> {

src/librustc_interface/util.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ pub fn spawn_thread_pool<F: FnOnce() -> R + Send, R: Send>(
205205
}
206206

207207
fn load_backend_from_dylib(path: &Path) -> fn() -> Box<dyn CodegenBackend> {
208-
let lib = DynamicLibrary::open(Some(path)).unwrap_or_else(|err| {
208+
let lib = DynamicLibrary::open(path).unwrap_or_else(|err| {
209209
let err = format!("couldn't load codegen backend {:?}: {:?}", path, err);
210210
early_error(ErrorOutputType::default(), &err);
211211
});

src/librustc_metadata/creader.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -591,7 +591,7 @@ impl<'a> CrateLoader<'a> {
591591

592592
// Make sure the path contains a / or the linker will search for it.
593593
let path = env::current_dir().unwrap().join(path);
594-
let lib = match DynamicLibrary::open(Some(&path)) {
594+
let lib = match DynamicLibrary::open(&path) {
595595
Ok(lib) => lib,
596596
Err(err) => self.sess.span_fatal(span, &err),
597597
};

src/librustc_metadata/dynamic_lib.rs

+11-36
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,9 @@ impl Drop for DynamicLibrary {
1616
}
1717

1818
impl DynamicLibrary {
19-
/// Lazily open a dynamic library. When passed None it gives a
20-
/// handle to the calling process
21-
pub fn open(filename: Option<&Path>) -> Result<DynamicLibrary, String> {
22-
let maybe_library = dl::open(filename.map(|path| path.as_os_str()));
19+
/// Lazily open a dynamic library.
20+
pub fn open(filename: &Path) -> Result<DynamicLibrary, String> {
21+
let maybe_library = dl::open(filename.as_os_str());
2322

2423
// The dynamic library must not be constructed if there is
2524
// an error opening the library so the destructor does not
@@ -57,24 +56,13 @@ mod dl {
5756
use std::ptr;
5857
use std::str;
5958

60-
pub(super) fn open(filename: Option<&OsStr>) -> Result<*mut u8, String> {
59+
pub(super) fn open(filename: &OsStr) -> Result<*mut u8, String> {
6160
check_for_errors_in(|| unsafe {
62-
match filename {
63-
Some(filename) => open_external(filename),
64-
None => open_internal(),
65-
}
61+
let s = CString::new(filename.as_bytes()).unwrap();
62+
libc::dlopen(s.as_ptr(), libc::RTLD_LAZY) as *mut u8
6663
})
6764
}
6865

69-
unsafe fn open_external(filename: &OsStr) -> *mut u8 {
70-
let s = CString::new(filename.as_bytes()).unwrap();
71-
libc::dlopen(s.as_ptr(), libc::RTLD_LAZY) as *mut u8
72-
}
73-
74-
unsafe fn open_internal() -> *mut u8 {
75-
libc::dlopen(ptr::null(), libc::RTLD_LAZY) as *mut u8
76-
}
77-
7866
fn check_for_errors_in<T, F>(f: F) -> Result<T, String>
7967
where
8068
F: FnOnce() -> T,
@@ -124,10 +112,10 @@ mod dl {
124112

125113
use winapi::shared::minwindef::HMODULE;
126114
use winapi::um::errhandlingapi::SetThreadErrorMode;
127-
use winapi::um::libloaderapi::{FreeLibrary, GetModuleHandleExW, GetProcAddress, LoadLibraryW};
115+
use winapi::um::libloaderapi::{FreeLibrary, GetProcAddress, LoadLibraryW};
128116
use winapi::um::winbase::SEM_FAILCRITICALERRORS;
129117

130-
pub(super) fn open(filename: Option<&OsStr>) -> Result<*mut u8, String> {
118+
pub(super) fn open(filename: &OsStr) -> Result<*mut u8, String> {
131119
// disable "dll load failed" error dialog.
132120
let prev_error_mode = unsafe {
133121
let new_error_mode = SEM_FAILCRITICALERRORS;
@@ -139,22 +127,9 @@ mod dl {
139127
prev_error_mode
140128
};
141129

142-
let result = match filename {
143-
Some(filename) => {
144-
let filename_str: Vec<_> = filename.encode_wide().chain(Some(0)).collect();
145-
let result = unsafe { LoadLibraryW(filename_str.as_ptr()) } as *mut u8;
146-
ptr_result(result)
147-
}
148-
None => {
149-
let mut handle = ptr::null_mut();
150-
let succeeded = unsafe { GetModuleHandleExW(0, ptr::null(), &mut handle) };
151-
if succeeded == 0 {
152-
Err(io::Error::last_os_error().to_string())
153-
} else {
154-
Ok(handle as *mut u8)
155-
}
156-
}
157-
};
130+
let filename_str: Vec<_> = filename.encode_wide().chain(Some(0)).collect();
131+
let result = unsafe { LoadLibraryW(filename_str.as_ptr()) } as *mut u8;
132+
let result = ptr_result(result);
158133

159134
unsafe {
160135
SetThreadErrorMode(prev_error_mode, ptr::null_mut());

src/librustc_metadata/dynamic_lib/tests.rs

+1-29
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,4 @@
11
use super::*;
2-
use std::mem;
3-
4-
#[test]
5-
fn test_loading_atoi() {
6-
if cfg!(windows) {
7-
return;
8-
}
9-
10-
// The C library does not need to be loaded since it is already linked in
11-
let lib = match DynamicLibrary::open(None) {
12-
Err(error) => panic!("Could not load self as module: {}", error),
13-
Ok(lib) => lib,
14-
};
15-
16-
let atoi: extern "C" fn(*const libc::c_char) -> libc::c_int = unsafe {
17-
match lib.symbol("atoi") {
18-
Err(error) => panic!("Could not load function atoi: {}", error),
19-
Ok(atoi) => mem::transmute::<*mut u8, _>(atoi),
20-
}
21-
};
22-
23-
let argument = CString::new("1383428980").unwrap();
24-
let expected_result = 0x52757374;
25-
let result = atoi(argument.as_ptr());
26-
if result != expected_result {
27-
panic!("atoi({:?}) != {} but equaled {} instead", argument, expected_result, result)
28-
}
29-
}
302

313
#[test]
324
fn test_errors_do_not_crash() {
@@ -39,7 +11,7 @@ fn test_errors_do_not_crash() {
3911
// Open /dev/null as a library to get an error, and make sure
4012
// that only causes an error, and not a crash.
4113
let path = Path::new("/dev/null");
42-
match DynamicLibrary::open(Some(&path)) {
14+
match DynamicLibrary::open(&path) {
4315
Err(_) => {}
4416
Ok(_) => panic!("Successfully opened the empty library."),
4517
}

src/librustc_middle/mir/interpret/error.rs

+10
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,11 @@ pub enum UndefinedBehaviorInfo {
360360
InvalidUndefBytes(Option<Pointer>),
361361
/// Working with a local that is not currently live.
362362
DeadLocal,
363+
/// Data size is not equal to target size.
364+
ScalarSizeMismatch {
365+
target_size: u64,
366+
data_size: u64,
367+
},
363368
}
364369

365370
impl fmt::Debug for UndefinedBehaviorInfo {
@@ -421,6 +426,11 @@ impl fmt::Debug for UndefinedBehaviorInfo {
421426
"using uninitialized data, but this operation requires initialized memory"
422427
),
423428
DeadLocal => write!(f, "accessing a dead local variable"),
429+
ScalarSizeMismatch { target_size, data_size } => write!(
430+
f,
431+
"scalar size mismatch: expected {} bytes but got {} bytes instead",
432+
target_size, data_size
433+
),
424434
}
425435
}
426436
}

src/librustc_middle/mir/interpret/value.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -393,7 +393,12 @@ impl<'tcx, Tag> Scalar<Tag> {
393393
assert_ne!(target_size.bytes(), 0, "you should never look at the bits of a ZST");
394394
match self {
395395
Scalar::Raw { data, size } => {
396-
assert_eq!(target_size.bytes(), u64::from(size));
396+
if target_size.bytes() != u64::from(size) {
397+
throw_ub!(ScalarSizeMismatch {
398+
target_size: target_size.bytes(),
399+
data_size: u64::from(size),
400+
});
401+
}
397402
Scalar::check_data(data, size);
398403
Ok(data)
399404
}

src/librustc_mir/transform/generator.rs

+13-21
Original file line numberDiff line numberDiff line change
@@ -210,8 +210,7 @@ struct TransformVisitor<'tcx> {
210210
remap: FxHashMap<Local, (Ty<'tcx>, VariantIdx, usize)>,
211211

212212
// A map from a suspension point in a block to the locals which have live storage at that point
213-
// FIXME(eddyb) This should use `IndexVec<BasicBlock, Option<_>>`.
214-
storage_liveness: FxHashMap<BasicBlock, liveness::LiveVarSet>,
213+
storage_liveness: IndexVec<BasicBlock, Option<liveness::LiveVarSet>>,
215214

216215
// A list of suspension points, generated during the transform
217216
suspension_points: Vec<SuspensionPoint<'tcx>>,
@@ -338,7 +337,7 @@ impl MutVisitor<'tcx> for TransformVisitor<'tcx> {
338337
resume,
339338
resume_arg,
340339
drop,
341-
storage_liveness: self.storage_liveness.get(&block).unwrap().clone(),
340+
storage_liveness: self.storage_liveness[block].clone().unwrap(),
342341
});
343342

344343
VariantIdx::new(state)
@@ -404,8 +403,7 @@ fn replace_local<'tcx>(
404403
is_block_tail: None,
405404
local_info: LocalInfo::Other,
406405
};
407-
let new_local = Local::new(body.local_decls.len());
408-
body.local_decls.push(new_decl);
406+
let new_local = body.local_decls.push(new_decl);
409407
body.local_decls.swap(local, new_local);
410408

411409
RenameLocalVisitor { from: local, to: new_local, tcx }.visit_body(body);
@@ -431,7 +429,7 @@ struct LivenessInfo {
431429

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

437435
fn locals_live_across_suspend_points(
@@ -472,7 +470,7 @@ fn locals_live_across_suspend_points(
472470
let mut liveness = liveness::liveness_of_locals(body);
473471
liveness::dump_mir(tcx, "generator_liveness", source, body_ref, &liveness);
474472

475-
let mut storage_liveness_map = FxHashMap::default();
473+
let mut storage_liveness_map = IndexVec::from_elem(None, body.basic_blocks());
476474
let mut live_locals_at_suspension_points = Vec::new();
477475

478476
for (block, data) in body.basic_blocks().iter_enumerated() {
@@ -502,7 +500,7 @@ fn locals_live_across_suspend_points(
502500

503501
// Store the storage liveness for later use so we can restore the state
504502
// after a suspension point
505-
storage_liveness_map.insert(block, storage_liveness);
503+
storage_liveness_map[block] = Some(storage_liveness);
506504

507505
requires_storage_cursor.seek_before(loc);
508506
let storage_required = requires_storage_cursor.get().clone();
@@ -690,7 +688,7 @@ fn compute_layout<'tcx>(
690688
) -> (
691689
FxHashMap<Local, (Ty<'tcx>, VariantIdx, usize)>,
692690
GeneratorLayout<'tcx>,
693-
FxHashMap<BasicBlock, liveness::LiveVarSet>,
691+
IndexVec<BasicBlock, Option<liveness::LiveVarSet>>,
694692
) {
695693
// Use a liveness analysis to compute locals which are live across a suspension point
696694
let LivenessInfo {
@@ -925,14 +923,12 @@ fn create_generator_drop_shim<'tcx>(
925923
}
926924

927925
fn insert_term_block<'tcx>(body: &mut Body<'tcx>, kind: TerminatorKind<'tcx>) -> BasicBlock {
928-
let term_block = BasicBlock::new(body.basic_blocks().len());
929926
let source_info = source_info(body);
930927
body.basic_blocks_mut().push(BasicBlockData {
931928
statements: Vec::new(),
932929
terminator: Some(Terminator { source_info, kind }),
933930
is_cleanup: false,
934-
});
935-
term_block
931+
})
936932
}
937933

938934
fn insert_panic_block<'tcx>(
@@ -1030,9 +1026,8 @@ fn create_generator_resume_function<'tcx>(
10301026

10311027
// Poison the generator when it unwinds
10321028
if can_unwind {
1033-
let poison_block = BasicBlock::new(body.basic_blocks().len());
10341029
let source_info = source_info(body);
1035-
body.basic_blocks_mut().push(BasicBlockData {
1030+
let poison_block = body.basic_blocks_mut().push(BasicBlockData {
10361031
statements: vec![transform.set_discr(VariantIdx::new(POISONED), source_info)],
10371032
terminator: Some(Terminator { source_info, kind: TerminatorKind::Resume }),
10381033
is_cleanup: true,
@@ -1105,21 +1100,19 @@ fn source_info(body: &Body<'_>) -> SourceInfo {
11051100
fn insert_clean_drop(body: &mut Body<'_>) -> BasicBlock {
11061101
let return_block = insert_term_block(body, TerminatorKind::Return);
11071102

1108-
// Create a block to destroy an unresumed generators. This can only destroy upvars.
1109-
let drop_clean = BasicBlock::new(body.basic_blocks().len());
11101103
let term = TerminatorKind::Drop {
11111104
location: Place::from(SELF_ARG),
11121105
target: return_block,
11131106
unwind: None,
11141107
};
11151108
let source_info = source_info(body);
1109+
1110+
// Create a block to destroy an unresumed generators. This can only destroy upvars.
11161111
body.basic_blocks_mut().push(BasicBlockData {
11171112
statements: Vec::new(),
11181113
terminator: Some(Terminator { source_info, kind: term }),
11191114
is_cleanup: false,
1120-
});
1121-
1122-
drop_clean
1115+
})
11231116
}
11241117

11251118
/// An operation that can be performed on a generator.
@@ -1151,7 +1144,6 @@ fn create_cases<'tcx>(
11511144
.filter_map(|point| {
11521145
// Find the target for this suspension point, if applicable
11531146
operation.target_block(point).map(|target| {
1154-
let block = BasicBlock::new(body.basic_blocks().len());
11551147
let mut statements = Vec::new();
11561148

11571149
// Create StorageLive instructions for locals with live storage
@@ -1186,7 +1178,7 @@ fn create_cases<'tcx>(
11861178
}
11871179

11881180
// Then jump to the real target
1189-
body.basic_blocks_mut().push(BasicBlockData {
1181+
let block = body.basic_blocks_mut().push(BasicBlockData {
11901182
statements,
11911183
terminator: Some(Terminator {
11921184
source_info,

src/librustc_plugin_impl/load.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ fn dylink_registrar(
7676
// Make sure the path contains a / or the linker will search for it.
7777
let path = env::current_dir().unwrap().join(&path);
7878

79-
let lib = match DynamicLibrary::open(Some(&path)) {
79+
let lib = match DynamicLibrary::open(&path) {
8080
Ok(lib) => lib,
8181
// this is fatal: there are almost certainly macros we need
8282
// inside this crate, so continue would spew "macro undefined"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// EMIT_MIR rustc.a.Inline.after.mir
2+
pub fn a<T>(x: &mut [T]) -> &mut [T] {
3+
x.as_mut()
4+
}
5+
6+
// EMIT_MIR rustc.b.Inline.after.mir
7+
pub fn b<T>(x: &mut Box<T>) -> &mut T {
8+
x.as_mut()
9+
}
10+
11+
// EMIT_MIR rustc.c.Inline.after.mir
12+
pub fn c<T>(x: &[T]) -> &[T] {
13+
x.as_ref()
14+
}
15+
16+
// EMIT_MIR rustc.d.Inline.after.mir
17+
pub fn d<T>(x: &Box<T>) -> &T {
18+
x.as_ref()
19+
}
20+
21+
fn main() {
22+
let mut boxed = Box::new(1);
23+
println!("{:?}", a(&mut [1]));
24+
println!("{:?}", b(&mut boxed));
25+
println!("{:?}", c(&[1]));
26+
println!("{:?}", d(&boxed));
27+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// MIR for `a` after Inline
2+
3+
fn a(_1: &mut [T]) -> &mut [T] {
4+
debug x => _1; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:2:13: 2:14
5+
let mut _0: &mut [T]; // return place in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:2:29: 2:37
6+
let mut _2: &mut [T]; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:5: 3:15
7+
let mut _3: &mut [T]; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:5: 3:15
8+
let mut _4: &mut [T]; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:5: 3:6
9+
scope 1 {
10+
debug self => _4; // in scope 1 at $SRC_DIR/libcore/convert/mod.rs:LL:COL
11+
let mut _5: &mut [T]; // in scope 1 at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:5: 3:15
12+
}
13+
14+
bb0: {
15+
StorageLive(_2); // bb0[0]: scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:5: 3:15
16+
StorageLive(_3); // bb0[1]: scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:5: 3:15
17+
StorageLive(_4); // bb0[2]: scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:5: 3:6
18+
_4 = &mut (*_1); // bb0[3]: scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:5: 3:6
19+
StorageLive(_5); // bb0[4]: scope 1 at $SRC_DIR/libcore/convert/mod.rs:LL:COL
20+
_5 = _4; // bb0[5]: scope 1 at $SRC_DIR/libcore/convert/mod.rs:LL:COL
21+
_3 = _5; // bb0[6]: scope 1 at $SRC_DIR/libcore/convert/mod.rs:LL:COL
22+
StorageDead(_5); // bb0[7]: scope 1 at $SRC_DIR/libcore/convert/mod.rs:LL:COL
23+
_2 = &mut (*_3); // bb0[8]: scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:5: 3:15
24+
StorageDead(_4); // bb0[9]: scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:14: 3:15
25+
_0 = &mut (*_2); // bb0[10]: scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:5: 3:15
26+
StorageDead(_3); // bb0[11]: scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:4:1: 4:2
27+
StorageDead(_2); // bb0[12]: scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:4:1: 4:2
28+
return; // bb0[13]: scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:4:2: 4:2
29+
}
30+
}

0 commit comments

Comments
 (0)