Dramatic performance change by adding additional unused method

I think that is what it is, effectively, if you follow that pattern. You could also parameterize more loosely, like:

struct Mother{T,S,M,PV}
    label::String
    shape::S             # Reference to the actual shape
    material::M                  # Reference to material
    daughters::Vector{PV} 
end

which will allow the types to be concrete, or go for a completely different layout to allow the Mother type to be simpler yet concrete. For instance, if instead of the actual Material as a field you have a label for the material type (as an integer, for instance, to enumerate the materials).

There are some threads discussing this type of pattern:

I am not sure if there is an “ideal” solution (in Julia or other languages). The default performance of what people usually implement in C++ seems to be faster than straightforward Julia implementation of the same thing, but there are a lot of nuances and possibilities which are discussed there.

Yes, thanks, I have to rationalize why these things are not equivalent at some point to remember which is the one that works.