Change:
This is ICE happens when I call from the abistable crate in const contexts in dependent crates/doctests, but not when using the associated constant. It can be reproduced using a doctest in the playground: It can also be reproduced by cloning ,and then build lib1. The code for the linked repositories is : lib0: lib_1: This is the error message:
cc
I think we have another issue open for another symptom of this bug but I can't find it. Basically the problem is that we fail to recognize that the allocation containing the function pointer came from another crate and thus was already collected. Since we don't realize we don't need to collect the alloc, we do so and try to collect the function pointers in it. Maybe we can cause the same bug by having a const fn return a function pointer and then storing that in a constant.
These also produce the same error(when running doctests): /// const ICEICE:fn()=playground::returnsfnptr(); /// /// const ICEICE:fn()=playground::FN_PTR; /// Error:
OK, so essentially it boils down to "don't try to monomorphize functions that can't be monomorphized locally, and assume they have been monomorphized upstream". Going for that logic will fix all of the ICEs we've had at this site, but also turn hypothetical compiler bugs that were ICEs into linker errors (undefined reference)
cc I see no other way (see previous post) to prevent the collector from trying to collect function pointers in constants if the function comes from a different crate, without breaking the case where we need to collect the function pointer because the function comes from the local crate. We may have local constants with function pointers to functions from other crates and constants with references to constants from other crates that contain function pointers. So there's no use in checking where the constant came from. Const eval could theoretically return a list of created function pointers, but that would just be a complicated way of subverting the ICE. We can make sure to just silence the ICE in the constant case, to ensure it still catches bugs in the regular case. Opinions?
Assigning and to discuss options here. P-high to revisit.
I think the way we handled situations like this in the past was to make the pass expand the set of items that are considered to be reachable by downstream crates. However, I'm not sure if it is powerful enough to provide a permanent solution. Some backround: IIRC, the privacy pass collects the set of items that are publicly visible from outside the crate, and the reachable expands this set by things that might be needed to instantiate the initial set of items in a downstream crate. E.g. if there is a public generic function that calls a private generic function, then it is the pass that makes sure that the MIR of private generic function is available downstream. Or if there is a public generic function that accesses a private non-generic function, it is the reachable pass that makes sure that the private function is exported from the object file so we can link against it. So, maybe the right solution here would be to make the reachable pass add things reachable from constants. Then the following check would make sure that we link to the upstream item: Looking through the code in , it looks like this should already be the case. Maybe it's just a subtle bug somewhere?
The problem isn't constants (which are checked correctly). It's const fns. s are handled just like normal functions, which don't treat things inside their body as reachable. So presumably all we need to do is make also treat as ?
So presumably all we need to do is make also treat const fn as inline? If the problem is that things in functions are not marked as reachable, then that solution is exactly what I'd expect.
Impl instructions: the FnHeader field from and check the field. If it's const, the same thing for by checking 's field () for and fetch the from that variant. tests from this issue
Nice! Thanks for writing up the instructions and for implementing them!

Discussion:
} match item.node { <ins> hir::ItemKind::Fn(_, header, ..) if header.is_const() => { return true; } </ins> hir::ItemKind::Impl(..) | hir::ItemKind::Fn(..) => { let generics = tcx.generics_of(tcx.hir().local_def_id(item.hir_id));

if codegen_fn_attrs.requests_inline() || generics.requires_monomorphization(tcx) { return true } <ins> if let hir::ImplItemKind::Method(method_sig, _) = &impl_item.node { if method_sig.header.is_const() { return true } } </ins> if let Some(impl_hir_id) = tcx.hir().as_local_hir_id(impl_src) { match tcx.hir().find(impl_hir_id) { Some(Node::Item(item)) =>

<ins> pub struct VTable{ state:extern fn(), } impl VTable{ pub const fn vtable()->&'static VTable{ Self::VTABLE } const VTABLE: &'static VTable = &VTable{state}; } extern fn state() {} </ins>

<ins> // aux-build:issue-63226.rs // compile-flags:--extern issue_63226 // edition:2018 // build-pass // A regression test for issue #63226. // Checks if `const fn` is marked as reachable. use issue_63226::VTable; static ICE_ICE:&'static VTable=VTable::vtable(); fn main() {} </ins>