-
Notifications
You must be signed in to change notification settings - Fork 29k
[SPARK-31190][SQL] ScalaReflection should not erasure user defined AnyVal type #27959
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -611,10 +611,39 @@ object ScalaReflection extends ScalaReflection { | |
| } | ||
| } | ||
|
|
||
| private def erasure(tpe: Type): Type = { | ||
| // For user-defined AnyVal classes, we should not erasure it. Otherwise, it will | ||
| // resolve to underlying type which wrapped by this class, e.g erasure | ||
| // `case class Foo(i: Int) extends AnyVal` will return type `Int` instead of `Foo`. | ||
| // But, for other types, we do need to erasure it. For example, we need to erasure | ||
| // `scala.Any` to `java.lang.Object` in order to load it from Java ClassLoader. | ||
| // Please see SPARK-17368 & SPARK-31190 for more details. | ||
| if (isSubtype(tpe, localTypeOf[AnyVal]) && !tpe.toString.startsWith("scala")) { | ||
| tpe | ||
| } else { | ||
| tpe.erasure | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What does erasure do here?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Basically, it convert a Scala type to Java type. e.g. |
||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Returns the full class name for a type. The returned name is the canonical | ||
| * Scala name, where each component is separated by a period. It is NOT the | ||
| * Java-equivalent runtime name (no dollar signs). | ||
| * | ||
| * In simple cases, both the Scala and Java names are the same, however when Scala | ||
| * generates constructs that do not map to a Java equivalent, such as singleton objects | ||
| * or nested classes in package objects, it uses the dollar sign ($) to create | ||
| * synthetic classes, emulating behaviour in Java bytecode. | ||
| */ | ||
| def getClassNameFromType(tpe: `Type`): String = { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. do we need to quote
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't know it clearly...just copied from the original one. |
||
| erasure(tpe).dealias.typeSymbol.asClass.fullName | ||
| } | ||
|
|
||
| /* | ||
| * Retrieves the runtime class corresponding to the provided type. | ||
| */ | ||
| def getClassFromType(tpe: Type): Class[_] = mirror.runtimeClass(tpe.dealias.typeSymbol.asClass) | ||
| def getClassFromType(tpe: Type): Class[_] = | ||
| mirror.runtimeClass(erasure(tpe).dealias.typeSymbol.asClass) | ||
|
|
||
| case class Schema(dataType: DataType, nullable: Boolean) | ||
|
|
||
|
|
@@ -863,20 +892,6 @@ trait ScalaReflection extends Logging { | |
| tag.in(mirror).tpe.dealias | ||
| } | ||
|
|
||
| /** | ||
| * Returns the full class name for a type. The returned name is the canonical | ||
| * Scala name, where each component is separated by a period. It is NOT the | ||
| * Java-equivalent runtime name (no dollar signs). | ||
| * | ||
| * In simple cases, both the Scala and Java names are the same, however when Scala | ||
| * generates constructs that do not map to a Java equivalent, such as singleton objects | ||
| * or nested classes in package objects, it uses the dollar sign ($) to create | ||
| * synthetic classes, emulating behaviour in Java bytecode. | ||
| */ | ||
| def getClassNameFromType(tpe: `Type`): String = { | ||
| tpe.dealias.erasure.typeSymbol.asClass.fullName | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why it's a problem only for AnyVal? Here we blindly erasure everything.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For a AnVal class, e.g. |
||
| } | ||
|
|
||
| /** | ||
| * Returns the parameter names and types for the primary constructor of this type. | ||
| * | ||
|
|
||
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 we add some comments to explain why we special case
AnyVal?