Skip to content

Commit 72b247b

Browse files
committed
Fix #3971: Relax checkInlineConformant for final vals
Necessary for -Ycheck:frontend to work
1 parent a768e39 commit 72b247b

File tree

4 files changed

+18
-11
lines changed

4 files changed

+18
-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: 9 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,20 @@ 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 _ =>
612615
if (!ctx.erasedTypes) ctx.error(em"$what must be a constant expression or a function", tree.pos)
613616
}
614617
}
618+
}
615619

616620
/** Check that class does not declare same symbol twice */
617621
def checkNoDoubleDeclaration(cls: Symbol)(implicit ctx: Context): Unit = {
@@ -867,7 +871,7 @@ trait NoChecking extends ReChecking {
867871
override def checkClassType(tp: Type, pos: Position, traitReq: Boolean, stablePrefixReq: Boolean)(implicit ctx: Context): Type = tp
868872
override def checkImplicitParamsNotSingletons(vparamss: List[List[ValDef]])(implicit ctx: Context): Unit = ()
869873
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) = ()
874+
override def checkInlineConformant(tree: Tree, isFinal: Boolean, what: => String)(implicit ctx: Context) = ()
871875
override def checkNoDoubleDeclaration(cls: Symbol)(implicit ctx: Context): Unit = ()
872876
override def checkParentCall(call: Tree, caller: ClassSymbol)(implicit ctx: Context) = ()
873877
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
@@ -1371,7 +1371,7 @@ class Typer extends Namer
13711371
}
13721372
val vdef1 = assignType(cpy.ValDef(vdef)(name, tpt1, rhs1), sym)
13731373
if (sym.is(Inline, butNot = DeferredOrTermParamOrAccessor))
1374-
checkInlineConformant(rhs1, em"right-hand side of inline $sym")
1374+
checkInlineConformant(rhs1, isFinal = sym.is(Final), em"right-hand side of inline $sym")
13751375
patchIfLazy(vdef1)
13761376
patchFinalVals(vdef1)
13771377
vdef1
@@ -1392,7 +1392,7 @@ class Typer extends Namer
13921392
* and instead return the value. This seemingly minor optimization has huge effect on initialization
13931393
* order and the values that can be observed during superconstructor call
13941394
*
1395-
* see remark about idempotency in PostTyper#normalizeTree
1395+
* see remark about idempotency in TreeInfo#constToLiteral
13961396
*/
13971397
private def patchFinalVals(vdef: ValDef)(implicit ctx: Context): Unit = {
13981398
def isFinalInlinableVal(sym: Symbol): Boolean = {
@@ -2329,7 +2329,7 @@ class Typer extends Namer
23292329
}
23302330
else if (tree.tpe <:< pt) {
23312331
if (pt.hasAnnotation(defn.InlineParamAnnot))
2332-
checkInlineConformant(tree, "argument to inline parameter")
2332+
checkInlineConformant(tree, isFinal = false, "argument to inline parameter")
23332333
if (Inliner.hasBodyToInline(tree.symbol) &&
23342334
!ctx.owner.ownersIterator.exists(_.isInlineMethod) &&
23352335
!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)