Skip to content

Commit

Permalink
Inline transparent implicit parameters when typing Unapply trees
Browse files Browse the repository at this point in the history
We needed to delay the inlining of the transparent inline when typing
the unapply function application. We used the NoInline mode, but this
also stopped the inlining of the arguments of the unapply. To fix this
we introduce a new mode, NoInlineUnapply, which is used to delay only
the inlining of the unapply method and not the implicit arguments.

Fixes #19623
  • Loading branch information
nicolasstucki committed Feb 8, 2024
1 parent 551eae4 commit 5ff35a9
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 1 deletion.
3 changes: 3 additions & 0 deletions compiler/src/dotty/tools/dotc/core/Mode.scala
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,9 @@ object Mode {

val PatternOrTypeBits: Mode = Pattern | Type

/** Skip inlining of unapply methods. */
val NoInlineUnapply: Mode = newMode(18, "NoInlineUnapply")

/** We are elaborating the fully qualified name of a package clause.
* In this case, identifiers should never be imported.
*/
Expand Down
2 changes: 2 additions & 0 deletions compiler/src/dotty/tools/dotc/inlines/Inlines.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package inlines
import ast.*, core.*
import Flags.*, Symbols.*, Types.*, Decorators.*, Constants.*, Contexts.*
import StdNames.{tpnme, nme}
import NameOps.*
import typer.*
import NameKinds.BodyRetainerName
import SymDenotations.SymDenotation
Expand Down Expand Up @@ -64,6 +65,7 @@ object Inlines:
&& !ctx.typer.hasInliningErrors
&& !ctx.base.stopInlining
&& !ctx.mode.is(Mode.NoInline)
&& !(ctx.mode.is(Mode.NoInlineUnapply) && tree.symbol.name.isUnapplyName)
}

private def needsTransparentInlining(tree: Tree)(using Context): Boolean =
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/typer/Applications.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1492,7 +1492,7 @@ trait Applications extends Compatibility {

val dummyArg = dummyTreeOfType(ownType)
val (newUnapplyFn, unapplyApp) =
val unapplyAppCall = withMode(Mode.NoInline):
val unapplyAppCall = withMode(Mode.NoInlineUnapply):
typedExpr(untpd.TypedSplice(Apply(unapplyFn, dummyArg :: Nil)))
inlinedUnapplyFnAndApp(dummyArg, unapplyAppCall)

Expand Down
40 changes: 40 additions & 0 deletions tests/pos/i19623.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import scala.compiletime.*
import scala.language.dynamics

abstract class % extends Selectable

trait Select { type Out <: % }
trait Selector extends Dynamic {
def selectDynamic[S <: Singleton & String](label: S): Any = ???

def unapply[R: RecordLike](record: R)(using
t: Select,
r: RecordLike[t.Out]
): r.ElemTypes = ???
}

trait RecordLike[R] {
type ElemTypes <: Tuple
}


@main def Test = {
val r: %{ val name: String; } = ???

// originally derived in macro, use dummy instance instead
transparent inline given outputRecordLike[R <: %]: RecordLike[R] = null.asInstanceOf[
RecordLike[R] {
type ElemTypes = String *: EmptyTuple
}
]

type FieldSelector = Select { type Out = % { val name: String } }
given fieldSelector: FieldSelector = ???
val selector: Selector = ???

val works = selector.unapply(r)
val works2 = selector.unapply(r)(using summon, fieldSelector, summon)
r match {
case selector(value) => value // compilation error
}
}

0 comments on commit 5ff35a9

Please sign in to comment.