Skip to content

DisableSyntax.NoFinalVal needs to take into account the context #1935

Open
@BalmungSan

Description

@BalmungSan

I totally understand that the old constant-inlining in Scala 2 has some problems, and that Scala 3 inline is better. I also, agree that a final val inside an object or final class is redundant.
However, unless I am missing something like a compiler bug or bad practice (and if that is the case I would highly appreciate the feedback), I think there are valid use cases for making a final val.

I will share the situation in particular that we faced today, but I think the root use case is common enough.

// We have a trait defined in a third-party library.
// Which, among other things, defines a resources abstract method for users to override.
trait ExternalTrait {
  protected type Resources
  protected def resources: Resource[IO, Resources]
}

// And we want to define a custom trait in a company-internal library.
// Which, among other things, abstracts the initialization of the common resources our users need.
trait CompanyTrait extends ExternalTrait {
  override protected final type Resources = CompanyResources
  override protected final val resources: Resource[IO, Resources] = ...
}

// Finally, our users MUST not be able to override our setup.
final class UserClass extends CompanyTrait {
  // resources is accessible here, but not modifiable.
}

This, of course, triggers thenoFinalVal warning / error.

For now, we work around the problem using override protected final def which is fine (and Arman will actually recommend doing that because of performance). But, we wonder if the rule is just too strict (since this feels like a normal use case in OOP) or if using final val in this context is still problematic and thus should be avoided.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions