Skip to content

Commit 67d0a2f

Browse files
committed
More polishings and tests
1 parent 479b784 commit 67d0a2f

File tree

7 files changed

+84
-32
lines changed

7 files changed

+84
-32
lines changed

compiler/src/dotty/tools/dotc/ast/TreeInfo.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -551,6 +551,7 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
551551
/** An extractor for def of a closure contained the block of the closure. */
552552
object closureDef {
553553
def unapply(tree: Tree): Option[DefDef] = tree match {
554+
case Block(Nil, expr) => unapply(expr)
554555
case Block((meth @ DefDef(nme.ANON_FUN, _, _, _, _)) :: Nil, closure: Closure) =>
555556
Some(meth)
556557
case _ => None

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

Lines changed: 17 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -53,23 +53,13 @@ object Inliner {
5353
// This is quite tricky, as such types can appear anywhere, including as parts
5454
// of types of other things. For the moment we do nothing and complain
5555
// at the implicit expansion site if there's a reference to an inaccessible type.
56-
override def transform(tree: Tree)(implicit ctx: Context): Tree = tree match {
57-
case tree: Assign =>
58-
transform(tree.lhs) match {
59-
case lhs1: RefTree =>
60-
lhs1.name match {
61-
case InlineAccessorName(name) =>
62-
cpy.Apply(tree)(useSetter(lhs1), transform(tree.rhs) :: Nil)
63-
case _ =>
64-
super.transform(tree)
65-
}
66-
case _ =>
67-
super.transform(tree)
68-
}
69-
case _ =>
70-
super.transform(accessorIfNeeded(tree))
71-
}
72-
56+
override def transform(tree: Tree)(implicit ctx: Context): Tree =
57+
super.transform(accessorIfNeeded(tree)) match {
58+
case tree1 @ Assign(lhs: RefTree, rhs) if lhs.symbol.name.is(InlineAccessorName) =>
59+
cpy.Apply(tree1)(useSetter(lhs), rhs :: Nil)
60+
case tree1 =>
61+
tree1
62+
}
7363
}
7464

7565
/** Adds accessors for all non-public term members accessed
@@ -104,14 +94,14 @@ object Inliner {
10494
* to have the inlined method as owner.
10595
*/
10696
def registerInlineInfo(
107-
sym: SymDenotation, treeExpr: Context => Tree)(implicit ctx: Context): Unit = {
108-
sym.unforcedAnnotation(defn.BodyAnnot) match {
97+
inlined: Symbol, treeExpr: Context => Tree)(implicit ctx: Context): Unit = {
98+
inlined.unforcedAnnotation(defn.BodyAnnot) match {
10999
case Some(ann: ConcreteBodyAnnotation) =>
110100
case Some(ann: LazyBodyAnnotation) if ann.isEvaluated =>
111101
case _ =>
112102
if (!ctx.isAfterTyper) {
113103
val inlineCtx = ctx
114-
sym.updateAnnotation(LazyBodyAnnotation { _ =>
104+
inlined.updateAnnotation(LazyBodyAnnotation { _ =>
115105
implicit val ctx = inlineCtx
116106
val body = treeExpr(ctx)
117107
if (ctx.reporter.hasErrors) body else ctx.compilationUnit.inlineAccessors.makeInlineable(body)
@@ -173,10 +163,10 @@ object Inliner {
173163

174164
/** Produces an inlined version of `call` via its `inlined` method.
175165
*
176-
* @param call The original call to a `@inline` method
177-
* @param rhs The body of the inline method that replaces the call.
166+
* @param call the original call to a `@inline` method
167+
* @param rhsToInline the body of the inline method that replaces the call.
178168
*/
179-
class Inliner(call: tpd.Tree, rhs: tpd.Tree)(implicit ctx: Context) {
169+
class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
180170
import tpd._
181171
import Inliner._
182172

@@ -200,7 +190,7 @@ class Inliner(call: tpd.Tree, rhs: tpd.Tree)(implicit ctx: Context) {
200190
*/
201191
private val paramProxy = new mutable.HashMap[Type, Type]
202192

203-
/** A map from the classes of (direct and outer) this references in `rhs`
193+
/** A map from the classes of (direct and outer) this references in `rhsToInline`
204194
* to references of their proxies.
205195
* Note that we can't index by the ThisType itself since there are several
206196
* possible forms to express what is logicaly the same ThisType. E.g.
@@ -315,7 +305,7 @@ class Inliner(call: tpd.Tree, rhs: tpd.Tree)(implicit ctx: Context) {
315305
if (!isIdempotentExpr(prefix)) registerType(meth.owner.thisType)
316306

317307
// Register types of all leaves of inlined body so that the `paramProxy` and `thisProxy` maps are defined.
318-
rhs.foreachSubTree(registerLeaf)
308+
rhsToInline.foreachSubTree(registerLeaf)
319309

320310
// The class that the this-proxy `selfSym` represents
321311
def classOf(selfSym: Symbol) = selfSym.info.widen.classSymbol
@@ -387,7 +377,7 @@ class Inliner(call: tpd.Tree, rhs: tpd.Tree)(implicit ctx: Context) {
387377
// the owner from the inlined method to the current owner.
388378
val inliner = new TreeTypeMap(typeMap, treeMap, meth :: Nil, ctx.owner :: Nil)(inlineCtx)
389379

390-
val expansion = inliner(rhs.withPos(call.pos))
380+
val expansion = inliner(rhsToInline.withPos(call.pos))
391381
trace(i"inlining $call\n, BINDINGS =\n${bindingsBuf.toList}%\n%\nEXPANSION =\n$expansion", inlining, show = true) {
392382

393383
// The final expansion runs a typing pass over the inlined tree. See InlineTyper for details.
@@ -426,7 +416,7 @@ class Inliner(call: tpd.Tree, rhs: tpd.Tree)(implicit ctx: Context) {
426416
/** A typer for inlined code. Its purpose is:
427417
* 1. Implement constant folding over inlined code
428418
* 2. Selectively expand ifs with constant conditions
429-
* 3. Inline arguments that are inlineable closures
419+
* 3. Inline arguments that are by-name closures
430420
* 4. Make sure inlined code is type-correct.
431421
* 5. Make sure that the tree's typing is idempotent (so that future -Ycheck passes succeed)
432422
*/

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

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -821,12 +821,12 @@ class Namer { typer: Typer =>
821821
else completeInCreationContext(denot)
822822
}
823823

824-
private def addInlineInfo(denot: SymDenotation) = original match {
825-
case original: untpd.DefDef if denot.isInlineableMethod =>
824+
private def addInlineInfo(sym: Symbol) = original match {
825+
case original: untpd.DefDef if sym.isInlineableMethod =>
826826
Inliner.registerInlineInfo(
827-
denot,
827+
sym,
828828
implicit ctx => typedAheadExpr(original).asInstanceOf[tpd.DefDef].rhs
829-
)(localContext(denot.symbol))
829+
)(localContext(sym))
830830
case _ =>
831831
}
832832

@@ -839,7 +839,7 @@ class Namer { typer: Typer =>
839839
case original: MemberDef => addAnnotations(sym, original)
840840
case _ =>
841841
}
842-
addInlineInfo(denot)
842+
addInlineInfo(sym)
843843
denot.info = typeSig(sym)
844844
Checking.checkWellFormed(sym)
845845
denot.info = avoidPrivateLeaks(sym, sym.pos)

tests/run/inline-implicits.check

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
(X(),Y())

tests/run/inline-implicits.scala

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
case class X()
2+
case class Y()
3+
4+
object impl {
5+
implicit val y: Y = new Y()
6+
}
7+
8+
object inlines {
9+
import impl._
10+
11+
class C {
12+
implicit val x: X = new X()
13+
14+
inline
15+
def f(): (X, Y) =
16+
(implicitly[X], implicitly[Y])
17+
}
18+
}
19+
20+
object Test {
21+
def main(args: Array[String]) = {
22+
val c = new inlines.C
23+
val xy = c.f()
24+
println(xy)
25+
}
26+
}

tests/run/typelevel.check

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
ToNat(Z)
2+
ToNat(S(Z))
3+
ToNat(S(S(Z)))

tests/run/typelevel.scala

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
object Test extends App {
2+
3+
trait Nat
4+
5+
case object Z extends Nat
6+
type Z = Z.type
7+
case class S[N <: Nat](n: Nat) extends Nat
8+
9+
abstract class HasResult[T] { type Result = T }
10+
case class ToNat[+T](val value: T) extends HasResult[T]
11+
12+
transparent def ToNat(inline n: Int): ToNat[Nat] =
13+
if n == 0 then new ToNat(Z)
14+
else {
15+
val n1 = ToNat(n - 1)
16+
new ToNat[S[n1.Result]](S(n1.value))
17+
}
18+
19+
val x0 = ToNat(0)
20+
//val y0: Z = x0.value
21+
//val z0: x0.Result = y0
22+
val x1 = ToNat(1)
23+
//val y1: S[Z] = x1.value
24+
//val z1: x1.Result = y1
25+
val x2 = ToNat(2)
26+
//val y2: S[S[Z]] = x2.value
27+
//val z2: x2.Result = y2
28+
println(x0)
29+
println(x1)
30+
println(x2)
31+
}

0 commit comments

Comments
 (0)