Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can nature of dependency on scalac-compat be clarified? #793

Open
Thrillpool opened this issue Feb 8, 2025 · 2 comments
Open

Can nature of dependency on scalac-compat be clarified? #793

Thrillpool opened this issue Feb 8, 2025 · 2 comments

Comments

@Thrillpool
Copy link

Thrillpool commented Feb 8, 2025

I notice that as of 2.13 (of cats-core), due to typelevel/cats@c442521#diff-7c156dc8732800194b79210cf462828782dcdf1b516cfc26f72afe892f8d279cR53, if you have like

class C extends cats.instances.AllInstances {}

and compile against scala 2.12, you get compilation error

[error] Symbol 'type org.typelevel.scalaccompat.annotation.unused' is missing from the classpath.
[error] This symbol is required by ' <none>'.
[error] Make sure that type unused is in your classpath and check for conflicting dependencies with `-Ylog-classpath`.
[error] A full rebuild may help if 'MapInstances.class' was compiled against an incompatible version of org.typelevel.scalaccompat.annotation.
[error] class C extends cats.instances.AllInstances {}

(actually in reality, the context I found this in was more a lot more confusing, scala compiler didn't at all point me to correct line or file causing the issue 😞 ).

Anyway, org.typelevel.scalaccompat.annotation.unused is indeed in scalasignature of MapInstances class, and reading https://github.com/typelevel/scalac-compat/blob/main/annotation/src/main/scala-2.12/org/typelevel/scalaccompat/annotation/unused.scala I guess this is all 'as intended'.

That's all /fine/ and scalac-compat is listed as provided dependency, and if you add it as dependency, OK my code example works.

Questions are

  1. Why is it provided dependency? To me looking through the 3 usages of scalaccompat in codebase it (naively) seems more like it should be that scalac-compat is compile dependency for 2.12, and not listed as dependency for other scala versions (in the poms).
  2. If it is to stay as provided dependency, should it be written down in some documentation that one needs to provide it when using scala 2.12, and probably noted in https://github.com/typelevel/cats/releases/tag/v2.13.0.
@armanbilge armanbilge transferred this issue from typelevel/cats Feb 8, 2025
@armanbilge
Copy link
Member

Thanks for reporting! I transferred here because the dependency is declared in sbt-typelevel.

Seq("org.typelevel" %% "scalac-compat-annotation" % "0.1.4" % Provided)

Why is it provided dependency?

The intention was to express that scalac-compat is needed only at compile-time, not runtime. Some history (cc @satorg):

seems more like it should be that scalac-compat is compile dependency for 2.12, and not listed as dependency for other scala versions

Actually, it is a compile-time dependency for all Scala versions. We use it in a variety of ways.

If it is to stay as provided dependency, should it be written down in some documentation

Instead of documentation, we should probably drop Provided. Maybe there is no good way to express this compile-time-only semantic 😕

@Thrillpool
Copy link
Author

Thrillpool commented Feb 8, 2025

Hmm yep, good point all are compile time (for consumers) dependency of cats, for those interested org.typelevel.scalaccompat.annotation.uncheckedVariance2 and org.typelevel.scalaccompat.annotation.unused in scala 2.13 are aliases for standard lib annotations, but org.typelevel.scalaccompat.annotation.targetName3 isn't :(.

Re rationale, yes I think there is no good semantic built into poms/sbt, Provided isn't strictly the right semantic and more just incidental that it does sort of the right thing, 'provided' as maven intended means something external provides at runtime (https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html), e.g. spark dependencies are 'provided' by a spark runtime.

It's actually not super clear to me what's best then 😕.


As I see things, most important thing is just that users of cats know 'yes it is expected some times that at compile time you will need dependency on scalac-compat', because really the resolution to compiler error is clear, it's just that finding out /why/ you need to do so isn't at all clear. I think this issue existing more or less resolves that, and I'm happy at least that I know what to do in original context that I found this thing.

The issues with that are

  1. it feels strange to add explicit compile time dependency on code you never yourself use
  2. it's plausible in future that cats updates its internal dependency on scalac-compat to refer to a newly added annotation say, and then you need to in your project update the scalac-compat dependency which is upsetting.

Longer term, I guess there doesn't feel like a huge amount of options, you can imagine either an sbt plugin associated with cats that does the work of managing this scalac-compat dependency for you (i.e. like what TypelevelSettingsPlugin.scala is doing, but probably solely adding scalac-compat-annotation dependency).

Or it would be nice if something that gets published could have some metadata in it, that sbt could then read and natively know to do compile-only stuff, I'm mostly familar with Gradle, and there they actually made their whole own alternative to poms as they were so upset with the limitations... https://github.com/gradle/gradle/blob/master/platforms/documentation/docs/src/docs/design/gradle-module-metadata-latest-specification.md

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants