-
Notifications
You must be signed in to change notification settings - Fork 14.8k
MINOR: Make the build compile with Scala 2.13 #6989
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
Conversation
|
retest this please |
|
retest this please |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@hachikuji @jsancio Do you know why this was a Set? It seems to me that a Map makes more sense, but I thought I'd ask for a second opinion and I know you have made changes to related code recently.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree, a Map makes more sense. Thanks for the change.
|
Not sure why the PR builder for Scala 2.13 is not triggering automatically. I started it manually: |
jsancio
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great! Thanks for doing this @ijuma
What your thought on removing our usage of deprecated classes and methods like JavaConverters, filterKeys, etc?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the suggested way of doing this do that it has the same behaviour in Scala 2.11, 2.12 and 2.13 is ...asScala.view.filterKeys(_.startsWith("...")).toMap.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Views have a lot of problems in 2.11 and 2.12 so we generally stay away from them (they were completely rewritten in Scala 2.13). For code like this where performance doesn't matter, it's fine to go with the simple approach.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you remember what are these issues?
I am aware of GC pressure for long lived "view" objects since they hold on to the underlining collection. I don't think this issue applies here since filterKeys creates a "view" which is converted to a strict Map and we never store a reference to the "view".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are several bugs, particularly in 2.11. You can search the bug tracker if you like. People working on the standard library don't recommend views, they suggest iterator instead. The migration notes for 2.13 also don't mention views as the replacement for the idiom, the example given:
| mapValues and filterKeys now return a MapView instead of a Map | kvs.mapValues(f) | kvs.mapValues(f).toMap |
|---|
A recent article talks about two issues: https://www.scala-lang.org/blog/2017/11/28/view-based-collections.html
I also recall an article showing that views didn't even perform better than the strict equivalent in many scenarios they were designed for.
Personally, I don't think it's worth the additional complexity (particularly around debugging).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay. Thanks for the information. The deprecation notice for filterKeys says:
(Since version 2.13.0) Use .view.filterKeys(f). A future version will include a strict version of this method (for now, .view.filterKeys(p).toMap).
Looks like there may be some inconsistency in the documentation. Like you say, in this particular code it doesn't matter much but maybe we should do what you did in a few other places:
scalaMap.filter { case (key, value) => predicate(key) }
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, I changed filterKeys to filter here and a few other places.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can be simplified by merging these two lines to getCommittedOffsets(groupId).keys.toSeq.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think importing scala.collection.{Set, Seq, Map, etc} causes a lot of issues. I think this is going to be even more problematic with 2.13. I think we should ban these imports and only allow the Predef imports, scala.collection.mutable and scala.collection.immutable. What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you elaborate on the issues you are thinking of? The Predef imports are all about immutable collections and they have different performance characteristics and I don't think it makes sense to make that change for Scala 2.13 support.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we take Map as an example, the issue is that collection.Map, collection.immutable.Map and collection.mutable.Map are all different types. collection.Map is a parent both mutable and immutable but the reality is that collection.Map cannot be safely downcasted to collection.immutable.Map or collection.mutable.Map.
[info] Compiling 1 Scala source to target/scala-2.12/classes ...
[error] TestCollection.scala:16:22: type mismatch;
[error] found : Map[String,String] (in scala.collection)
[error] required: Map[String,String] (in scala.collection.immutable)
[error] expectImmutableMap(map)
[error] ^
[error] TestCollection.scala:18:22: type mismatch;
[error] found : Map[String,String] (in scala.collection.mutable)
[error] required: Map[String,String] (in scala.collection.immutable)
[error] expectImmutableMap(mutableMap)
[error] ^
[error] TestCollection.scala:20:20: type mismatch;
[error] found : Map[String,String] (in scala.collection)
[error] required: Map[String,String] (in scala.collection.mutable)
[error] expectMutableMap(map)
[error] ^
[error] TestCollection.scala:21:20: type mismatch;
[error] found : Map[String,String] (in scala.collection.immutable)
[error] required: Map[String,String] (in scala.collection.mutable)
[error] expectMutableMap(immutableMap)
[error] ^
[error] four errors found
It is very rare that we have code that is generic over mutable vs immutable collection. I think that this conversions are simplify is we require a concrete version like collection.immtable.Map or collection.mutable.Map.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Predef imports are all about immutable collections
This is true except for Seq but they are fixing this in Scala 2.13. In the other Scala version Seq was a alias for collection.Seq which is the parent class for collection.immutable.Seq and collection.mutable.Seq.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's worth understanding the context. The Kafka code was written with the assumption that the Seq in Predef was not immutable. In Scala 2.13 it has become immutable. The simplest change to maintain existing assumptions is to add import scala.collection.Seq everywhere. In the future, we can consider other changes, I don't think they should be in the Scala 2.13 PR.
In this particular class, I did add an import to scala.collection.Map and I can remove that if that's what you are objecting to.
It is very rare that we have code that is generic over mutable vs immutable collection.
I don't think this is true, a lot of code just does map/filter/flatMap/foreach/etc. Such code doesn't care whether the collection is mutable or immutable.
but the reality is that collection.Map cannot be safely downcasted to collection.immutable.Map or collection.mutable.Map
I don't think you should ever downcast collections outside of very specialized collection utility code (e.g. a method that converts from one collection to another could do this for best performance).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here also. I think the recommend way to guarantee the same behaviour across Scala version (lazy eval) is to do ...all.get().asScala.view.mapValues(_.asScala).toMap
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I responded to the other comment. Let's discuss it there and we'll do here whatever we agree there.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about proposedReplicaAssignment.view.filterKeys(...).toMap?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See my comment about views being discouraged in Scala 2.11 and Scala 2.12.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about newConfig.originals.asScala.view.filterKeys(...).filterKeys(...).toMap?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's discuss this in the other comment about views. :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I find that one line imports like some.package.{One, Two, Three} lead to unnecessary merge conflicts. How about encouraging one line imports like:
import some.package.One
import some.package.Two
...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the current style. If we want to change it, let's start a discussion in the mailing list.
|
3 test failures remaining:
@debasishg Any idea why the Streams tests are failing with a ClassCastException?
|
|
I figured out the reason for the Streams failure and pushed a fix (8139e52d2aa92322504). I'm not sure if this is an intentional change in Scala 2.13, but the behavior of something like the following has changed:
Assume the existance of |
|
Sounds like "Explicit imports now shadow locally defined identifiers" scala/scala#6589 |
|
apologies @ijuma - I am offsite in some team meeting and could not take a look. Thanks for the fix. |
|
Thanks for the reference @ennru. No worries @debasishg. :) |
…iority over the Scala ones
…r included by default in the standard library.
…s with Scala 2.13
… returns MapView in Scala 2.13
…partitionRatio` correctly
|
I fixed the bug causing the remaining test to fail. Rebased and pushed. |
…code did not compile with Scala 2.13
|
Jenkins build with Scala 2.13: https://builds.apache.org/job/kafka-pr-jdk11-scala2.13/21/ |
|
retest this please |
|
Scala 2.11 and 2.12 builds are green. Scala 2.13 had one seemingly unrelated test failure: Started another 2.13 build just in case. This is ready for review. |
|
Last run for Scala 2.13 had 2 flaky Connect failures that passed in the previous run:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ijuma Thanks for the PR. Changes looks good to me. I haved used https://docs.scala-lang.org/overviews/core/collections-migration-213.html for reference.
|
Thanks for the review, another run of the Scala 2.13 had another unrelated flaky test failure:
Merging to master. |
|
Is there a ticket I can link to from https://github.com/scala/make-release-notes/blob/2.13.x/projects-2.13.md#pending that people can subscribe to track progress on a release that includes 2.13 support? |
|
@SethTisue This will be part of 2.4, the next release. We don't have a ticket for upcoming releases, we will have a release plan wiki page linked from https://cwiki.apache.org/confluence/display/KAFKA/Future+release+plan (we do releases every 4 months). |
Scala 2.13 support was added to build via #5454. This PR adjusts the code so that
it compiles with 2.11, 2.12 and 2.13.
Changes:
scala-collection-compatdependency.scala.collection.Seqin a number of places for consistent behavior betweenScala 2.11, 2.12 and 2.13.
Scala ones, related Scala issue: Explicit imports now shadow locally defined identifiers scala/scala#6589.
Future. The former is no longer included bydefault in the standard library.
filterKeyswithfilterwhen we expect aMap.filterKeysreturns a viewthat doesn't implement the
Maptrait in Scala 2.13.mapValueswithmapor add atoMapas an additional transformationwhen we expect a
Map.mapValuesreturns a view that doesn't implement theMaptrait in Scala 2.13.breakOutwithiteratorandto,breakOutwas removed in Scala2.13.
mutable.Buffer.--withfilterNot.Factoryinstead ofCanBuildFromin DecodeJson.CanBuildFrombehavesa bit differently in Scala 2.13 and it's been deprecated.
Factoryhas the behaviorwe need and it's available via the compat library.
"Map.values.map is not strict in Scala 2.13" (Map.values.map is not strict in Scala 2.13 scala/bug#11589).
Iterableinstead ofSeqto avoidunnecessary collection copies.
tocall thatdoesn't work in Scala 2.13.
maps require an
Orderingin Scala 2.13 for safety reasons.ConsumerGroupCommandto compile with Scala 2.13.Iterableinstead ofTraversableOnce, the latter doesnot exist in Scala 2.13.
Unitwith()in a couple places. Scala 2.13 is stricter when it expectsa value instead of a type.
partitionRatiocorrectly,
forallcan terminate early.places.
CoreUtils.JSONEscapeString.Committer Checklist (excluded from commit message)