Skip to content

Commit 0ab5a2c

Browse files
committed
Fix scala#3971: Relax checkInlineConformant for final vals
Necessary for -Ycheck:frontend to work
1 parent 6b68266 commit 0ab5a2c

File tree

4 files changed

+20
-11
lines changed

4 files changed

+20
-11
lines changed

compiler/src/dotty/tools/dotc/ast/TreeInfo.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -317,7 +317,7 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
317317
* Idempotent if running the statement a second time has no side effects
318318
* Impure otherwise
319319
*/
320-
private def statPurity(tree: Tree)(implicit ctx: Context): PurityLevel = unsplice(tree) match {
320+
def statPurity(tree: Tree)(implicit ctx: Context): PurityLevel = unsplice(tree) match {
321321
case EmptyTree
322322
| TypeDef(_, _)
323323
| Import(_, _)
@@ -342,7 +342,7 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
342342
* takes a different code path than all to follow; but they are idempotent
343343
* because running the expression a second time gives the cached result.
344344
*/
345-
private def exprPurity(tree: Tree)(implicit ctx: Context): PurityLevel = unsplice(tree) match {
345+
def exprPurity(tree: Tree)(implicit ctx: Context): PurityLevel = unsplice(tree) match {
346346
case EmptyTree
347347
| This(_)
348348
| Super(_, _)
@@ -397,7 +397,7 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
397397
* @DarkDimius: need to make sure that lazy accessor methods have Lazy and Stable
398398
* flags set.
399399
*/
400-
private def refPurity(tree: Tree)(implicit ctx: Context): PurityLevel =
400+
def refPurity(tree: Tree)(implicit ctx: Context): PurityLevel =
401401
if (!tree.tpe.widen.isParameterless || tree.symbol.is(Erased)) SimplyPure
402402
else if (!tree.symbol.isStable) Impure
403403
else if (tree.symbol.is(Lazy)) Idempotent // TODO add Module flag, sinxce Module vals or not Lazy from the start.

compiler/src/dotty/tools/dotc/typer/Checking.scala

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import StdNames._
1313
import NameOps._
1414
import Symbols._
1515
import Trees._
16+
import TreeInfo._
1617
import ProtoTypes._
1718
import Constants._
1819
import Scopes._
@@ -601,17 +602,22 @@ trait Checking {
601602
}
602603
}
603604

604-
/** Check that `tree` is a pure expression of constant type */
605-
def checkInlineConformant(tree: Tree, what: => String)(implicit ctx: Context): Unit =
605+
/** Check that `tree` can be marked `inline` */
606+
def checkInlineConformant(tree: Tree, isFinal: Boolean, what: => String)(implicit ctx: Context): Unit = {
607+
// final vals can be marked inline even if they're not pure, see Typer#patchFinalVals
608+
val purityLevel = if (isFinal) Idempotent else Pure
606609
tree.tpe match {
607610
case tp: TermRef if tp.symbol.is(InlineParam) => // ok
608611
case tp => tp.widenTermRefExpr match {
609-
case tp: ConstantType if isPureExpr(tree) => // ok
610-
case tp if defn.isFunctionType(tp) && isPureExpr(tree) => // ok
612+
case tp: ConstantType if exprPurity(tree) >= purityLevel => // ok
613+
case tp if defn.isFunctionType(tp) && exprPurity(tree) >= purityLevel => // ok
611614
case _ =>
615+
println("exprP: " + exprPurity(tree))
616+
println("purityLevel: " + purityLevel)
612617
if (!ctx.erasedTypes) ctx.error(em"$what must be a constant expression or a function", tree.pos)
613618
}
614619
}
620+
}
615621

616622
/** Check that class does not declare same symbol twice */
617623
def checkNoDoubleDeclaration(cls: Symbol)(implicit ctx: Context): Unit = {
@@ -867,7 +873,7 @@ trait NoChecking extends ReChecking {
867873
override def checkClassType(tp: Type, pos: Position, traitReq: Boolean, stablePrefixReq: Boolean)(implicit ctx: Context): Type = tp
868874
override def checkImplicitParamsNotSingletons(vparamss: List[List[ValDef]])(implicit ctx: Context): Unit = ()
869875
override def checkFeasibleParent(tp: Type, pos: Position, where: => String = "")(implicit ctx: Context): Type = tp
870-
override def checkInlineConformant(tree: Tree, what: => String)(implicit ctx: Context) = ()
876+
override def checkInlineConformant(tree: Tree, isFinal: Boolean, what: => String)(implicit ctx: Context) = ()
871877
override def checkNoDoubleDeclaration(cls: Symbol)(implicit ctx: Context): Unit = ()
872878
override def checkParentCall(call: Tree, caller: ClassSymbol)(implicit ctx: Context) = ()
873879
override def checkSimpleKinded(tpt: Tree)(implicit ctx: Context): Tree = tpt

compiler/src/dotty/tools/dotc/typer/Typer.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1366,7 +1366,7 @@ class Typer extends Namer
13661366
}
13671367
val vdef1 = assignType(cpy.ValDef(vdef)(name, tpt1, rhs1), sym)
13681368
if (sym.is(Inline, butNot = DeferredOrTermParamOrAccessor))
1369-
checkInlineConformant(rhs1, em"right-hand side of inline $sym")
1369+
checkInlineConformant(rhs1, isFinal = sym.is(Final), em"right-hand side of inline $sym")
13701370
patchIfLazy(vdef1)
13711371
patchFinalVals(vdef1)
13721372
vdef1
@@ -1387,7 +1387,7 @@ class Typer extends Namer
13871387
* and instead return the value. This seemingly minor optimization has huge effect on initialization
13881388
* order and the values that can be observed during superconstructor call
13891389
*
1390-
* see remark about idempotency in PostTyper#normalizeTree
1390+
* see remark about idempotency in TreeInfo#constToLiteral
13911391
*/
13921392
private def patchFinalVals(vdef: ValDef)(implicit ctx: Context): Unit = {
13931393
def isFinalInlinableVal(sym: Symbol): Boolean = {
@@ -2322,7 +2322,7 @@ class Typer extends Namer
23222322
}
23232323
else if (tree.tpe <:< pt) {
23242324
if (pt.hasAnnotation(defn.InlineParamAnnot))
2325-
checkInlineConformant(tree, "argument to inline parameter")
2325+
checkInlineConformant(tree, isFinal = false, "argument to inline parameter")
23262326
if (Inliner.hasBodyToInline(tree.symbol) &&
23272327
!ctx.owner.ownersIterator.exists(_.isInlineMethod) &&
23282328
!ctx.settings.YnoInline.value &&

tests/pos/i3971.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
object BadInlineConstCheck {
2+
final val MaxSize = Int.MaxValue + 0
3+
}

0 commit comments

Comments
 (0)