@@ -300,6 +300,7 @@ object desugar {
300
300
def isAnyVal (tree : Tree ): Boolean = tree match {
301
301
case Ident (tpnme.AnyVal ) => true
302
302
case Select (qual, tpnme.AnyVal ) => isScala(qual)
303
+ case TypedSplice (tree) => tree.tpe.isRef(defn.AnyValClass )
303
304
case _ => false
304
305
}
305
306
def isScala (tree : Tree ): Boolean = tree match {
@@ -770,66 +771,105 @@ object desugar {
770
771
(elimTypeDefs.transform(tree), bindingsBuf.toList)
771
772
}
772
773
773
- /** augment <name> < type-params > <params> extends <parents> { <body>} }
774
+ /** augment <type-pattern > <params> extends <parents> { <body>} }
774
775
* ->
775
- * implicit class <deconame> <type-params> ($this: name <type-args>) <params>
776
- * extends <parents> { <body1> }
777
- *
778
- * augment <type-param> <params> extends <parents> { <body>} }
779
- * ->
780
- * implicit class <deconame> <type-param> ($this: <type-arg>) <params>
776
+ * implicit class <deconame> <type-params> ($this: <decorated>) <combined-params>
781
777
* extends <parents> { <body1> }
782
778
*
783
779
* where
784
780
*
785
- * <deconame> = <name>To<parent>$<n> where <parent> is first extended class name
786
- * = <name>Augmentation$<n> if no such <parent> exists
781
+ * (<decorated>, <type-params0>) = decomposeTypePattern(<type-pattern>)
782
+ * (<type-params>, <evidence-params>) = desugarTypeBindings(<type-params0>)
783
+ * <combined-params> = <params> concatenated with <evidence-params> in one clause
784
+ * <deconame> = <from>To<parent>_in_<location>$$<n> where <parent> is first extended class name
785
+ *
786
+ * = <from>Augmentation_in_<location>$$<n> if no such <parent> exists
787
+ * <from> = underlying type name of <decorated>
788
+ * <location> = flat name of enclosing toplevel class
787
789
* <n> = counter making prefix unique
788
- * <type-args> = references to <type-params>
789
790
* <body1> = <body> with each occurrence of unqualified `this` substituted by `$this`.
791
+ *
792
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
793
+ *
794
+ * augment <type-pattern> <params> { <body> }
795
+ * ->
796
+ * implicit class <deconame> <type-params> ($this: <decorated>)
797
+ * extends AnyVal { <body2> }
798
+ *
799
+ * where
800
+ *
801
+ * <body2> = <body1> where each method definition gets <combined-params> as last parameter section.
802
+ * <deconame>, <type-params> are as above.
790
803
*/
791
804
def augmentation (tree : Augment )(implicit ctx : Context ): Tree = {
792
805
val Augment (augmented, impl) = tree
793
- val constr @ DefDef (_, Nil , vparamss, _, _) = impl.constr
806
+ val isSimpleExtension =
807
+ impl.parents.isEmpty &&
808
+ impl.self.isEmpty &&
809
+ impl.body.forall(_.isInstanceOf [DefDef ])
794
810
val (decorated, bindings) = decomposeTypePattern(augmented)
795
- val firstParam = ValDef (nme.SELF , decorated, EmptyTree ).withFlags(Private | Local | ParamAccessor )
796
- val constr1 =
797
- cpy.DefDef (constr)(
798
- tparams = bindings.map(_.withFlags(Param | Private | Local )),
799
- vparamss = (firstParam :: Nil ) :: vparamss)
800
- val substThis = new UntypedTreeMap {
801
- override def transform (tree : Tree )(implicit ctx : Context ): Tree = tree match {
802
- case This (Ident (tpnme.EMPTY )) => Ident (nme.SELF ).withPos(tree.pos)
803
- case _ => super .transform(tree)
804
- }
805
- }
811
+ val (typeParams, evidenceParams) =
812
+ desugarTypeBindings(bindings, forPrimaryConstructor = ! isSimpleExtension)
806
813
val decoName = {
807
- def clsName (tree : Tree ): String = tree match {
808
- case Apply (tycon, args) => clsName(tycon)
809
- case TypeApply (tycon, args) => clsName(tycon)
810
- case Select (pre, nme.CONSTRUCTOR ) => clsName(pre)
811
- case New (tpt) => clsName(tpt)
812
- case AppliedTypeTree (tycon, _) => clsName(tycon)
813
- case tree : RefTree if tree.name.isTypeName => tree.name.toString
814
- case Parens (tree) => clsName(tree)
815
- case tree : TypeDef => tree.name.toString
816
- case _ => " "
817
- }
814
+ def clsName (tree : Tree ): String = leadingName(" " , tree)
818
815
val fromName = clsName(augmented)
819
816
val toName = impl.parents match {
820
817
case parent :: _ if ! clsName(parent).isEmpty => " To" + clsName(parent)
821
818
case _ => str.Augmentation
822
819
}
823
820
s " ${fromName}${toName}_in_ ${ctx.owner.topLevelClass.flatName}"
824
821
}
822
+
823
+ val firstParam = ValDef (nme.SELF , decorated, EmptyTree ).withFlags(Private | Local | ParamAccessor )
824
+ var constr1 =
825
+ cpy.DefDef (impl.constr)(
826
+ tparams = typeParams.map(_.withFlags(Param | Private | Local )),
827
+ vparamss = (firstParam :: Nil ) :: impl.constr.vparamss)
828
+ var parents1 = impl.parents
829
+ var body1 = substThis.transform(impl.body)
830
+ if (isSimpleExtension) {
831
+ constr1 = cpy.DefDef (constr1)(vparamss = constr1.vparamss.take(1 ))
832
+ parents1 = ref(defn.AnyValType ) :: Nil
833
+ body1 = body1.map {
834
+ case ddef : DefDef =>
835
+ def resetFlags (vdef : ValDef ) =
836
+ vdef.withMods(vdef.mods &~ PrivateLocalParamAccessor | Param )
837
+ val originalParams = impl.constr.vparamss.headOption.getOrElse(Nil ).map(resetFlags)
838
+ addEvidenceParams(addEvidenceParams(ddef, originalParams), evidenceParams)
839
+ }
840
+ }
841
+ else
842
+ constr1 = addEvidenceParams(constr1, evidenceParams)
843
+
825
844
val icls =
826
845
TypeDef (UniqueName .fresh(decoName.toTermName).toTypeName,
827
- cpy.Template (impl)(constr = constr1, body = substThis.transform(impl. body) ))
846
+ cpy.Template (impl)(constr = constr1, parents = parents1, body = body1 ))
828
847
.withFlags(Implicit )
829
848
desugr.println(i " desugar $augmented --> $icls" )
830
849
classDef(icls)
831
850
}
832
851
852
+ private val substThis = new UntypedTreeMap {
853
+ override def transform (tree : Tree )(implicit ctx : Context ): Tree = tree match {
854
+ case This (Ident (tpnme.EMPTY )) => Ident (nme.SELF ).withPos(tree.pos)
855
+ case _ => super .transform(tree)
856
+ }
857
+ }
858
+
859
+ private val leadingName = new UntypedTreeAccumulator [String ] {
860
+ override def apply (x : String , tree : Tree )(implicit ctx : Context ): String =
861
+ if (x.isEmpty)
862
+ tree match {
863
+ case Select (pre, nme.CONSTRUCTOR ) => foldOver(x, pre)
864
+ case tree : RefTree if tree.name.isTypeName => tree.name.toString
865
+ case tree : TypeDef => tree.name.toString
866
+ case tree : Tuple => " Tuple"
867
+ case tree : Function => " Function"
868
+ case _ => foldOver(x, tree)
869
+ }
870
+ else x
871
+ }
872
+
833
873
def defTree (tree : Tree )(implicit ctx : Context ): Tree = tree match {
834
874
case tree : ValDef => valDef(tree)
835
875
case tree : TypeDef => if (tree.isClassDef) classDef(tree) else tree
0 commit comments