Enforcing factory method syntax for object creation

In Scala 3, one can always write Hamster("boo") instead of new Hamster("boo"), even if Hamster doesn’t name an object or a method. I love this feature, because I always thought that using new on any public classes is a bad design choice, and in almost all cases a factory method should be used instead, as it makes a refactor much easier if some time later one decides to introduce a MiniatureGiantSpaceHamster extends Hamster, or needs to execute code which - in Scala - cannot be executed in a constructor when creating hamsters.

Therefore, I would really like a compiler flag which forbids the use of new A in any scope other than:

  1. the companion object A.
  2. a method in the same scope as the declaration of A.
    In my eyes it improves code quality for the above reasons so much, that I can’t think of any downsides, other than backwards source compatibility and habit. However, Scala 3 already offers other optional features, such as null being only a valid value for Null (and not Null <:< AnyRef), which I also see no reason for not enabling on new projects.

If it seems like a desirable feature and someone gives me a hint where to start looking, I could try to create a pull request. I have no current knowledge of the compiler code or architecture however, so I don’t really want to spend time learning it unless there is a very high likelihood it would be integrated.

I’ve gotten rid of most of my new during my switch to Scala 3, but I still need them in two cases:

  • After I add an apply method to the companion object, to access a public constructor with a different signature (arguably, I shouldn’t mix constructors and factory methods).

  • For anonymous classes, i.e., new A() with B (or should I replace those with object x extends A with B?).

This would I feel be hard to enforce with the current limitations for factory method syntax. For example, last I checked it didn’t work with type aliases.

Please don’t. It would disallow ad-hoc mixin of traits, like new A with B with C.

I think Wartremover is a good choice for this task. We are planing to use it to restrict using standard mutable collections.