Skip to content
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

Don't emit line number for synthetic unit value #18717

Merged
merged 1 commit into from
Oct 18, 2023
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
45 changes: 22 additions & 23 deletions compiler/src/dotty/tools/backend/jvm/BCodeSkelBuilder.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,24 @@ package backend
package jvm

import scala.language.unsafeNulls

import scala.annotation.tailrec

import scala.collection.{ mutable, immutable }

import scala.collection.{immutable, mutable}
import scala.tools.asm
import dotty.tools.dotc.ast.tpd
import dotty.tools.dotc.ast.TreeTypeMap
import dotty.tools.dotc.CompilationUnit
import dotty.tools.dotc.core.Decorators._
import dotty.tools.dotc.core.Flags._
import dotty.tools.dotc.core.StdNames._
import dotty.tools.dotc.core.NameKinds._
import dotty.tools.dotc.ast.Trees.SyntheticUnit
import dotty.tools.dotc.core.Decorators.*
import dotty.tools.dotc.core.Flags.*
import dotty.tools.dotc.core.StdNames.*
import dotty.tools.dotc.core.NameKinds.*
import dotty.tools.dotc.core.Names.TermName
import dotty.tools.dotc.core.Symbols._
import dotty.tools.dotc.core.Types._
import dotty.tools.dotc.core.Contexts._
import dotty.tools.dotc.util.Spans._
import dotty.tools.dotc.core.Symbols.*
import dotty.tools.dotc.core.Types.*
import dotty.tools.dotc.core.Contexts.*
import dotty.tools.dotc.util.Spans.*
import dotty.tools.dotc.report
import dotty.tools.dotc.transform.SymUtils._
import dotty.tools.dotc.transform.SymUtils.*

/*
*
Expand Down Expand Up @@ -624,16 +622,17 @@ trait BCodeSkelBuilder extends BCodeHelpers {
case _ => a
}

if (!emitLines || !tree.span.exists) return;
val nr = ctx.source.offsetToLine(tree.span.point) + 1
if (nr != lastEmittedLineNr) {
lastEmittedLineNr = nr
getNonLabelNode(lastInsn) match {
case lnn: asm.tree.LineNumberNode =>
// overwrite previous landmark as no instructions have been emitted for it
lnn.line = nr
case _ =>
mnode.visitLineNumber(nr, currProgramPoint())
if (emitLines && tree.span.exists && !tree.hasAttachment(SyntheticUnit)) {
val nr = ctx.source.offsetToLine(tree.span.point) + 1
if (nr != lastEmittedLineNr) {
lastEmittedLineNr = nr
getNonLabelNode(lastInsn) match {
case lnn: asm.tree.LineNumberNode =>
// overwrite previous landmark as no instructions have been emitted for it
lnn.line = nr
case _ =>
mnode.visitLineNumber(nr, currProgramPoint())
}
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions compiler/src/dotty/tools/dotc/ast/Desugar.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1844,7 +1844,7 @@ object desugar {
case ts: Thicket => ts.trees.tail
case t => Nil
} map {
case Block(Nil, EmptyTree) => Literal(Constant(())) // for s"... ${} ..."
case Block(Nil, EmptyTree) => unitLiteral // for s"... ${} ..."
case Block(Nil, expr) => expr // important for interpolated string as patterns, see i1773.scala
case t => t
}
Expand Down Expand Up @@ -1872,7 +1872,7 @@ object desugar {
val pats1 = if (tpt.isEmpty) pats else pats map (Typed(_, tpt))
flatTree(pats1 map (makePatDef(tree, mods, _, rhs)))
case ext: ExtMethods =>
Block(List(ext), Literal(Constant(())).withSpan(ext.span))
Block(List(ext), unitLiteral.withSpan(ext.span))
case f: FunctionWithMods if f.hasErasedParams => makeFunctionWithValDefs(f, pt)
}
desugared.withSpan(tree.span)
Expand Down
2 changes: 2 additions & 0 deletions compiler/src/dotty/tools/dotc/ast/Trees.scala
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ object Trees {

/** Property key for backquoted identifiers and definitions */
val Backquoted: Property.StickyKey[Unit] = Property.StickyKey()

val SyntheticUnit: Property.StickyKey[Unit] = Property.StickyKey()

/** Trees take a parameter indicating what the type of their `tpe` field
* is. Two choices: `Type` or `Untyped`.
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/ast/tpd.scala
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
ta.assignType(untpd.Literal(const))

def unitLiteral(using Context): Literal =
Literal(Constant(()))
Literal(Constant(())).withAttachment(SyntheticUnit, ())

def nullLiteral(using Context): Literal =
Literal(Constant(null))
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/ast/untpd.scala
Original file line number Diff line number Diff line change
Expand Up @@ -492,7 +492,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
def InferredTypeTree(tpe: Type)(using Context): TypedSplice =
TypedSplice(new InferredTypeTree().withTypeUnchecked(tpe))

def unitLiteral(implicit src: SourceFile): Literal = Literal(Constant(()))
def unitLiteral(implicit src: SourceFile): Literal = Literal(Constant(())).withAttachment(SyntheticUnit, ())

def ref(tp: NamedType)(using Context): Tree =
TypedSplice(tpd.ref(tp))
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/inlines/Inliner.scala
Original file line number Diff line number Diff line change
Expand Up @@ -793,7 +793,7 @@ class Inliner(val call: tpd.Tree)(using Context):
typed(tree.cond, defn.BooleanType)(using condCtx) match {
case cond1 @ ConstantValue(b: Boolean) =>
val selected0 = if (b) tree.thenp else tree.elsep
val selected = if (selected0.isEmpty) tpd.Literal(Constant(())) else typed(selected0, pt)
val selected = if (selected0.isEmpty) tpd.unitLiteral else typed(selected0, pt)
if (isIdempotentExpr(cond1)) selected
else Block(cond1 :: Nil, selected)
case cond1 =>
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/inlines/Inlines.scala
Original file line number Diff line number Diff line change
Expand Up @@ -408,7 +408,7 @@ object Inlines:
arg match
case ConstantValue(_) | Inlined(_, Nil, Typed(ConstantValue(_), _)) => // ok
case _ => report.error(em"expected a constant value but found: $arg", arg.srcPos)
return Literal(Constant(())).withSpan(call.span)
return unitLiteral.withSpan(call.span)
else if inlinedMethod == defn.Compiletime_codeOf then
return Intrinsics.codeOf(arg, call.srcPos)
case _ =>
Expand Down
8 changes: 4 additions & 4 deletions compiler/src/dotty/tools/dotc/parsing/Parsers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2211,7 +2211,7 @@ object Parsers {
case _ =>
}
patch(source, cond.span.endPos, "}) ()")
WhileDo(Block(body, cond), Literal(Constant(())))
WhileDo(Block(body, cond), unitLiteral)
}
case TRY =>
val tryOffset = in.offset
Expand Down Expand Up @@ -2241,7 +2241,7 @@ object Parsers {
in.nextToken();
val expr = subExpr()
if expr.span.exists then expr
else Literal(Constant(())) // finally without an expression
else unitLiteral // finally without an expression
}
else {
if handler.isEmpty then
Expand Down Expand Up @@ -3728,10 +3728,10 @@ object Parsers {
val stats = selfInvocation() :: (
if (isStatSep) { in.nextToken(); blockStatSeq() }
else Nil)
Block(stats, Literal(Constant(())))
Block(stats, unitLiteral)
}
}
else Block(selfInvocation() :: Nil, Literal(Constant(())))
else Block(selfInvocation() :: Nil, unitLiteral)

/** SelfInvocation ::= this ArgumentExprs {ArgumentExprs}
*/
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/transform/DropBreaks.scala
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ class DropBreaks extends MiniPhase:
case id: Ident =>
val arg = (args: @unchecked) match
case arg :: Nil => arg
case Nil => Literal(Constant(())).withSpan(tree.span)
case Nil => unitLiteral.withSpan(tree.span)
Some((id.symbol, arg))
case _ => None
case _ => None
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/transform/Erasure.scala
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,7 @@ object Erasure {
cast(tree1, pt)
case _ =>
val cls = pt.classSymbol
if (cls eq defn.UnitClass) constant(tree, Literal(Constant(())))
if (cls eq defn.UnitClass) constant(tree, unitLiteral)
else {
assert(cls ne defn.ArrayClass)
ref(unboxMethod(cls.asClass)).appliedTo(tree)
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/transform/Memoize.scala
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ class Memoize extends MiniPhase with IdentityDenotTransformer { thisPhase =>
myState.classesThatNeedReleaseFence += sym.owner
val initializer =
if isErasableBottomField(field, tree.termParamss.head.head.tpt.tpe.classSymbol)
then Literal(Constant(()))
then unitLiteral
else Assign(ref(field), adaptToField(field, ref(tree.termParamss.head.head.symbol)))
val setterDef = cpy.DefDef(tree)(rhs = transformFollowingDeep(initializer)(using ctx.withOwner(sym)))
sym.keepAnnotationsCarrying(thisPhase, Set(defn.SetterMetaAnnot))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -947,7 +947,7 @@ object PatternMatcher {
case LabeledPlan(label, expr) =>
Labeled(label, emit(expr))
case ReturnPlan(label) =>
Return(Literal(Constant(())), ref(label))
Return(unitLiteral, ref(label))
case plan: SeqPlan =>
def default = seq(emit(plan.head) :: Nil, emit(plan.tail))
def maybeEmitSwitch(scrutinee: Tree): Tree = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,7 @@ object TypeTestsCasts {
Typed(expr, tree.args.head) // Replace cast by type ascription (which does not generate any bytecode)
else if (testCls eq defn.BoxedUnitClass)
// as a special case, casting to Unit always successfully returns Unit
Block(expr :: Nil, Literal(Constant(()))).withSpan(expr.span)
Block(expr :: Nil, unitLiteral).withSpan(expr.span)
else if (foundClsSymPrimitive)
if (testCls.isPrimitiveValueClass) primitiveConversion(expr, testCls)
else derivedTree(box(expr), defn.Any_asInstanceOf, testType)
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/typer/RefChecks.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1578,7 +1578,7 @@ class RefChecks extends MiniPhase { thisPhase =>
private def transformIf(tree: If): Tree = {
val If(cond, thenpart, elsepart) = tree
def unitIfEmpty(t: Tree): Tree =
if (t == EmptyTree) Literal(Constant(())).setPos(tree.pos).setType(UnitTpe) else t
if (t == EmptyTree) unitLiteral.setPos(tree.pos).setType(UnitTpe) else t

cond.tpe match {
case ConstantType(value) =>
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/typer/Typer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4216,7 +4216,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
if (!ctx.isAfterTyper && !tree.isInstanceOf[Inlined] && ctx.settings.WvalueDiscard.value && !isThisTypeResult(tree)) {
report.warning(ValueDiscarding(tree.tpe), tree.srcPos)
}
return tpd.Block(tree1 :: Nil, Literal(Constant(())))
return tpd.Block(tree1 :: Nil, unitLiteral)
}

// convert function literal to SAM closure
Expand Down
19 changes: 19 additions & 0 deletions compiler/test/dotty/tools/backend/jvm/DottyBytecodeTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1682,6 +1682,25 @@ class DottyBytecodeTests extends DottyBytecodeTest {
assertSameCode(instructions, expected)
}
}

@Test def i18320(): Unit = {
val c1 =
"""class C {
| def m: Unit = {
| val x = 1
| }
|}
|""".stripMargin
checkBCode(c1) {dir =>
val clsIn = dir.lookupName("C.class", directory = false).input
val clsNode = loadClassNode(clsIn, skipDebugInfo = false)
val method = getMethod(clsNode, "m")
val instructions = instructionsFromMethod(method).filter(_.isInstanceOf[LineNumber])
val expected = List(LineNumber(3, Label(0)))
assertSameCode(instructions, expected)

}
}
}

object invocationReceiversTestCode {
Expand Down