Simulacrum Scalafix
This project began as an experiment in rewriting Typelevel Simulacrum as a set of Scalafix rules. It's currently still a proof-of-concept, but it is able to replace Simulacrum 1 in the Cats repository without breaking any tests or binary-compatibility checks.
Please see this Cats issue for discussion about this experiment.
Development of this tool has been supported by Permutive. Please see our monthly reports for updates on the work of the Permutive Community Engineering team.
Simulacrum rules
Simulacrum 1's @typeclass
macro annotation adds three kinds of boilerplate, which this project factors into three Scalafix rules:
AddSerializable
: This rule addsextends Serializable
to the root type classes in a type class hierarchy.AddImplicitNotFound
: This rule adds custom@implicitNotFound
annotations for type classes.TypeClassSupport
: This rule adds a summoner method and syntax method support to the type class companion object.
Dotty compatibility rules
This repo currently includes a few miscellaneous Scalafix rules that may be useful for experimenting with Dotty cross-compilation:
ExpandPolymorphicLambdas
: This rule rewrites kind-projector's polymorphic lambda values to explicit anonymous class instantiations that work on both Scala 2 and Dotty.ExpandTypeLambdas
: This rule rewrites (a large subset of) kind-projector's type lambda syntax to a representation that currently works on both Scala 2 and Dotty.ParenthesizeLambdaParamWithType
: This rule parenthesizes lambda parameters with type annotations as needed.
The first rule may be used in Cats—it's not yet clear whether the polymorphic SAM support that may eventually be added to Dotty will support cross-building there.
The latter two rules should no longer be necessary in most cases, since Dotty now supports a subset of kind-projector's syntax via the -Ykind-projector
compiler option, and can add parentheses to lambda parameters with type annotations with -language:Scala2Compat -rewrite
.
Building Cats without macro annotations
It's not currently possible to build Cats with Dotty because Simulacrum 1 uses macro annotations, which Dotty doesn't support. The goal of this project is to change that by providing a non-macro-annotation-based version of Simulacrum.
I have a Cats branch that demonstrates how these Scalafix rules work. You can follow along with the following steps:
- Add Scalafix and the locally-published Scalafix rules to the Cats build and remove Simulacrum 1, Macro Paradise, etc. This takes about eight lines of configuration.
- Add
@noop
annotations toFlatMap#ifM
,Functor#ifF
, andMonad#whileM
andwhileM_
. This is necessary for compatibility because Simulacrum 1 didn't handle these methods. - Open an sbt console in the Cats repo and run the following commands:
sbt:cats> scalafix AddSerializable sbt:cats> scalafix AddImplicitNotFound sbt:cats> scalafix TypeClassSupport sbt:cats> scalafmtAll
50 files changed, 2461 insertions(+), 17 deletions(-)
- Run
sbt validateJVM
to verify that tests and binary-compatibility checks pass after the change (andsbt ++2.13.1 buildJVM
if you want to check Scala 2.13 as well).
Cross-building cats-core on Dotty
The instructions below are not up-to-date with Cats master, although they should still work. Please follow this work-in-progress PR for the current status of Dotty cross-building.
You can add Dotty cross-building with a few additional steps:
- Add build configuration for Dotty. This is a net couple dozen lines.
- Move the one macro definition in cats-core into a Scala 2-specific source directory tree.
- Expand type lambdas and polymorphic function value definitions with the following commands:
sbt:cats> +scalafix ExpandTypeLambdas sbt:cats> +scalafix ExpandPolymorphicLambdas sbt:cats> +scalafmtAll
- Add a couple of casts that Dotty needs for some reason.
- Compile on Dotty:
sbt:cats> ++0.21.0-bin-20191201-65a404f-NIGHTLY sbt:cats> coreJVM/compile sbt:cats> kernelLawsJVM/compile sbt:cats> alleycatsCoreJVM/compile
Community
People are expected to follow the Scala Code of Conduct on GitHub and in any other project channels.
License
This experimental code is licensed under the Apache License, Version 2.0 (the "License"); you may not use this software except in compliance with the License.
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.