Skip to content
Draft
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
16 changes: 15 additions & 1 deletion compiler/src/dotty/tools/dotc/inlines/Inlines.scala
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,23 @@ object Inlines:
case _ => false
tree.symbol.name.isUnapplyName && rec(tree)

isInlineable(tree.symbol)
val sym = tree.symbol
sym.is(Inline) && sym.hasAnnotation(defn.BodyAnnot)
&& !tree.tpe.widenTermRefExpr.isInstanceOf[MethodOrPoly]
&& StagingLevel.level == 0
&& (
// Outside of inline method bodies, any inline call may be inlined.
!inInlineMethod
// Inside inline method bodies, a transparent inline given must still be
// expanded at typer so that dependent type members of its result
// (e.g. `tc.Out` from `fromVal[Int, Int]`) are known when typing the
// enclosing body; otherwise the implicit-argument reference is
// non-stable and gets skolemized, making `tc.Out` opaque. See #15798.
// Macro-based givens are excluded: eager expansion of their bodies
// would run a macro at the def site with abstract types, typically
// causing cyclic-macro-dependency errors (see tests/neg-macros/i18695).
|| (sym.is(Given) && !sym.is(Macro) && needsTransparentInlining(tree))
)
&& (
ctx.phase == Phases.inliningPhase
|| (ctx.phase == Phases.typerPhase && needsTransparentInlining(tree))
Expand Down
25 changes: 25 additions & 0 deletions tests/pos/i15798.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import compiletime.ops.*

class Inlined[T](val value : T)
object Inlined:
trait TC[UB, R]:
type Out <: UB
def apply(arg: R): Inlined[Out]
object TC:
transparent inline given fromVal[UB, R <: UB]: TC[UB, R] = new TC[UB, R]:
type Out = R
def apply(arg: R): Inlined[R] = forced[R](arg)
transparent inline given fromInline[UB, R <: UB, I <: Inlined[R]]: TC[UB, I] =
new TC[UB, I]:
type Out = R
def apply(arg: I): Inlined[R] = arg

protected inline def forced[T](_value: Any): Inlined[T] = Inlined[T](_value.asInstanceOf[T])

def add[T <: Int, R](lhs: Inlined[T], rhs: R)(using tc: TC[Int, R]) =
forced[int.+[T, tc.Out]](lhs.value + tc(rhs).value)
def get[T <: Int](inlined: Inlined[T]) : T = inlined.value

object Test:
inline def check[UB <: Int](ub: Inlined[UB]): Unit =
val y = Inlined.get(Inlined.add(ub, 1))
Loading