diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs index b6691df39c120..411a6e7e6238e 100644 --- a/src/librustc/ty/instance.rs +++ b/src/librustc/ty/instance.rs @@ -173,10 +173,7 @@ impl<'tcx> InstanceDef<'tcx> { // available to normal end-users. return true } - let codegen_fn_attrs = tcx.codegen_fn_attrs(self.def_id()); - // need to use `is_const_fn_raw` since we don't really care if the user can use it as a - // const fn, just whether the function should be inlined - codegen_fn_attrs.requests_inline() || tcx.is_const_fn_raw(self.def_id()) + tcx.codegen_fn_attrs(self.def_id()).requests_inline() } } diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index 8e27635dee8c1..977285b27be38 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -178,10 +178,6 @@ //! Some things are not yet fully implemented in the current version of this //! module. //! -//! ### Initializers of Constants and Statics -//! Since no MIR is constructed yet for initializer expressions of constants and -//! statics we cannot inspect these properly. -//! //! ### Const Fns //! Ideally, no mono item should be generated for const fns unless there //! is a call to them that cannot be evaluated at compile time. At the moment @@ -191,7 +187,6 @@ use rustc::hir::{self, CodegenFnAttrFlags}; use rustc::hir::itemlikevisit::ItemLikeVisitor; -use rustc::hir::Node; use rustc::hir::def_id::DefId; use rustc::mir::interpret::{AllocId, ConstValue}; use rustc::middle::lang_items::{ExchangeMallocFnLangItem, StartFnLangItem}; @@ -741,27 +736,27 @@ fn should_monomorphize_locally<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, instance: ty::InstanceDef::CloneShim(..) => return true }; - return match tcx.hir.get_if_local(def_id) { - Some(Node::ForeignItem(..)) => { - false // foreign items are linked against, not codegened. - } - Some(_) => true, - None => { - if tcx.is_reachable_non_generic(def_id) || - tcx.is_foreign_item(def_id) || - is_available_upstream_generic(tcx, def_id, instance.substs) - { - // We can link to the item in question, no instance needed - // in this crate - false - } else { - if !tcx.is_mir_available(def_id) { - bug!("Cannot create local mono-item for {:?}", def_id) - } - true - } - } - }; + if tcx.is_foreign_item(def_id) { + // We can always link to foreign items + return false; + } + + if def_id.is_local() { + // local items cannot be referred to locally without monomorphizing them locally + return true; + } + + if tcx.is_reachable_non_generic(def_id) || + is_available_upstream_generic(tcx, def_id, instance.substs) { + // We can link to the item in question, no instance needed + // in this crate + return false; + } + + if !tcx.is_mir_available(def_id) { + bug!("Cannot create local mono-item for {:?}", def_id) + } + return true; fn is_available_upstream_generic<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId, diff --git a/src/test/codegen-units/item-collection/unreferenced-const-fn.rs b/src/test/codegen-units/item-collection/unreferenced-const-fn.rs index c4a49fd4ec4d6..5e181870fed65 100644 --- a/src/test/codegen-units/item-collection/unreferenced-const-fn.rs +++ b/src/test/codegen-units/item-collection/unreferenced-const-fn.rs @@ -11,11 +11,10 @@ // ignore-tidy-linelength // compile-flags:-Zprint-mono-items=lazy -// NB: We do not expect *any* monomorphization to be generated here. - #![deny(dead_code)] #![crate_type = "rlib"] +//~ MONO_ITEM fn unreferenced_const_fn::foo[0] @@ unreferenced_const_fn-cgu.0[External] pub const fn foo(x: u32) -> u32 { x + 0xf00 } diff --git a/src/test/ui/consts/auxiliary/const_fn_lib.rs b/src/test/ui/consts/auxiliary/const_fn_lib.rs index 5063c8d1d1f54..72369aae97ce3 100644 --- a/src/test/ui/consts/auxiliary/const_fn_lib.rs +++ b/src/test/ui/consts/auxiliary/const_fn_lib.rs @@ -10,6 +10,24 @@ // Crate that exports a const fn. Used for testing cross-crate. +#![feature(const_fn)] #![crate_type="rlib"] -pub const fn foo() -> usize { 22 } //~ ERROR const fn is unstable +pub const fn foo() -> usize { 22 } + +pub const fn bar() -> fn() { + fn x() {} + x +} + +#[inline] +pub const fn bar_inlined() -> fn() { + fn x() {} + x +} + +#[inline(always)] +pub const fn bar_inlined_always() -> fn() { + fn x() {} + x +} diff --git a/src/test/ui/consts/const_fn_return_nested_fn_ptr.rs b/src/test/ui/consts/const_fn_return_nested_fn_ptr.rs new file mode 100644 index 0000000000000..c7617c9c7ad03 --- /dev/null +++ b/src/test/ui/consts/const_fn_return_nested_fn_ptr.rs @@ -0,0 +1,10 @@ +// compile-pass +// aux-build:const_fn_lib.rs + +extern crate const_fn_lib; + +fn main() { + const_fn_lib::bar()(); + const_fn_lib::bar_inlined()(); + const_fn_lib::bar_inlined_always()(); +}