Change:
Adding to 's definition works around the ICE. Also, the bug doesn't trigger if is an non- , so it's not just that is inlined cross-crate, but -specific behavior is also involved. cc
Still happens on the latest nightly. cc It doesn't block , but the workaround in that PR is a bit ugly.
I have a fix in

Discussion:
// available to normal end-users. return true } <del> 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()) </del> <ins> tcx.codegen_fn_attrs(self.def_id()).requests_inline() </ins> } }

//! Some things are not yet fully implemented in the current version of this //! module. //! <del> //! ### Initializers of Constants and Statics //! Since no MIR is constructed yet for initializer expressions of constants and //! statics we cannot inspect these properly. //! </del> //! ### 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

use rustc::hir::{self, CodegenFnAttrFlags}; use rustc::hir::itemlikevisit::ItemLikeVisitor; <del> use rustc::hir::Node; </del> use rustc::hir::def_id::DefId; use rustc::mir::interpret::{AllocId, ConstValue}; use rustc::middle::lang_items::{ExchangeMallocFnLangItem, StartFnLangItem};

ty::InstanceDef::CloneShim(..) => return true }; <del> 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 } } }; </del> <ins> 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; </ins> fn is_available_upstream_generic<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId,

// ignore-tidy-linelength // compile-flags:-Zprint-mono-items=lazy <del> // NB: We do not expect *any* monomorphization to be generated here. </del> #![deny(dead_code)] #![crate_type = "rlib"] <ins> //~ MONO_ITEM fn unreferenced_const_fn::foo[0] @@ unreferenced_const_fn-cgu.0[External] </ins> pub const fn foo(x: u32) -> u32 { x + 0xf00 }

// Crate that exports a const fn. Used for testing cross-crate. <ins> #![feature(const_fn)] </ins> #![crate_type="rlib"] <del> pub const fn foo() -> usize { 22 } //~ ERROR const fn is unstable </del> <ins> 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 } </ins>

<ins> // 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()(); } </ins>