mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 06:44:35 +00:00
mentioned items: also handle closure-to-fn-ptr coercions
This commit is contained in:
parent
347ca50bc8
commit
f1ec494c32
@ -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.
|
||||
|
@ -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.
|
||||
_ => {}
|
||||
}
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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`.
|
@ -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`.
|
29
tests/ui/consts/required-consts/collect-in-dead-closure.rs
Normal file
29
tests/ui/consts/required-consts/collect-in-dead-closure.rs
Normal file
@ -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>();
|
||||
}
|
Loading…
Reference in New Issue
Block a user