Skip to content

Commit 3832214

Browse files
committed
Disallow invocations of deferred inline methods
1 parent c43448e commit 3832214

File tree

3 files changed

+32
-5
lines changed

3 files changed

+32
-5
lines changed

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

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,14 +125,26 @@ object Inliner {
125125
}
126126

127127
/** For a retained inline method: The inline expansion of the call to itself with its
128-
* parameters as arguments.
128+
* parameters as arguments. Given an inline method
129+
*
130+
* inline def f[Ts](xs: Us) = body
131+
*
132+
* This sets up the call
133+
*
134+
* f[Ts'](xs')
135+
*
136+
* where the 'ed parameters are copies of the original ones. The call is
137+
* then inline processed in a context which has a clone f' of f as owner.
138+
* The cloning of owner and parameters is necessary since otherwise the
139+
* inliner gets confused in various ways. The inlined body is then
140+
* transformed back by replacing cloned versions of parameters with original
141+
* and replacing the cloned owner f' with f.
129142
*/
130143
def inlineSelfCall(mdef: DefDef)(using ctx: Context): Tree =
131144
val meth = mdef.symbol
132145
val origParams: List[Symbol] = mdef.tparams.map(_.symbol) ::: mdef.vparamss.flatten.map(_.symbol)
133146
val callParams: List[Symbol] = origParams.map(_.copy())
134147
val callOwner = meth.copy(flags = meth.flags &~ Inline)
135-
assert(ctx.owner != meth)
136148
inlineCall(
137149
ref(meth)
138150
.appliedToTypes(mdef.tparams.tpes)

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

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2939,9 +2939,13 @@ class Typer extends Namer
29392939
!suppressInline) {
29402940
tree.tpe <:< wildApprox(pt)
29412941
val errorCount = ctx.reporter.errorCount
2942-
val inlined = Inliner.inlineCall(tree)
2943-
if ((inlined ne tree) && errorCount == ctx.reporter.errorCount) readaptSimplified(inlined)
2944-
else inlined
2942+
val meth = methPart(tree).symbol
2943+
if meth.is(Deferred) then
2944+
errorTree(tree, i"Deferred inline ${meth.showLocated} cannot be invoked")
2945+
else
2946+
val inlined = Inliner.inlineCall(tree)
2947+
if ((inlined ne tree) && errorCount == ctx.reporter.errorCount) readaptSimplified(inlined)
2948+
else inlined
29452949
}
29462950
else if (tree.symbol.isScala2Macro &&
29472951
// raw and s are eliminated by the StringInterpolatorOpt phase

tests/neg/inline-abstract.scala

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
class A:
2+
inline def f(): Int
3+
4+
class B extends A:
5+
inline def f() = 1
6+
7+
def Test =
8+
val b = B()
9+
println(b.f()) // ok
10+
val a: A = b
11+
println(a.f()) // error: Deferred inline method f in class A cannot be invoked

0 commit comments

Comments
 (0)