Skip to content

Commit 84fe952

Browse files
committed
Allow inline unapply
Unapply methods can have `inline` flags. This enables reduceProjection to see the methods right hand side. On the other hand, since `unapply` methods are not applied hen used in patterns we do not classify them as inline methods. Consequently they cannot contain inline matches or inline ifs.
1 parent 72c71b0 commit 84fe952

File tree

3 files changed

+12
-11
lines changed

3 files changed

+12
-11
lines changed

compiler/src/dotty/tools/dotc/core/SymDenotations.scala

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -773,7 +773,10 @@ object SymDenotations {
773773
def isSkolem: Boolean = name == nme.SKOLEM
774774

775775
def isInlineMethod(implicit ctx: Context): Boolean =
776-
is(InlineMethod, butNot = AccessorOrSynthetic)
776+
is(InlineMethod, butNot = AccessorOrSynthetic) &&
777+
name != nme.unapply // unapply methods do not count as inline methods
778+
// we need an inline flag on them only do that
779+
// reduceProjection gets access to their rhs
777780

778781
/** An erased value or an inline method, excluding @forceInline annotated methods.
779782
* The latter have to be kept around to get to parity with Scala.

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

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -981,14 +981,6 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
981981
else trySelectUnapply(qual1)(_ => notAnExtractor(sel))
982982
}
983983

984-
/* Can probably be dropped. The idea is that inline unapply methods are available
985-
* for inspection in the Inliner's reduceMatch method, but are never inlined
986-
* when called from normal code.
987-
988-
if (unapplyFn.symbol.isInlineMethod)
989-
checkInInlineContext("implementation restriction: call to inline unapply", tree.pos)
990-
*/
991-
992984
/** Add a `Bind` node for each `bound` symbol in a type application `unapp` */
993985
def addBinders(unapp: Tree, bound: List[Symbol]) = unapp match {
994986
case TypeApply(fn, args) =>

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

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -890,8 +890,14 @@ trait Checking {
890890

891891
/** Check that we are in an inline context (inside an inline method or in inline code) */
892892
def checkInInlineContext(what: String, pos: Position)(implicit ctx: Context): Unit =
893-
if (!ctx.inInlineMethod && !ctx.isInlineContext)
894-
ctx.error(em"$what can only be used in an inline method", pos)
893+
if (!ctx.inInlineMethod && !ctx.isInlineContext) {
894+
val inInlineUnapply = ctx.owner.ownersIterator.exists(owner =>
895+
owner.name == nme.unapply && owner.is(Inline) && owner.is(Method))
896+
val msg =
897+
if (inInlineUnapply) "cannot be used in an inline unapply"
898+
else "can only be used in an inline method"
899+
ctx.error(em"$what $msg", pos)
900+
}
895901

896902
/** Check that all case classes that extend `scala.Enum` are `enum` cases */
897903
def checkEnum(cdef: untpd.TypeDef, cls: Symbol, parent: Symbol)(implicit ctx: Context): Unit = {

0 commit comments

Comments
 (0)