pharo
pharo copied to clipboard
Be robust against unintentionally sending #initialize to a Trait
Bug description
Object class>>#initialize is implemented as:
initialize
"This method is empty but this is on purpose. This is to protect subclasses that are wrongly calling super initialize or classes that are receiving initialize.
If you remove this method, the method Behavior >> initialize will be executed and the class will be nuked because reinitialized."
That is a nice safety net for the reasons described in the method comment.
However, there is no safety net for initializing Traits by accident. If one would try initializing a Trait, e.g. MyTrait initialize, then ClassDescription>>#initialize does the initialization:
initialize
super initialize.
self resetProtocols
The super send triggers Behavior>>#initialize:
initialize
"moved here from the class side's #new"
super initialize.
self basicSuperclass: Object.
"no longer sending any messages, some of them crash the VM"
self methodDict: self emptyMethodDictionary.
self setFormat: Object format
This method clears the method dictionary. That is not desired. When making the mistake to initialize Traits as part of initializing all classes in a baseline for instance, it is very confusing that after loading the baseline, traits have no methods.
Suggested fix
It would be better to put a safety net in place for such mistakes, similar to Object class>>#initialize. A new method Trait>>#initialize could be the safety net:
initialize
"This method is empty but this is on purpose. This is to protect subclasses that are receiving initialize.
If you remove this method, the method Behavior >> initialize will be executed and the trait will be nuked because reinitialized."
Another implementation could be to not be silent and signal an error.
Version information
- Pharo 13
Additional context
cc @MarcusDenker This is the root cause of the problem I discussed and investigated with you during the Pharo Sprint of May 23, 2025.
If this bug report is considered to be valid, I am happy to create PR with the suggested fix.
Tx good catch! I thought that we fixed the Object class >> initialize too. I remember working on it.
Do not you think that the solution should be
Trait class>> initialize
...
@Ducasse I made a stupid mistake. Of course the class method #initialize has to be implemented with an empty body:
Trait class >> #initialize
"This method is empty but this is on purpose. This is to protect subclasses that are receiving initialize.
If you remove this method, the method Behavior >> initialize will be executed and the trait will be nuked because reinitialized."
Tx good catch! I thought that we fixed the Object class >> initialize too. I remember working on it.
You did. That is what I wrote at the top of the ticket 😀. Object class>>#initialize is empty.
Nice, I will do PRs for both Pharo13 and Pharo14
This has been fixed
Thank you!