Skip to content

Make assert work as a plain inline function #10354

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

Merged
merged 6 commits into from
Nov 20, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 10 additions & 9 deletions compiler/src/dotty/tools/dotc/transform/Erasure.scala
Original file line number Diff line number Diff line change
Expand Up @@ -588,16 +588,17 @@ object Erasure {
tree.withType(erasure(tree.tpe))

/** This override is only needed to semi-erase type ascriptions */
override def typedTyped(tree: untpd.Typed, pt: Type)(using Context): Tree = {
override def typedTyped(tree: untpd.Typed, pt: Type)(using Context): Tree =
val Typed(expr, tpt) = tree
val tpt1 = tpt match {
case Block(_, tpt) => tpt // erase type aliases (statements) from type block
case tpt => tpt
}
val tpt2 = typedType(tpt1)
val expr1 = typed(expr, tpt2.tpe)
assignType(untpd.cpy.Typed(tree)(expr1, tpt2), tpt2)
}
if tpt.typeOpt.typeSymbol == defn.UnitClass then
typed(expr, defn.UnitType)
else
val tpt1 = tpt match
case Block(_, tpt) => tpt // erase type aliases (statements) from type block
case tpt => tpt
val tpt2 = typedType(tpt1)
val expr1 = typed(expr, tpt2.tpe)
assignType(untpd.cpy.Typed(tree)(expr1, tpt2), tpt2)

override def typedLiteral(tree: untpd.Literal)(using Context): Tree =
if (tree.typeOpt.isRef(defn.UnitClass))
Expand Down
5 changes: 4 additions & 1 deletion compiler/src/dotty/tools/dotc/typer/ReTyper.scala
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import ast.{tpd, untpd, Trees}
import Trees._
import scala.util.control.NonFatal
import util.Spans.Span
import Nullables._

/** A version of Typer that keeps all symbols defined and referenced in a
* previously typed tree.
Expand Down Expand Up @@ -53,13 +54,15 @@ class ReTyper extends Typer with ReChecking {

override def typedTyped(tree: untpd.Typed, pt: Type)(using Context): Tree = {
assertTyped(tree)

val tpt1 = checkSimpleKinded(typedType(tree.tpt))
val expr1 = tree.expr match {
case id: untpd.Ident if (ctx.mode is Mode.Pattern) && untpd.isVarPattern(id) && (id.name == nme.WILDCARD || id.name == nme.WILDCARD_STAR) =>
tree.expr.withType(tpt1.tpe)
case _ => typed(tree.expr)
}
untpd.cpy.Typed(tree)(expr1, tpt1).withType(tree.typeOpt)
val result = untpd.cpy.Typed(tree)(expr1, tpt1).withType(tree.typeOpt)
if ctx.mode.isExpr then result.withNotNullInfo(expr1.notNullInfo) else result
}

override def typedTypeTree(tree: untpd.TypeTree, pt: Type)(using Context): TypeTree =
Expand Down
4 changes: 4 additions & 0 deletions compiler/test/dotc/pos-test-pickling.blacklist
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,7 @@ i8651b.scala

# uneliminated @uncheckedVariance after pickling
annot-bootstrap.scala

# interaction with Scala-2's implicitly
i9793.scala

Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,9 @@ class InlineBytecodeTests extends DottyBytecodeTest {
}
}

@Test def inlineLocally = {
/** Disabled since locally comes from Predef now
@Test
def inlineLocally = {
val source =
"""
|class Foo {
Expand Down Expand Up @@ -103,6 +105,7 @@ class InlineBytecodeTests extends DottyBytecodeTest {
diffInstructions(instructions1, instructions2))
}
}
*/

@Test def i4947 = {
val source = """class Foo {
Expand Down
45 changes: 4 additions & 41 deletions library/src/dotty/DottyPredef.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,48 +3,11 @@ package dotty
object DottyPredef {
import compiletime.summonFrom

inline final def assert(inline assertion: Boolean, inline message: => Any): Unit = {
if (!assertion)
scala.runtime.Scala3RunTime.assertFailed(message)
}

transparent inline final def assert(inline assertion: Boolean): Unit = {
if (!assertion)
scala.runtime.Scala3RunTime.assertFailed()
}
inline def assert(inline assertion: Boolean, inline message: => Any): Unit =
if !assertion then scala.runtime.Scala3RunTime.assertFailed(message)

inline final def implicitly[T](implicit ev: T): T = ev

/** Used to mark code blocks as being expressions, instead of being taken as part of anonymous classes and the like.
* This is just a different name for [[identity]].
*
* @example Separating code blocks from `new`:
* {{{
* val x = new AnyRef
* {
* val y = ...
* println(y)
* }
* // the { ... } block is seen as the body of an anonymous class
*
* val x = new AnyRef
*
* {
* val y = ...
* println(y)
* }
* // an empty line is a brittle "fix"
*
* val x = new AnyRef
* locally {
* val y = ...
* println(y)
* }
* // locally guards the block and helps communicate intent
* }}}
* @group utilities
*/
inline def locally[T](inline body: T): T = body
inline def assert(inline assertion: Boolean): Unit =
if !assertion then scala.runtime.Scala3RunTime.assertFailed()

/**
* Retrieve the single value of a type with a unique inhabitant.
Expand Down
2 changes: 1 addition & 1 deletion tests/neg/implicitSearch.check
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@
-- Error: tests/neg/implicitSearch.scala:15:38 -------------------------------------------------------------------------
15 | listOrd(listOrd(implicitly[Ord[T]] /*not found*/)) // error
| ^
| no implicit argument of type Test.Ord[T] was found for parameter ev of method implicitly in object DottyPredef
| no implicit argument of type Test.Ord[T] was found for parameter e of method implicitly in object Predef
Binary file modified tests/run/nullAsInstanceOf.check
Binary file not shown.
2 changes: 1 addition & 1 deletion tests/semanticdb/expect/ValPattern.expect.scala
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class ValPattern/*<-example::ValPattern#*/ {
rightVar/*->example::ValPattern#rightVar().*/
)
)
locally/*->dotty::DottyPredef.locally().*/ {
locally/*->scala::Predef.locally().*/ {
val (left/*<-local0*/, right/*<-local1*/) = (/*->scala::Tuple2.apply().*/1, 2)
val Some/*->scala::Some.*//*->scala::Some.unapply().*/(number1/*<-local2*/) =
Some/*->scala::Some.*//*->scala::Some.apply().*/(1)
Expand Down
2 changes: 1 addition & 1 deletion tests/semanticdb/expect/local-file.expect.scala
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package example

class `local-file/*<-example::`local-file`#*/` {
locally/*->dotty::DottyPredef.locally().*/ {
locally/*->scala::Predef.locally().*/ {
val local/*<-local0*/ = 42
local/*->local0*/ +/*->scala::Int#`+`(+4).*/ 4
}
Expand Down
4 changes: 2 additions & 2 deletions tests/semanticdb/metac.expect
Original file line number Diff line number Diff line change
Expand Up @@ -2778,7 +2778,7 @@ Occurrences:
[20:8..20:18): number1Var -> example/ValPattern#number1Var().
[21:8..21:15): leftVar -> example/ValPattern#leftVar().
[22:8..22:16): rightVar -> example/ValPattern#rightVar().
[25:4..25:11): locally -> dotty/DottyPredef.locally().
[25:4..25:11): locally -> scala/Predef.locally().
[26:11..26:15): left <- local0
[26:17..26:22): right <- local1
[26:27..26:27): -> scala/Tuple2.apply().
Expand Down Expand Up @@ -3153,7 +3153,7 @@ Occurrences:
[0:8..0:15): example <- example/
[2:7..2:17): local-file <- example/`local-file`#
[3:2..3:2): <- example/`local-file`#`<init>`().
[3:2..3:9): locally -> dotty/DottyPredef.locally().
[3:2..3:9): locally -> scala/Predef.locally().
[4:8..4:13): local <- local0
[5:4..5:9): local -> local0
[5:10..5:11): + -> scala/Int#`+`(+4).
Expand Down