Skip to content

Commit 1a06ac5

Browse files
committed
Auto merge of #118492 - cuviper:beta-next, r=cuviper
[beta] backports - Build pre-coroutine-transform coroutine body #117686 - Fix coroutine validation for mixed panic strategy #118422 - ConstProp: Remove const when rvalue check fails. #118426 - Dispose llvm::TargetMachines prior to llvm::Context being disposed #118464 r? ghost
2 parents bd45872 + 6c45608 commit 1a06ac5

File tree

13 files changed

+145
-29
lines changed

13 files changed

+145
-29
lines changed

compiler/rustc_codegen_llvm/src/back/lto.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ use std::ffi::{CStr, CString};
2525
use std::fs::File;
2626
use std::io;
2727
use std::iter;
28+
use std::mem::ManuallyDrop;
2829
use std::path::Path;
2930
use std::slice;
3031
use std::sync::Arc;
@@ -734,7 +735,7 @@ pub unsafe fn optimize_thin_module(
734735
let llcx = llvm::LLVMRustContextCreate(cgcx.fewer_names);
735736
let llmod_raw = parse_module(llcx, module_name, thin_module.data(), &diag_handler)? as *const _;
736737
let mut module = ModuleCodegen {
737-
module_llvm: ModuleLlvm { llmod_raw, llcx, tm },
738+
module_llvm: ModuleLlvm { llmod_raw, llcx, tm: ManuallyDrop::new(tm) },
738739
name: thin_module.name().to_string(),
739740
kind: ModuleKind::Regular,
740741
};

compiler/rustc_codegen_llvm/src/lib.rs

+16-5
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ use rustc_span::symbol::Symbol;
5353
use std::any::Any;
5454
use std::ffi::CStr;
5555
use std::io::Write;
56+
use std::mem::ManuallyDrop;
5657

5758
mod back {
5859
pub mod archive;
@@ -408,8 +409,9 @@ pub struct ModuleLlvm {
408409
llcx: &'static mut llvm::Context,
409410
llmod_raw: *const llvm::Module,
410411

411-
// independent from llcx and llmod_raw, resources get disposed by drop impl
412-
tm: OwnedTargetMachine,
412+
// This field is `ManuallyDrop` because it is important that the `TargetMachine`
413+
// is disposed prior to the `Context` being disposed otherwise UAFs can occur.
414+
tm: ManuallyDrop<OwnedTargetMachine>,
413415
}
414416

415417
unsafe impl Send for ModuleLlvm {}
@@ -420,15 +422,23 @@ impl ModuleLlvm {
420422
unsafe {
421423
let llcx = llvm::LLVMRustContextCreate(tcx.sess.fewer_names());
422424
let llmod_raw = context::create_module(tcx, llcx, mod_name) as *const _;
423-
ModuleLlvm { llmod_raw, llcx, tm: create_target_machine(tcx, mod_name) }
425+
ModuleLlvm {
426+
llmod_raw,
427+
llcx,
428+
tm: ManuallyDrop::new(create_target_machine(tcx, mod_name)),
429+
}
424430
}
425431
}
426432

427433
fn new_metadata(tcx: TyCtxt<'_>, mod_name: &str) -> Self {
428434
unsafe {
429435
let llcx = llvm::LLVMRustContextCreate(tcx.sess.fewer_names());
430436
let llmod_raw = context::create_module(tcx, llcx, mod_name) as *const _;
431-
ModuleLlvm { llmod_raw, llcx, tm: create_informational_target_machine(tcx.sess) }
437+
ModuleLlvm {
438+
llmod_raw,
439+
llcx,
440+
tm: ManuallyDrop::new(create_informational_target_machine(tcx.sess)),
441+
}
432442
}
433443
}
434444

@@ -449,7 +459,7 @@ impl ModuleLlvm {
449459
}
450460
};
451461

452-
Ok(ModuleLlvm { llmod_raw, llcx, tm })
462+
Ok(ModuleLlvm { llmod_raw, llcx, tm: ManuallyDrop::new(tm) })
453463
}
454464
}
455465

@@ -461,6 +471,7 @@ impl ModuleLlvm {
461471
impl Drop for ModuleLlvm {
462472
fn drop(&mut self) {
463473
unsafe {
474+
ManuallyDrop::drop(&mut self.tm);
464475
llvm::LLVMContextDispose(&mut *(self.llcx as *mut _));
465476
}
466477
}

compiler/rustc_mir_build/src/build/mod.rs

+1-11
Original file line numberDiff line numberDiff line change
@@ -656,17 +656,7 @@ fn construct_error(tcx: TyCtxt<'_>, def_id: LocalDefId, guar: ErrorGuaranteed) -
656656
let args = args.as_coroutine();
657657
let yield_ty = args.yield_ty();
658658
let return_ty = args.return_ty();
659-
let self_ty = Ty::new_adt(
660-
tcx,
661-
tcx.adt_def(tcx.lang_items().pin_type().unwrap()),
662-
tcx.mk_args(&[Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, coroutine_ty).into()]),
663-
);
664-
let coroutine_state = Ty::new_adt(
665-
tcx,
666-
tcx.adt_def(tcx.lang_items().coroutine_state().unwrap()),
667-
tcx.mk_args(&[yield_ty.into(), return_ty.into()]),
668-
);
669-
(vec![self_ty, args.resume_ty()], coroutine_state, Some(yield_ty))
659+
(vec![coroutine_ty, args.resume_ty()], return_ty, Some(yield_ty))
670660
}
671661
dk => bug!("{:?} is not a body: {:?}", def_id, dk),
672662
};

compiler/rustc_mir_transform/src/const_prop.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -440,6 +440,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
440440

441441
// FIXME we need to revisit this for #67176
442442
if rvalue.has_param() {
443+
trace!("skipping, has param");
443444
return None;
444445
}
445446
if !rvalue
@@ -708,7 +709,11 @@ impl<'tcx> Visitor<'tcx> for ConstPropagator<'_, 'tcx> {
708709
fn visit_assign(&mut self, place: &Place<'tcx>, rvalue: &Rvalue<'tcx>, location: Location) {
709710
self.super_assign(place, rvalue, location);
710711

711-
let Some(()) = self.check_rvalue(rvalue) else { return };
712+
let Some(()) = self.check_rvalue(rvalue) else {
713+
trace!("rvalue check failed, removing const");
714+
Self::remove_const(&mut self.ecx, place.local);
715+
return;
716+
};
712717

713718
match self.ecx.machine.can_const_prop[place.local] {
714719
// Do nothing if the place is indirect.

compiler/rustc_mir_transform/src/coroutine.rs

-9
Original file line numberDiff line numberDiff line change
@@ -1153,18 +1153,9 @@ fn create_coroutine_drop_shim<'tcx>(
11531153
simplify::remove_dead_blocks(&mut body);
11541154

11551155
// Update the body's def to become the drop glue.
1156-
// This needs to be updated before the AbortUnwindingCalls pass.
11571156
let coroutine_instance = body.source.instance;
11581157
let drop_in_place = tcx.require_lang_item(LangItem::DropInPlace, None);
11591158
let drop_instance = InstanceDef::DropGlue(drop_in_place, Some(coroutine_ty));
1160-
body.source.instance = drop_instance;
1161-
1162-
pm::run_passes_no_validate(
1163-
tcx,
1164-
&mut body,
1165-
&[&abort_unwinding_calls::AbortUnwindingCalls],
1166-
None,
1167-
);
11681159

11691160
// Temporary change MirSource to coroutine's instance so that dump_mir produces more sensible
11701161
// filename.

compiler/rustc_mir_transform/src/shim.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -74,11 +74,13 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<'
7474
let mut body = EarlyBinder::bind(body.clone()).instantiate(tcx, args);
7575
debug!("make_shim({:?}) = {:?}", instance, body);
7676

77-
// Run empty passes to mark phase change and perform validation.
7877
pm::run_passes(
7978
tcx,
8079
&mut body,
81-
&[],
80+
&[
81+
&abort_unwinding_calls::AbortUnwindingCalls,
82+
&add_call_guards::CriticalCallEdges,
83+
],
8284
Some(MirPhase::Runtime(RuntimePhase::Optimized)),
8385
);
8486

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// unit-test: ConstProp
2+
// compile-flags: -O
3+
4+
// Regression test for https://github.com/rust-lang/rust/issues/118328
5+
6+
#![allow(unused_assignments)]
7+
8+
struct SizeOfConst<T>(std::marker::PhantomData<T>);
9+
impl<T> SizeOfConst<T> {
10+
const SIZE: usize = std::mem::size_of::<T>();
11+
}
12+
13+
// EMIT_MIR overwrite_with_const_with_params.size_of.ConstProp.diff
14+
fn size_of<T>() -> usize {
15+
// CHECK-LABEL: fn size_of(
16+
// CHECK: _1 = const 0_usize;
17+
// CHECK-NEXT: _1 = const _;
18+
// CHECK-NEXT: _0 = _1;
19+
let mut a = 0;
20+
a = SizeOfConst::<T>::SIZE;
21+
a
22+
}
23+
24+
fn main() {
25+
assert_eq!(size_of::<u32>(), std::mem::size_of::<u32>());
26+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
- // MIR for `size_of` before ConstProp
2+
+ // MIR for `size_of` after ConstProp
3+
4+
fn size_of() -> usize {
5+
let mut _0: usize;
6+
let mut _1: usize;
7+
scope 1 {
8+
debug a => _1;
9+
}
10+
11+
bb0: {
12+
StorageLive(_1);
13+
_1 = const 0_usize;
14+
_1 = const _;
15+
_0 = _1;
16+
StorageDead(_1);
17+
return;
18+
}
19+
}
20+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// compile-flags: -O
2+
// run-pass
3+
4+
// Regression test for https://github.com/rust-lang/rust/issues/118328
5+
6+
#![allow(unused_assignments)]
7+
8+
struct SizeOfConst<T>(std::marker::PhantomData<T>);
9+
impl<T> SizeOfConst<T> {
10+
const SIZE: usize = std::mem::size_of::<T>();
11+
}
12+
13+
fn size_of<T>() -> usize {
14+
let mut a = 0;
15+
a = SizeOfConst::<T>::SIZE;
16+
a
17+
}
18+
19+
fn main() {
20+
assert_eq!(size_of::<u32>(), std::mem::size_of::<u32>());
21+
}
+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// compile-flags: -Cpanic=unwind --crate-type=lib
2+
// no-prefer-dynamic
3+
// edition:2021
4+
5+
#![feature(coroutines)]
6+
pub fn run<T>(a: T) {
7+
let _ = move || {
8+
drop(a);
9+
yield;
10+
};
11+
}
+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Ensure that coroutine drop glue is valid when mixing different panic
2+
// strategies. Regression test for #116953.
3+
//
4+
// no-prefer-dynamic
5+
// build-pass
6+
// aux-build:unwind-aux.rs
7+
// compile-flags: -Cpanic=abort
8+
// needs-unwind
9+
extern crate unwind_aux;
10+
11+
pub fn main() {
12+
unwind_aux::run(String::new());
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// edition: 2021
2+
3+
async fn asyncfn() {
4+
let binding = match true {};
5+
//~^ ERROR non-exhaustive patterns: type `bool` is non-empty
6+
}
7+
8+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
error[E0004]: non-exhaustive patterns: type `bool` is non-empty
2+
--> $DIR/build-async-error-body-correctly.rs:4:25
3+
|
4+
LL | let binding = match true {};
5+
| ^^^^
6+
|
7+
= note: the matched value is of type `bool`
8+
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
9+
|
10+
LL ~ let binding = match true {
11+
LL + _ => todo!(),
12+
LL ~ };
13+
|
14+
15+
error: aborting due to previous error
16+
17+
For more information about this error, try `rustc --explain E0004`.

0 commit comments

Comments
 (0)