Well, when you talk about "THE copying machinery" you have to be a bit more specific. There is no such thing as #deepCopy or #shallowCopy in the ANSI Smalltalk standard. Many Smalltalks have
Object>>copy
^self shallowCopy postCopy
and encourage you to override #postCopy.
But nothing stops you doing
MyClass
methods for: 'copying'
copy
^self
deepcopy
^self
postCopy
^self
shallowCopy
^self
You will note that in Pharo, AtomicCollection, Behavior, Boolean,
Character, Float, SmallFloat64, Form, ColorForm, Morph, Paragraph,
Point, SmallInteger, String, UndefinedObject, and perhaps others
override #deepCopy. Also, Boolean, Character, Float, SmallFloat64,
SmallInteger, Symbol, UndefinedObject, and perhaps others
override #shallowCopy.
So it *is* possible to have singletons in Smalltalk.
Classes can be copied in Pharo because someone thought it
would be a good idea.
On to the next point.
'I have an object whose internal state is updated
by incoming messages. I need to take immutable snapshots of that
object's state at some points. And that I do by sending "deepCopy"
and then "beRecursivelyReadOnlyObject".'
You do not know which objects will be copied by #deepCopy and
which won't, or if you do, you cannot be sure that that will not
change in a future release, or indeed if you load a package.
You do not know whether some of these objects will break if made
read-only.
#deepCopy is *serious* "Hic sunt dracones" territory.
It's marked on the Hunt-Lenox Globe, just beside the
Vesuvian introitus ad infernum.
Seriously, the OOP way to do this is
MyClass>>immutableSnapshot
"Answer an immutable copy of myself."
...
and then whatever it takes to make precisely that happen.