@@ -11,6 +11,7 @@ import language.higherKinds
11
11
import typer .FrontEnd
12
12
import collection .mutable .ListBuffer
13
13
import util .Property
14
+ import config .Printers .desugr
14
15
import reporting .diagnostic .messages ._
15
16
import reporting .trace
16
17
@@ -154,6 +155,25 @@ object desugar {
154
155
ValDef (epname, tpt, EmptyTree ).withFlags(paramFlags | Implicit )
155
156
}
156
157
158
+ private def desugarTypeBindings (
159
+ bindings : List [TypeDef ],
160
+ forPrimaryConstructor : Boolean = false )(implicit ctx : Context ): (List [TypeDef ], List [ValDef ]) = {
161
+ val epbuf = new ListBuffer [ValDef ]
162
+ def desugarContextBounds (rhs : Tree ): Tree = rhs match {
163
+ case ContextBounds (tbounds, cxbounds) =>
164
+ epbuf ++= makeImplicitParameters(cxbounds, forPrimaryConstructor)
165
+ tbounds
166
+ case LambdaTypeTree (tparams, body) =>
167
+ cpy.LambdaTypeTree (rhs)(tparams, desugarContextBounds(body))
168
+ case _ =>
169
+ rhs
170
+ }
171
+ val bindings1 = bindings mapConserve { tparam =>
172
+ cpy.TypeDef (tparam)(rhs = desugarContextBounds(tparam.rhs))
173
+ }
174
+ (bindings1, epbuf.toList)
175
+ }
176
+
157
177
/** Expand context bounds to evidence params. E.g.,
158
178
*
159
179
* def f[T >: L <: H : B](params)
@@ -171,21 +191,8 @@ object desugar {
171
191
private def defDef (meth : DefDef , isPrimaryConstructor : Boolean = false )(implicit ctx : Context ): Tree = {
172
192
val DefDef (name, tparams, vparamss, tpt, rhs) = meth
173
193
val mods = meth.mods
174
- val epbuf = new ListBuffer [ValDef ]
175
- def desugarContextBounds (rhs : Tree ): Tree = rhs match {
176
- case ContextBounds (tbounds, cxbounds) =>
177
- epbuf ++= makeImplicitParameters(cxbounds, isPrimaryConstructor)
178
- tbounds
179
- case LambdaTypeTree (tparams, body) =>
180
- cpy.LambdaTypeTree (rhs)(tparams, desugarContextBounds(body))
181
- case _ =>
182
- rhs
183
- }
184
- val tparams1 = tparams mapConserve { tparam =>
185
- cpy.TypeDef (tparam)(rhs = desugarContextBounds(tparam.rhs))
186
- }
187
-
188
- val meth1 = addEvidenceParams(cpy.DefDef (meth)(tparams = tparams1), epbuf.toList)
194
+ val (tparams1, evidenceParams) = desugarTypeBindings(tparams, isPrimaryConstructor)
195
+ val meth1 = addEvidenceParams(cpy.DefDef (meth)(tparams = tparams1), evidenceParams)
189
196
190
197
/** The longest prefix of parameter lists in vparamss whose total length does not exceed `n` */
191
198
def takeUpTo (vparamss : List [List [ValDef ]], n : Int ): List [List [ValDef ]] = vparamss match {
@@ -293,6 +300,7 @@ object desugar {
293
300
def isAnyVal (tree : Tree ): Boolean = tree match {
294
301
case Ident (tpnme.AnyVal ) => true
295
302
case Select (qual, tpnme.AnyVal ) => isScala(qual)
303
+ case TypedSplice (tree) => tree.tpe.isRef(defn.AnyValClass )
296
304
case _ => false
297
305
}
298
306
def isScala (tree : Tree ): Boolean = tree match {
@@ -749,6 +757,73 @@ object desugar {
749
757
Bind (name, Ident (nme.WILDCARD )).withPos(tree.pos)
750
758
}
751
759
760
+ /** extension id <type-params> <implicit-params> for <extended> : <parents> { <body> }
761
+ * ->
762
+ * implicit class <id> <type-params> ($this: <extended>) <combined-params>
763
+ * extends <parents> {
764
+ * import $this._
765
+ * <body1>
766
+ * }
767
+ *
768
+ * where
769
+ *
770
+ * (<type-params>, <evidence-params>) = desugarTypeBindings(<type-params0>)
771
+ * <combined-params> = <implicit-params> concatenated with <evidence-params> in one clause
772
+ * <body1> = <body> with each occurrence of unqualified `this` substituted by `$this`.
773
+ *
774
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
775
+ *
776
+ * extension <id> <type-params> <implicit-params> for <extended> { <defs> }
777
+ * ->
778
+ * implicit class <id> <type-params> (private val $this: <extended>)
779
+ * extends AnyVal {
780
+ * import $this._
781
+ * <body2>
782
+ * }
783
+ *
784
+ * where
785
+ *
786
+ * <body2> = <body1> where each method definition gets <combined-params> as last parameter section.
787
+ */
788
+ def extension (tree : Extension )(implicit ctx : Context ): Tree = {
789
+ val Extension (name, extended, impl) = tree
790
+ val isSimpleExtension = impl.parents.isEmpty
791
+
792
+ val firstParams = ValDef (nme.SELF , extended, EmptyTree ).withFlags(Private | Local | ParamAccessor ) :: Nil
793
+ val body1 = substThis.transform(impl.body)
794
+ val impl1 =
795
+ if (isSimpleExtension) {
796
+ val (typeParams, evidenceParams) =
797
+ desugarTypeBindings(impl.constr.tparams, forPrimaryConstructor = false )
798
+ cpy.Template (impl)(
799
+ constr = cpy.DefDef (impl.constr)(tparams = typeParams, vparamss = firstParams :: Nil ),
800
+ parents = ref(defn.AnyValType ) :: Nil ,
801
+ body = body1.map {
802
+ case ddef : DefDef =>
803
+ def resetFlags (vdef : ValDef ) =
804
+ vdef.withMods(vdef.mods &~ PrivateLocalParamAccessor | Param )
805
+ val originalParams = impl.constr.vparamss.headOption.getOrElse(Nil ).map(resetFlags)
806
+ addEvidenceParams(addEvidenceParams(ddef, originalParams), evidenceParams)
807
+ case other =>
808
+ other
809
+ })
810
+ }
811
+ else
812
+ cpy.Template (impl)(
813
+ constr = cpy.DefDef (impl.constr)(vparamss = firstParams :: impl.constr.vparamss),
814
+ body = body1)
815
+ val icls = TypeDef (name, impl1).withMods(tree.mods.withAddedMod(Mod .Extension ()) | Implicit )
816
+ desugr.println(i " desugar $extended --> $icls" )
817
+ classDef(icls)
818
+ }
819
+
820
+ private val substThis = new UntypedTreeMap {
821
+ override def transform (tree : Tree )(implicit ctx : Context ): Tree = tree match {
822
+ case This (Ident (tpnme.EMPTY )) => Ident (nme.SELF ).withPos(tree.pos)
823
+ case _ => super .transform(tree)
824
+ }
825
+ }
826
+
752
827
def defTree (tree : Tree )(implicit ctx : Context ): Tree = tree match {
753
828
case tree : ValDef => valDef(tree)
754
829
case tree : TypeDef => if (tree.isClassDef) classDef(tree) else tree
@@ -757,6 +832,7 @@ object desugar {
757
832
else defDef(tree)
758
833
case tree : ModuleDef => moduleDef(tree)
759
834
case tree : PatDef => patDef(tree)
835
+ case tree : Extension => extension(tree)
760
836
}
761
837
762
838
/** { stats; <empty > }
0 commit comments