Scala跨版本行为澄清:两种kind-projector编译器插件依赖配置方式的差异疑问
%% and % with cross CrossVersion.full for kind-projector Great question—this is one of those sbt syntax quirks that can feel confusing at first, especially with compiler plugins that have strict cross-version requirements like kind-projector. Let’s break this down clearly:
First, let’s recap the core sbt dependency syntax basics:
%%is sbt’s syntax sugar that automatically appends your project’s binary Scala version (e.g.,2.13) to the artifact ID. So"org.typelevel" %% "kind-projector" % "0.11.3"expands to"org.typelevel" % "kind-projector_2.13" % "0.11.3"by default.%is the raw dependency declaration—no automatic Scala version is added; you’d normally specify the full artifact ID (like"kind-projector_2.13") manually.
Now, cross CrossVersion.full changes everything here. For compiler plugins like kind-projector, which are tightly coupled to specific Scala compiler versions (not just binary-compatible families), this flag tells sbt to ignore the default binary version matching and instead fetch the artifact built for your project’s exact full Scala version (e.g., 2.13.4).
Why both %% and % work with cross CrossVersion.full
Kind-projector publishes its compiler plugin artifacts using full Scala versions (e.g., kind-projector_2.13.4:0.11.3), not binary versions. So regardless of whether you use %% or %, cross CrossVersion.full overrides the default behavior to target these full-version artifacts.
The actual difference between the two lines
Let’s walk through what each does step-by-step:
Using
%%:addCompilerPlugin("org.typelevel" %% "kind-projector" % "0.11.3" cross CrossVersion.full)- First,
%%adds the binary Scala version: artifact ID becomeskind-projector_2.13. - Then,
cross CrossVersion.fullreplaces the binary version suffix with the full Scala version:kind-projector_2.13→kind-projector_2.13.4. - Result: sbt fetches
org.typelevel:kind-projector_2.13.4:0.11.3.
- First,
Using
%:addCompilerPlugin("org.typelevel" % "kind-projector" % "0.11.3" cross CrossVersion.full)%leaves the artifact ID askind-projector(no automatic version suffix).cross CrossVersion.fulldirectly appends the full Scala version to the artifact ID:kind-projector→kind-projector_2.13.4.- Result: sbt fetches the exact same artifact as the
%%version:org.typelevel:kind-projector_2.13.4:0.11.3.
Which should you use?
Both work identically in practice for kind-projector, but the %% syntax is generally preferred:
- It follows sbt’s standard dependency conventions, making your build file more readable to other Scala developers.
- It’s more flexible: if kind-projector ever starts publishing binary-version artifacts (unlikely for compiler plugins, but possible), you could just remove
cross CrossVersion.fullinstead of rewriting the dependency string.
内容的提问来源于stack exchange,提问作者MaatDeamon

