When designing and implenting an object-oriented programming language, at some point one must make a choice about implementing fundamental types (like
double or equivalents) as classes or something else. Clearly, languages in the C family have a tendency not to define them as classes (Java has special primitive types, C# implements them as immutable structs, etc).
I can think of a very important advantage when fundamental types are implemented as classes (in a type system with a unified hierarchy): these types can be proper Liskov subtypes of the root type. Thus, we avoid complicating the language with boxing/unboxing (either explicit or implicit), wrapper types, special variance rules, special behavior, etc.
Of course, I can partially understand why language designers decide the way they do: class instances tend to have some spatial overhead (because the instances may contain a vtable or other metadata in their memory layout), that primitives/structs don't need to have (if the language doesnt allow inheritance on those).
Is spatial efficiency (and improved spatial locality, especially in large arrays) the only reason why fundamental types are often not classes?
I've generally assumed the answer to be yes, but compilers have escape analysis algorithms and thus they can deduce whether they can (selectively) omit the spatial overhead when an instance (any instance, not just a fundamental type) is proven to be strictly local.
Is the above wrong, or is there something else I'm missing?