Skip to content

Command line options to control Scala versions and migration? #8571

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

Closed
odersky opened this issue Mar 18, 2020 · 17 comments
Closed

Command line options to control Scala versions and migration? #8571

odersky opened this issue Mar 18, 2020 · 17 comments

Comments

@odersky
Copy link
Contributor

odersky commented Mar 18, 2020

We should regularize our options for controlling language versions and migration.

The current state

Option What it does
-language:Scala2Compat Some effort is made to support Scala-2 idioms.
-migration Issue migration warnings, otherwise these are bunched, like deprecation warnings
-rewrite When used with -migration perform some rewrites from Scala 2 -> Scala 3
-strict Keep to a stricter language that avoids some fragile or unsound code

A possible alternative

Option What it does
-source Set source version. Legal values for now: 3.0, 3.1. 3.0 is the default.
-migration Some effort is made to also support earlier language versions (such as Scala 2.13, or Scala 3.0 if -source is 3.1) and migration warnings are issued where something is no longer supported without -migration in the new source version. Migration warnings are always emitted, never bunched
-rewrite When used with -migration perform some automatic rewrites from old to new version

So, we'd have the following equivalences between current state and alternative:

  • -language:Scala2Compat -migration maps to -source 3.0 -migration or simply -migration
  • -language:Scala2Compat -migration -rewrite maps to -migration -rewrite
  • -strict maps to -source 3.1
  • -language:Scala2Compat alone does not map to anything -- you can't support dropped features without migration warnings.

Btw, what was the motivation in Scala 2 to use -Xsource:version instead of -source version as Java does? It seems source version should be a standard option, so -X seems out of place.

@dwijnand
Copy link
Member

Btw, what was the motivation in Scala 2 to use -Xsource:version instead of -source version as Java does? It seems source version should be a standard option, so -X seems out of place.

Jason: I also wonder if this option should be -Y for now. Is it really ready to show up in scala -help?
Iulian: If you prefer to hide this option from users, I don't mind not showing it in the scalac -help page.. how about -X? I thought -Y is private/debugging options, while -X is experimental. Either way is fine with me.
Jason: -X is probably suitable. This option sort of generalizes the existing option -Xfuture.

(scala/scala#3340 (comment))

@smarter
Copy link
Member

smarter commented Mar 18, 2020

Some effort is made to also support earlier language versions (such as Scala 2.13, or Scala 3.0 if -source is 3.1)

I think having the semantics of -migration depend on the value passed to another flag (-source) can too easily lead to confusion. Can we try to use a single flag instead ? Whatever Scala version N I'm using, I can set -source M, if M < N, this enables migration warnings for dropped features (or error out if support for these features has since been fully removed from the compiler). If M > N, this enables preview features. I think that's how -Xsource in Scala 2 already behaves.

@smarter
Copy link
Member

smarter commented Mar 18, 2020

Btw, what was the motivation in Scala 2 to use -Xsource:version instead of -source version as Java does?

My understanding is that -Xsource is not officially supported/recommended because it's only very lightly tested (ideally you'd want to run the whole test suite with every value of the flag) /cc @SethTisue

@dwijnand
Copy link
Member

My understanding is that -Xsource is not officially supported/recommended because it's only very lightly tested (ideally you'd want to run the whole test suite with every value of the flag)

Yeah, that's right: scala/bug#11661

@odersky
Copy link
Contributor Author

odersky commented Mar 19, 2020

@smarter

Can we use a single flag instead?

There's the immediate problem that we should not have a flag -source 2.13, since that would be a lie.

Also, there are the following scenarios, which I don't see how to support with a single flag:

  • The compiler is on 3.0, but I already want to adhere to the tighter standard of 3.1. I want errors, not warnings. I could use -Xfatal-warnings, but I feel that's a separate concern.
  • The compiler is on 3.1 (because it's hopefully much better than the 3.0 compiler), but I want to stick to -source 3.0 because my sources cross-compile with 2.13. I do not want migration warnings or rewrite options to upgrade to 3.1. These would be besides the point.
  • The compiler is on 3.1, but I am still compiling an old Scala 2.13 source that I want to upgrade to 3.0. So I want migration warnings and rewrites to go from 2.13 to 3.0, but not further.

The combination of -source and -migration covers all these scenarios naturally. I believe it is easy to remember, too: -source sets the language version and -migration helps migrating older code to that version.

@smarter
Copy link
Member

smarter commented Mar 19, 2020

There's the immediate problem that we should not have a flag -source 2.13, since that would be a lie.

It's not much or of a lie than having -source 3.0 in Scala 3.1: it will never behave exactly like Scala 3.0 in all aspects. If the name is too misleading, we could use -compat instead maybe.

Also, there are the following scenarios, which I don't see how to support with a single flag:

I think that all of those scenarios can be handled by the new configurable warning mechanism from scala/scala#8373, which we should implement and consider improving before adding a separate overlapping warning mechanism control just for migration.

@odersky
Copy link
Contributor Author

odersky commented Mar 19, 2020

I think we can do a credible job to support -source 3.0 in 3.1. It will be mostly just syntax restrictions and extensions: Don't use features shipped in 3.1., and continue to support already implemented features in 3.0 in later versions under a flag. That does not look so hard.

I do not think configurable warnings is a substitute, and am in fact quite sceptical about that development.
Configurable warnings is a super-rich and complex feature for true expert users. I do not think normal developers should be burdened with it. But everyone will have to migrate across versions, and that should be possible without plunging into configurable warnings.

The reason I am sceptical about configurable warnings is that it could start a development where we end up with another complex nightmare like sbt. Because warnings are now configurable, there will be many more of them, with intricate categories for flitering. I somehow do not think that's the right way to go!

@odersky
Copy link
Contributor Author

odersky commented Mar 19, 2020

Concrete scenario: I am using the 3.1 compiler (because it's great!) but our code base is on 3.0 (because cross-compile). I compile with -source 3.0 according to your proposal I get migration warnings whenever I use a feature that is no longer supported in 3.1.

Whatever Scala version N I'm using, I can set -source M, if M < N, this enables migration warnings for dropped features (or error out if support for these features has since been fully removed from the compiler).

But that's not what I want! I want it to accept all 3.0 features without warnings. Instead I want errors if a 3.1 feature is used in that codebase.

@smarter
Copy link
Member

smarter commented Mar 19, 2020

I am using the 3.1 compiler (because it's great!) but our code base is on 3.0 (because cross-compile).

You mean, cross-compile with 2.13 ? If this is a common usecase, then maybe we just need to ensure that we can cross-compile between 2.13/3.1 the same way we can between 2.13/3.0.

if a 3.1 feature is used in that codebase.

How do we define what a 3.1 feature is ? Is this about source-compat, tasty-compat, binary-compat, or all of them ?

@smarter
Copy link
Member

smarter commented Mar 19, 2020

If I'm using -source 3.0, am I also prevented from using new APIs introduced in the 3.1 standard library ?

@odersky
Copy link
Contributor Author

odersky commented Mar 19, 2020

You mean, cross-compile with 2.13 ? If this is a common usecase, then maybe we just need to ensure that we can cross-compile between 2.13/3.1 the same way we can between 2.13/3.0.

We probably can't: Let's say 3.1 will drop support for implicits. How do you cross-compile then?

About coverage: It's source compat, and language only. Libraries are not affected. I believe that's also the case for Java.

@odersky
Copy link
Contributor Author

odersky commented Mar 19, 2020

One possible refinement would be to have a separate source level for 2.13/3.0 cross compiles. Something like -source 2x3. We could probably never guarantee Scala 2.13 compatibility, but we could give it a good shot to disallow most features that would prevent cross compilation.

@som-snytt
Copy link
Contributor

I had this question the other day because of the migration section on "Given Imports / Importing Givens". I wanted strict behavior of wildcard import of implicits, but didn't know how to ask for -source 3.1. I'm not sure it's implemented under -strict.

In Scala 2, -Xsource:3 is aspirational. -Xsource:haskell means you took the other color pill. Downgrading with -Xsource was never a goal.

-Xmigration:2.12 says I'm coming from 2.12, warn about changes since then. I don't care that io.Codec.toUTF8 was misnamed fromUTF8 in Scala 2.8.

On the other hand, I do care about old deprecations. My deprecator plugin would turn old deprecations into errors, for example, warnings older than 2.12.

Deprecations are really a kind of migration message. But policy around how they are managed is not trivial. Summaries such as 55 deprecations since 2.10 are not informative or actionable.

I agree warnings should be limited, or rather eliminated, except for -migration warnings about language changes that would otherwise error. I might have liked a nicer name for the language feature, such as import language.compat.aida and compat.dongiovanni. Obviously, 3.1 will become compat.cosifantutte or figaro if opera names includes names in operas.

Even deprecations can be pushed to an external linter. In Scala 2, deprecations are emitted for language changes, but -migration is a much better tool for "grandparenting" in old code.

I agree that warning suppression is a symptom of too many warnings to manage.

Sometimes it's easier to shut down all the trash compactors on the detention level.

@odersky
Copy link
Contributor Author

odersky commented Mar 30, 2020

Scenarios:

  • I want to cross compile between Scala 2 and Scala 3: -source 2x3.
  • I want help with migration to Scala 3: -migration
  • I want help with migration to the cross-compilable subset: -source 2x3 -migration
  • I want to make sure my code is future-proof for 3.1: -source 3.1.
  • I want help making my code future-proof for 3.1: -source 3.1 -migration
  • My compiler's version is3.1, but I want to stick to the more lenient 3.0 version for the moment: -source 3.0.
  • My compiler's version is 3.1, but I want to stick to the cross-compilable subset: -source 2x3.

Are there other scenarios that we should consider?

@smarter
Copy link
Member

smarter commented Apr 6, 2020

@sjrd If you have time, your opinion on this subject would be appreciated :) (Martin is planning to implement this stuff soon).

@lrytz
Copy link
Member

lrytz commented Apr 7, 2020

What would these flags do? Would -source 2x3 report code that Scala 2 doesn't understand? As warnings, or errors? Would it allow things that are forbidden in 3 (like auto-application)? Is -migration rewriting the code, or adding more warnings/erros?

In 2.13 we're following the strategy that -Xsource:3 should give the same errors/warnings as Scala 3. Also, what is an error in 3 has to be a (deprecation) warning in plain 2.13, without additional flags (e.g., procedure syntax, auto application).

@odersky
Copy link
Contributor Author

odersky commented Apr 8, 2020

Would -source 2x3 report code that Scala 2 doesn't understand?

Yes, it would try to do some approximation of that. Violations would be errors,

Would it allow things that are forbidden in 3 (like auto-application)?

No, for that you would need source 2x3 -migration (or -source 2x3-migration according to #8700).

Is -migration rewriting the code, or adding more warnings/erros?

It only rewrites code in conjunction with -rewrite. Besides that it

  • turns some errors into migration warnings
  • it changes some rules to be compatible with 2.13
  • it gives some additional warnings where the rules has changed.

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

No branches or pull requests

6 participants