No object/primitive distinction, but you have to explicitly make objects and methods nullable, and the dereference operator is null-safe. (You use the dereference operator on a null object, you get null. You use the dereference operator to call a nullable method on a null object, you get null. It is a compile-time error to call a non-nullable method on a nullable reference where the compiler cannot prove that it won't be null. Pure functions are implicitly nullable.)
It is a compile-time error if you assign a nullable reference to a non-nullable reference and the compiler cannot prove that it won't be null.
I've also had an idea for what I call a "pseudo-statically typed" language: instead of checking types at compile time, it checks that you implement all functions called on the parameter at compile time. Public variables are just syntactic sugar for getX/setX, operations are just syntactic sugar for addX/subX/etc. If you define a method with an input type of X, the compiler checks that you only call methods that are defined in X, and then replaces the type with the methods actually called.
But nullable "primitives" can actually be useful occasionally, for caching, for example. Having a separate boolean flag works, but can be inefficient (you can store null internally as NaN with a specific payload, for example, whereas a boolean flag generally requires at least a byte, more with alignment. This also allows easier atomic updates.)