-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Erase arguments of phantom type #2399
Erase arguments of phantom type #2399
Conversation
bacfeba
to
de3a1c8
Compare
d273d89
to
2a25799
Compare
2a25799
to
e8fb429
Compare
* | ||
* - Parameters/arguments are erased to ErasedPhantom. The next step will remove the parameters | ||
* from the method definitions and calls (implemented in branch implement-phantom-types-part-2). | ||
* - Parameters/arguments are erased removed from the function definition/call in `PhantomArgumentEval`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo: erased removed
@@ -400,12 +400,15 @@ class TypeErasure(isJava: Boolean, semiEraseVCs: Boolean, isConstructor: Boolean | |||
case tp: MethodType => | |||
def paramErasure(tpToErase: Type) = | |||
erasureFn(tp.isJava, semiEraseVCs, isConstructor, wildcardOK)(tpToErase) | |||
val formals = tp.paramInfos.mapConserve(paramErasure) | |||
val (names, formals0) = | |||
if (tp.paramInfos.forall(!_.isPhantom)) (tp.paramNames, tp.paramInfos) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
!tp.paramInfos.exists(_.isPhantom)
val formals = tp.paramInfos.mapConserve(paramErasure) | ||
val (names, formals0) = | ||
if (tp.paramInfos.forall(!_.isPhantom)) (tp.paramNames, tp.paramInfos) | ||
else tp.paramNames.iterator.zip(tp.paramInfos.iterator).filterNot(_._2.isPhantom).toList.unzip |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can probably drop .iterator
.
@@ -474,7 +477,7 @@ object Erasure extends TypeTestsCasts{ | |||
.withType(defn.ArrayOf(defn.ObjectType)) | |||
args0 = bunchedArgs :: Nil | |||
} | |||
val args1 = args0.zipWithConserve(mt.paramInfos)(typedExpr) | |||
val args1 = args0.filterConserve(arg => !wasPhantom(arg.typeOpt)).zipWithConserve(mt.paramInfos)(typedExpr) | |||
untpd.cpy.Apply(tree)(fun1, args1) withType mt.resultType |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a comment why we know that argument.isPhantom if and only if parameter.isPhantomj
} | ||
|
||
/** Collects all args (and possibly the function) as synthetic vals and replaces them in the tree by the reference to | ||
* the lifted its val. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo?
/* Tree transform */ | ||
|
||
override def transformApply(tree: Apply)(implicit ctx: Context, info: TransformerInfo): Tree = tree.tpe match { | ||
case _: MethodType => tree // Do the transformation higher in the tree if needed |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tree.tpe.widen
private def transformApplication(tree: Tree, mkTree: (Tree, List[ValDef]) => Tree)(implicit ctx: Context): Tree = tree match { | ||
case tree: Apply => | ||
def mkNewApply(newFun: Tree, accSynthVals: List[ValDef]) = { | ||
val (synthVals, synthValRefs) = tree.args.map(mkSynthVal).unzip |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
insert: .filterNot(tpd.isPureExpr)
case _ => | ||
def mkNewBlock(newApply: Tree, synthVals: List[ValDef]) = Block(synthVals, newApply) | ||
if (!hasPhantomArgs(tree)) tree | ||
else transformApplication(tree, mkNewBlock) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Change logic to:
- If function has impure phantom args, lift out all args using
EtaExpansion.liftApp
.
3802539
to
0975c68
Compare
All requested changes have been taken care of. |
This commit removes arguments and parameter of phantom type from all applications. Arguments are evaluated before the application in case they have side effects. ``` def foo(i: Int, p: SomePhantom) = ??? foo(42, { println("hello"); getSomePhantom }) ``` becomes ``` def foo(i: Int) = ??? val x$0 = 42 val x$1 = { println("hello"); getSomePhantom } foo(x$0) ``` Note that now `def foo(i: Int)` and def `foo(i: Int, p: SomePhantom)` erase to the same signature. Tests for this commit where added in `Extra tests for Phantoms 1`, they where back ported as the semantics and runtime is not affected.
Phantom `var`s where disallowed.
0975c68
to
975cee5
Compare
Rebased |
This commit removes arguments and parameter of phantom type from all applications.
Arguments are evaluated before the application in case they have side effects.
becomes
Note that now
def foo(i: Int)
and deffoo(i: Int, p: SomePhantom)
erase to the same signature.Tests for this commit where added in
Extra tests for Phantoms 1
, they where back ported as the semantics and runtime is not affected.