Skip to content

Add a phase to Dotty that hides Dotty bottom types from JVM. #1002

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
wants to merge 5 commits into from

Conversation

DarkDimius
Copy link
Contributor

It is very convenient to have bottom types in type system. Unfortunately
JVM does not have bottom types and we need to insert casts that would make
bytecode pass verification.

@DarkDimius
Copy link
Contributor Author

/rebuild

@DarkDimius
Copy link
Contributor Author

@odersky please review.

@@ -263,6 +263,12 @@ object Erasure extends TypeTestsCasts{
else
cast(tree, pt)
}


/** Is `tpe` a type which is a bottom type for Dotty, but not a bottom type for JVM */
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no bottom type on the JVM so I don't really understand the naming of this function, how is it different from Definitions#isBottomType?

@smarter
Copy link
Member

smarter commented Dec 18, 2015

Nothing is supposed to have no value, so I don't know if allowing null.asInstanceOf[Nothing] to run without any error is a good thing or not, maybe it doesn't matter.

/** Is `tpe` a type which is a bottom type for Dotty, but not a bottom type for JVM */
def isNonJVMBottomType(tpe: Type)(implicit ctx: Context): Boolean = {
tpe.derivesFrom(ctx.definitions.NothingClass) || tpe.derivesFrom(ctx.definitions.NullClass)
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, why not use Definitions#isBottomType?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Definitions#isBottomType(tp) is defined to be tp.symbol \in {NothingClass, NullClass}
It does not work for types that do not return a usable symbol, such as And\Or types.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should I update Definitions#isBottomType to account for Null | Nothing and Int & Nothing?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, I think it's OK to leave the two separate. Maybe rename the second to
derivesFromBottomType
to make clear that refinements and & / | count as well?

On Fri, Dec 18, 2015 at 6:32 PM, Dmitry Petrashko [email protected]
wrote:

In src/dotty/tools/dotc/transform/Erasure.scala
#1002 (comment):

@@ -263,6 +263,12 @@ object Erasure extends TypeTestsCasts{
else
cast(tree, pt)
}
+
+

  • /** Is tpe a type which is a bottom type for Dotty, but not a bottom type for JVM */
  • def isNonJVMBottomType(tpe: Type)(implicit ctx: Context): Boolean = {
  •  tpe.derivesFrom(ctx.definitions.NothingClass) || tpe.derivesFrom(ctx.definitions.NullClass)
    
  • }
    }

Should I update Definitions#isBottomType to account for Null | Nothing
and Int & Nothing?


Reply to this email directly or view it on GitHub
https://github.com/lampepfl/dotty/pull/1002/files#r48048942.

Martin Odersky
EPFL

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will do.

@DarkDimius
Copy link
Contributor Author

@smarter

Nothing is supposed to have no value, so I don't know if allowing null.asInstanceOf[Nothing] to run without any error is a good thing or not, maybe it doesn't matter.

I do not have a strong opinion on this either. So I've implemented be compatible with scalac mode.

class A {
 val s: Nothing  = null.asInstanceOf[Nothing]
}

scalac emmits:

public class A {
    private final Nothing. s = null;

    public Nothing. s() {
        return this.s;
    }
}

PS: the . in Nothing. is not a printing error. Nothing is replaced by Nothing$ in a late transformation done by GenBCode.

@smarter
Copy link
Member

smarter commented Dec 20, 2015

Being compatible with scalac seems OK here, but note that the following fails at runtime in scalac but works with your patch:

object X {
  def main(args: Array[String]): Unit = {
    val x: Int = null.asInstanceOf[Nothing]
  }
}

@smarter
Copy link
Member

smarter commented Dec 20, 2015

And now that I think about it, this might be a good think because in the following:

object X {
  def main(args: Array[String]): Unit = {
    val x: Int = null.asInstanceOf
  }
}

The type parameter of asInstanceOf will be instantiated to Nothing, so it crashes at runtime in scalac but works in dotty with your patch.

/** Is `tpe` a type which is a bottom type for Dotty, but not a bottom type for JVM */
def isNonJVMBottomType(tpe: Type)(implicit ctx: Context): Boolean = {
tpe.derivesFrom(ctx.definitions.NothingClass) || tpe.derivesFrom(ctx.definitions.NullClass)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I now did a similar change in definitions (f780a37).
So it's best if you cherry-pick the commit and use defn.isBottomType.

@DarkDimius DarkDimius self-assigned this Jan 3, 2016
It is very convenient to have bottom types in type system.
Unfortunately JVM does not have bottom types and we need to insert
casts that would make bytecode pass verification.
@DarkDimius DarkDimius force-pushed the fix-#828 branch 2 times, most recently from 45278e1 to 64e17d0 Compare January 4, 2016 10:40
@DarkDimius DarkDimius removed their assignment Jan 4, 2016
@DarkDimius
Copy link
Contributor Author

I've addressed most comments except the (null.asInstanceOf[Nothing]): Int) one.
I do not have a clear understanding of how this works in scalac and why is it different from the other case.
If you someone is interested to get to the bottom of this, It could be done in a different PR. This one fixes a compiler crash so I'd like to get this in.

@sjrd
Copy link
Member

sjrd commented Jan 4, 2016

FTR, in Scala.js we recently decided to go against what scalac/JVM does for null.asInstanceOf[Nothing]. Now it always throws immediately (as a ClassCastException/undefined behavior). See the PR scala-js/scala-js#2126 fixing issue scala-js/scala-js#2125

@smarter
Copy link
Member

smarter commented Jan 4, 2016

@DarkDimius
Copy link
Contributor Author

java.lang.OutOfMemoryError: GC overhead limit exceeded

/rebuild

@odersky
Copy link
Contributor

odersky commented Jul 27, 2016

Let's either rebase and try again or close.

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

Successfully merging this pull request may close these issues.

5 participants