No, that is wrong. The issue is that the compiler does world splitting optimizations based on what is in the system image. ! only has methods that return Bool, so uninferred code will still specialize on the Bool output. If there are three types, like Bool, True, and False, then it will create code to union split on those three. If there are 4, like Bool, True, False, and Num (symbolic types), then that is over the limit and it will no longer do any splitting and will dynamically handle the boxed output. I think this is a major over optimization which is contributing to a lot of compilation bloat with little to no real world runtime performance gain, so I would say we should drop the heuristic to 1 and just add one more method to ! to Base and it will be fine.
But, with all of that, if the static types and dispatches were added to the Base system image then it would always default to the three branches and completely remove the invalidations. Maybe that’s not an elegant way to do it, but it makes clear what the issue is and what it’s a fix.
(I would also drop the other union splitting heuristic too, but that’s another matter…)
@oxinabox saw something similar with ChainRulesCore invalidations recently too. I think this heuristic is set in a way that favors recompilation way too much right now, especially since it only (slightly) helps performance of only uninferred code