Skip to content

Commit 28a8554

Browse files
committed
Remove unused params in erasure
With path dependent types on parameters it is not possible to remove them before erasure because there is no type that can be put in their place without messing with typing (Ychecks will fail).
1 parent 44a8fe6 commit 28a8554

File tree

8 files changed

+34
-173
lines changed

8 files changed

+34
-173
lines changed

compiler/src/dotty/tools/dotc/Compiler.scala

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,15 +65,14 @@ class Compiler {
6565
new LiftTry, // Put try expressions that might execute on non-empty stacks into their own methods
6666
new HoistSuperArgs, // Hoist complex arguments of supercalls to enclosing scope
6767
new ClassOf), // Expand `Predef.classOf` calls.
68-
List(new UnusedParams), // Removes all unused parameters and arguments
6968
List(new TryCatchPatterns, // Compile cases in try/catch
7069
new PatternMatcher, // Compile pattern matches
7170
new ExplicitOuter, // Add accessors to outer classes from nested ones.
7271
new ExplicitSelf, // Make references to non-trivial self types explicit as casts
7372
new ShortcutImplicits, // Allow implicit functions without creating closures
7473
new CrossCastAnd, // Normalize selections involving intersection types.
7574
new Splitter), // Expand selections involving union types into conditionals
76-
List(new UnusedDecls, // Removes all unused defs and vals decls
75+
List(new UnusedDecls, // Removes all unused defs and vals decls (except for parameters)
7776
new VCInlineMethods, // Inlines calls to value class methods
7877
new SeqLiterals, // Express vararg arguments as arrays
7978
new InterceptedMethods, // Special handling of `==`, `|=`, `getClass` methods

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -400,7 +400,8 @@ class TypeErasure(isJava: Boolean, semiEraseVCs: Boolean, isConstructor: Boolean
400400
def paramErasure(tpToErase: Type) =
401401
erasureFn(tp.isJavaMethod, semiEraseVCs, isConstructor, wildcardOK)(tpToErase)
402402
val (names, formals0) =
403-
if (tp.paramInfos.exists(_.isPhantom)) tp.paramNames.zip(tp.paramInfos).filterNot(_._2.isPhantom).unzip
403+
if (tp.isUnusedMethod) (Nil, Nil)
404+
else if (tp.paramInfos.exists(_.isPhantom)) tp.paramNames.zip(tp.paramInfos).filterNot(_._2.isPhantom).unzip
404405
else (tp.paramNames, tp.paramInfos)
405406
val formals = formals0.mapConserve(paramErasure)
406407
eraseResult(tp.resultType) match {

compiler/src/dotty/tools/dotc/transform/Erasure.scala

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -456,6 +456,15 @@ object Erasure {
456456
case _ => Nil
457457
}
458458

459+
// TODO: merge this whit protoArgs if it is actually needed
460+
private def protoArgs2(pt: Type, tp: Type): List[untpd.Tree] = (pt, tp) match {
461+
case (pt: FunProto, tp: MethodType) if tp.isUnusedMethod => protoArgs2(pt.resType, tp.resType)
462+
case (pt: FunProto, tp: MethodType) => pt.args ++ protoArgs2(pt.resType, tp.resType)
463+
case _ =>
464+
assert(!tp.isInstanceOf[MethodOrPoly], tp)
465+
Nil
466+
}
467+
459468
override def typedTypeApply(tree: untpd.TypeApply, pt: Type)(implicit ctx: Context) = {
460469
val ntree = interceptTypeApply(tree.asInstanceOf[TypeApply])(ctx.withPhase(ctx.erasurePhase))
461470

@@ -486,7 +495,10 @@ object Erasure {
486495
fun1.tpe.widen match {
487496
case mt: MethodType =>
488497
val outers = outer.args(fun.asInstanceOf[tpd.Tree]) // can't use fun1 here because its type is already erased
489-
var args0 = outers ::: args ++ protoArgs(pt)
498+
var args0 = protoArgs2(pt, tree.typeOpt)
499+
if (!mt.isUnusedMethod) args0 = args ::: args0
500+
args0 = outers ::: args0
501+
490502
if (args0.length > MaxImplementedFunctionArity && mt.paramInfos.length == 1) {
491503
val bunchedArgs = untpd.JavaSeqLiteral(args0, TypeTree(defn.ObjectType))
492504
.withType(defn.ArrayOf(defn.ObjectType))
@@ -554,6 +566,7 @@ object Erasure {
554566
vparamss1 = (tpd.ValDef(bunchedParam) :: Nil) :: Nil
555567
rhs1 = untpd.Block(paramDefs, rhs1)
556568
}
569+
vparamss1 = vparamss1.mapConserve(_.filterConserve(!_.symbol.is(Flags.Unused)))
557570
vparamss1 = vparamss1.mapConserve(_.filterConserve(vparam => !wasPhantom(vparam.tpe)))
558571
if (sym.is(Flags.ParamAccessor) && wasPhantom(ddef.tpt.tpe)) {
559572
sym.resetFlag(Flags.ParamAccessor)

compiler/src/dotty/tools/dotc/transform/UnusedDecls.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ class UnusedDecls extends MiniPhaseTransform with InfoTransformer {
2424

2525
/** Check what the phase achieves, to be called at any point after it is finished. */
2626
override def checkPostCondition(tree: Tree)(implicit ctx: Context): Unit = tree match {
27-
case tree: ValOrDefDef => assert(!tree.symbol.is(Unused))
27+
case tree: ValOrDefDef if !tree.symbol.is(Param) => assert(!tree.symbol.is(Unused, butNot = Param))
2828
case _ =>
2929
}
3030

@@ -35,7 +35,7 @@ class UnusedDecls extends MiniPhaseTransform with InfoTransformer {
3535
override def transformValDef(tree: ValDef)(implicit ctx: Context, info: TransformerInfo): Tree = transformValOrDefDef(tree)
3636

3737
private def transformValOrDefDef(tree: ValOrDefDef)(implicit ctx: Context): Tree =
38-
if (tree.symbol is Unused) EmptyTree else tree
38+
if (tree.symbol.is(Unused, butNot = Param)) EmptyTree else tree
3939

4040

4141
/* Info transform */

compiler/src/dotty/tools/dotc/transform/UnusedParams.scala

Lines changed: 0 additions & 122 deletions
This file was deleted.

compiler/src/dotty/tools/dotc/transform/UnusedRefs.scala

Lines changed: 4 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import dotty.tools.dotc.transform.TreeTransforms.{MiniPhaseTransform, Transforme
1919
* then `x` --> `(default value for T)`
2020
* `x.Y` --> `T#Y`
2121
*/
22-
class UnusedRefs extends MiniPhaseTransform with InfoTransformer {
22+
class UnusedRefs extends MiniPhaseTransform {
2323
import tpd._
2424

2525
override def phaseName: String = "unusedRefs"
@@ -29,22 +29,9 @@ class UnusedRefs extends MiniPhaseTransform with InfoTransformer {
2929
)
3030

3131
/** Check what the phase achieves, to be called at any point after it is finished. */
32-
override def checkPostCondition(tree: Tree)(implicit ctx: Context): Unit = {
33-
val checker = new TypeMap {
34-
override def apply(tp: Type): Type = tp match {
35-
case tp: TermParamRef => assert(!tp.binder.isUnusedMethod); tp
36-
case tp: TermRef if !tp.symbol.is(Method) => assert(!tp.symbol.is(Unused)); tp
37-
case _ => mapOver(tp)
38-
}
39-
}
40-
tree match {
41-
case _: ValDef =>
42-
case _: Apply | _: RefTree =>
43-
assert(!tree.symbol.is(Unused))
44-
checker.apply(tree.tpe)
45-
case _ =>
46-
checker.apply(tree.tpe)
47-
}
32+
override def checkPostCondition(tree: Tree)(implicit ctx: Context): Unit = tree match {
33+
case _: Apply | _: RefTree => assert(!tree.symbol.is(Unused))
34+
case _ =>
4835
}
4936

5037
/* Tree transform */
@@ -70,26 +57,4 @@ class UnusedRefs extends MiniPhaseTransform with InfoTransformer {
7057
}
7158
}
7259
}
73-
74-
override def transformTypeTree(tree: TypeTree)(implicit ctx: Context, info: TransformerInfo): Tree = {
75-
val newType = removeUnusedPaths(tree.tpe)
76-
if (tree.tpe == newType) tree
77-
else TypeTree(newType)
78-
}
79-
80-
81-
/* Tree info */
82-
83-
override def transformInfo(tp: Type, sym: Symbol)(implicit ctx: Context): Type = removeUnusedPaths(tp)
84-
85-
private def removeUnusedPaths(tp: Type)(implicit ctx: Context): Type = {
86-
// TODO: handle variance
87-
new TypeMap {
88-
override def apply(tp: Type): Type = tp match {
89-
case tp: TermParamRef if tp.binder.isUnusedMethod => tp.classSymbol.typeRef
90-
case tp: TermRef if tp.symbol.is(Unused) => tp.widen
91-
case _ => mapOver(tp)
92-
}
93-
}.apply(tp)
94-
}
9560
}

tests/run/unused-3.check

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
foo
2-
foo
1+
foo1
2+
foo2
33
fun

tests/run/unused-3.scala

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,20 @@
11
object Test {
22

33
def main(args: Array[String]): Unit = {
4-
fun(foo)(foo)
4+
fun(foo1)(foo2)
55
}
66

7-
def foo: Int = {
8-
println("foo")
7+
def foo1: Int = {
8+
println("foo1")
99
42
1010
}
1111

12-
def fun(unused a: Int)(unused b: Int): Unit = {
12+
def foo2: String = {
13+
println("foo2")
14+
"abc"
15+
}
16+
17+
def fun(unused a: Int)(unused b: String): Unit = {
1318
println("fun")
1419
}
1520

0 commit comments

Comments
 (0)