diff options
| author | Ralf Jung <post@ralfj.de> | 2024-03-17 13:42:54 +0100 |
|---|---|---|
| committer | Ralf Jung <post@ralfj.de> | 2024-03-20 11:07:12 +0100 |
| commit | f1ec494c322a2eabbba0bf93867170f702e7a05a (patch) | |
| tree | e225dd8a85d2131df7600ca6d9359d7ac086c41a | |
| parent | 347ca50bc82734b45ed1834fd3a15ed978aba258 (diff) | |
| download | rust-f1ec494c322a2eabbba0bf93867170f702e7a05a.tar.gz rust-f1ec494c322a2eabbba0bf93867170f702e7a05a.zip | |
mentioned items: also handle closure-to-fn-ptr coercions
6 files changed, 99 insertions, 1 deletions
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index f7451e4c916..8e9b095028c 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -324,7 +324,8 @@ pub enum MentionedItem<'tcx> { source_ty: Ty<'tcx>, target_ty: Ty<'tcx>, }, - // FIXME: do we have to add closures? + /// A closure that is coerced to a function pointer. + Closure(DefId, GenericArgsRef<'tcx>), } /// The lowered representation of a single function. diff --git a/compiler/rustc_mir_transform/src/mentioned_items.rs b/compiler/rustc_mir_transform/src/mentioned_items.rs index 0e0114c9d2c..63f898630ab 100644 --- a/compiler/rustc_mir_transform/src/mentioned_items.rs +++ b/compiler/rustc_mir_transform/src/mentioned_items.rs @@ -74,6 +74,22 @@ impl<'tcx> Visitor<'tcx> for MentionedItemsVisitor<'_, 'tcx> { span, }); } + // Similarly, record closures that are turned into function pointers. + mir::Rvalue::Cast( + mir::CastKind::PointerCoercion(PointerCoercion::ClosureFnPointer(_)), + ref operand, + _, + ) => { + let span = self.body.source_info(location).span; + let source_ty = operand.ty(self.body, self.tcx); + match *source_ty.kind() { + ty::Closure(def_id, args) => { + self.mentioned_items + .push(Spanned { node: MentionedItem::Closure(def_id, args), span }); + } + _ => bug!(), + } + } // Function pointer casts are already handled by `visit_constant` above. _ => {} } diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 005a2233507..a5ab4ab3d18 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -1727,6 +1727,12 @@ fn visit_mentioned_item<'tcx>( create_mono_items_for_vtable_methods(tcx, target_ty, source_ty, span, output); } } + MentionedItem::Closure(def_id, args) => { + let instance = Instance::resolve_closure(tcx, def_id, args, ty::ClosureKind::FnOnce); + if should_codegen_locally(tcx, &instance) { + output.push(create_fn_mono_item(tcx, instance, span)); + } + } } } diff --git a/tests/ui/consts/required-consts/collect-in-dead-closure.noopt.stderr b/tests/ui/consts/required-consts/collect-in-dead-closure.noopt.stderr new file mode 100644 index 00000000000..40cecaab241 --- /dev/null +++ b/tests/ui/consts/required-consts/collect-in-dead-closure.noopt.stderr @@ -0,0 +1,23 @@ +error[E0080]: evaluation of `Fail::<i32>::C` failed + --> $DIR/collect-in-dead-closure.rs:8:19 + | +LL | const C: () = panic!(); + | ^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/collect-in-dead-closure.rs:8:19 + | + = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) + +note: erroneous constant encountered + --> $DIR/collect-in-dead-closure.rs:16:17 + | +LL | let _ = Fail::<T>::C; + | ^^^^^^^^^^^^ + +note: the above error was encountered while instantiating `fn not_called::<i32>` + --> $DIR/collect-in-dead-closure.rs:23:33 + | +LL | let _closure: fn() = || not_called::<T>(); + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/required-consts/collect-in-dead-closure.opt.stderr b/tests/ui/consts/required-consts/collect-in-dead-closure.opt.stderr new file mode 100644 index 00000000000..d6298132e1b --- /dev/null +++ b/tests/ui/consts/required-consts/collect-in-dead-closure.opt.stderr @@ -0,0 +1,23 @@ +error[E0080]: evaluation of `Fail::<i32>::C` failed + --> $DIR/collect-in-dead-closure.rs:8:19 + | +LL | const C: () = panic!(); + | ^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/collect-in-dead-closure.rs:8:19 + | + = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) + +note: erroneous constant encountered + --> $DIR/collect-in-dead-closure.rs:16:17 + | +LL | let _ = Fail::<T>::C; + | ^^^^^^^^^^^^ + +note: the above error was encountered while instantiating `fn not_called::<i32>` + --> $DIR/collect-in-dead-closure.rs:23:33 + | +LL | let _closure: fn() = || not_called::<T>(); + | ^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/required-consts/collect-in-dead-closure.rs b/tests/ui/consts/required-consts/collect-in-dead-closure.rs new file mode 100644 index 00000000000..91f52827af4 --- /dev/null +++ b/tests/ui/consts/required-consts/collect-in-dead-closure.rs @@ -0,0 +1,29 @@ +//@revisions: noopt opt +//@ build-fail +//@[opt] compile-flags: -O +//! This fails without optimizations, so it should also fail with optimizations. + +struct Fail<T>(T); +impl<T> Fail<T> { + const C: () = panic!(); //~ERROR evaluation of `Fail::<i32>::C` failed +} + +// This function is not actually called, but it is mentioned in a closure that is coerced to a +// function pointer in dead code in a function that is called. Make sure we still find this error. +#[inline(never)] +fn not_called<T>() { + if false { + let _ = Fail::<T>::C; + } +} + +#[inline(never)] +fn called<T>() { + if false { + let _closure: fn() = || not_called::<T>(); + } +} + +pub fn main() { + called::<i32>(); +} |
