Oh sorry! It seemed the obvious strategy to me since the beginning (cannot allocate before main anyway) so I am afraid I never spelled it out 
As you mention in your revised post, there seems be a division between what you evaluate (any const fn) and what you can store in a const item: UnsafeCell and the like1. While an Arc could be used within the evaluation code, it cannot be stored in .rodata. This seems to mean that some types could be const and others not.
I do disagree slightly with the static BAD: Arc<Mutex<String>> = Arc::new(Mutex::new(String::from("foo")));, I think it should be okay if we let the static or const keyword determine the context of the memory allocations, and thus where they occur. In the case of static it would be in the .data segment, in the case of const in the .rodata segment.
As you mention though, there is at least one hitch: these memory areas are not handled by the memory allocator, and therefore attempting to query them through it is impossible. Unfortunately, instrumenting the call to behave differently when pointing inside .data or .rodata would introduce some overhead on all calls. This issue seems specific to static data though (could @Manishearth confirm?), so maybe just keeping using lazy_static! for such data is fine for now (I don’t personally have any strong urge to make global variables any cheaper or more ergonomic to use anyway).
1 Determining the exact extent of “and the like” is left as an exercise to the poor implementer 