@@ -163,11 +163,11 @@ object desugar {
163
163
else vdef
164
164
}
165
165
166
- def makeImplicitParameters (tpts : List [Tree ], forPrimaryConstructor : Boolean = false )(implicit ctx : Context ): List [ValDef ] =
166
+ def makeImplicitParameters (tpts : List [Tree ], contextualFlag : FlagSet = EmptyFlags , forPrimaryConstructor : Boolean = false )(implicit ctx : Context ): List [ValDef ] =
167
167
for (tpt <- tpts) yield {
168
168
val paramFlags : FlagSet = if (forPrimaryConstructor) PrivateLocalParamAccessor else Param
169
169
val epname = EvidenceParamName .fresh()
170
- ValDef (epname, tpt, EmptyTree ).withFlags(paramFlags | Implicit )
170
+ ValDef (epname, tpt, EmptyTree ).withFlags(paramFlags | Implicit | contextualFlag )
171
171
}
172
172
173
173
/** 1. Expand context bounds to evidence params. E.g.,
@@ -197,12 +197,13 @@ object desugar {
197
197
* inline def f(x: Boolean): Any = (if (x) 1 else ""): Any
198
198
*/
199
199
private def defDef (meth : DefDef , isPrimaryConstructor : Boolean = false )(implicit ctx : Context ): Tree = {
200
- val DefDef (name, tparams, vparamss, tpt, rhs) = meth
200
+ val DefDef (_, tparams, vparamss, tpt, rhs) = meth
201
+ val methName = normalizeName(meth, tpt).asTermName
201
202
val mods = meth.mods
202
203
val epbuf = new ListBuffer [ValDef ]
203
204
def desugarContextBounds (rhs : Tree ): Tree = rhs match {
204
205
case ContextBounds (tbounds, cxbounds) =>
205
- epbuf ++= makeImplicitParameters(cxbounds, isPrimaryConstructor)
206
+ epbuf ++= makeImplicitParameters(cxbounds, forPrimaryConstructor = isPrimaryConstructor)
206
207
tbounds
207
208
case LambdaTypeTree (tparams, body) =>
208
209
cpy.LambdaTypeTree (rhs)(tparams, desugarContextBounds(body))
@@ -213,7 +214,8 @@ object desugar {
213
214
cpy.TypeDef (tparam)(rhs = desugarContextBounds(tparam.rhs))
214
215
}
215
216
216
- var meth1 = addEvidenceParams(cpy.DefDef (meth)(tparams = tparams1), epbuf.toList)
217
+ var meth1 = addEvidenceParams(
218
+ cpy.DefDef (meth)(name = methName, tparams = tparams1), epbuf.toList)
217
219
218
220
if (meth1.mods.is(Inline ))
219
221
meth1.tpt match {
@@ -245,7 +247,7 @@ object desugar {
245
247
case (vparam :: vparams) :: vparamss1 =>
246
248
def defaultGetter : DefDef =
247
249
DefDef (
248
- name = DefaultGetterName (meth.name , n),
250
+ name = DefaultGetterName (methName , n),
249
251
tparams = meth.tparams.map(tparam => dropContextBound(toDefParam(tparam))),
250
252
vparamss = takeUpTo(normalizedVparamss.nestedMap(toDefParam), n),
251
253
tpt = TypeTree (),
@@ -302,8 +304,8 @@ object desugar {
302
304
303
305
/** The expansion of a class definition. See inline comments for what is involved */
304
306
def classDef (cdef : TypeDef )(implicit ctx : Context ): Tree = {
305
- val className = checkNotReservedName(cdef).asTypeName
306
- val impl @ Template (_, _, self, _) = cdef.rhs
307
+ val impl @ Template (constr0, _, self, _) = cdef.rhs
308
+ val className = normalizeName(cdef, impl).asTypeName
307
309
val parents = impl.parents
308
310
val mods = cdef.mods
309
311
val companionMods = mods
@@ -341,6 +343,7 @@ object desugar {
341
343
val isCaseClass = mods.is(Case ) && ! mods.is(Module )
342
344
val isCaseObject = mods.is(Case ) && mods.is(Module )
343
345
val isImplicit = mods.is(Implicit )
346
+ val isInstance = isImplicit && mods.mods.exists(_.isInstanceOf [Mod .Instance ])
344
347
val isEnum = mods.isEnumClass && ! mods.is(Module )
345
348
def isEnumCase = mods.isEnumCase
346
349
val isValueClass = parents.nonEmpty && isAnyVal(parents.head)
@@ -445,7 +448,15 @@ object desugar {
445
448
}
446
449
447
450
// new C[Ts](paramss)
448
- lazy val creatorExpr = New (classTypeRef, constrVparamss nestedMap refOfDef)
451
+ lazy val creatorExpr = {
452
+ val vparamss = constrVparamss match {
453
+ case (vparam :: _) :: _ if vparam.mods.is(Implicit ) => // add a leading () to match class parameters
454
+ Nil :: constrVparamss
455
+ case _ =>
456
+ constrVparamss
457
+ }
458
+ New (classTypeRef, vparamss.nestedMap(refOfDef))
459
+ }
449
460
450
461
val copiedAccessFlags = if (ctx.scala2Setting) EmptyFlags else AccessFlags
451
462
@@ -660,16 +671,23 @@ object desugar {
660
671
ctx.error(ImplicitCaseClass (cdef), cdef.sourcePos)
661
672
Nil
662
673
}
663
- else if (arity != 1 ) {
674
+ else if (arity != 1 && ! isInstance ) {
664
675
ctx.error(ImplicitClassPrimaryConstructorArity (), cdef.sourcePos)
665
676
Nil
666
677
}
667
- else
678
+ else {
679
+ val defParamss = constrVparamss match {
680
+ case Nil :: paramss =>
681
+ paramss // drop leading () that got inserted by class
682
+ // TODO: drop this once we do not silently insert empty class parameters anymore
683
+ case paramss => paramss
684
+ }
668
685
// implicit wrapper is typechecked in same scope as constructor, so
669
686
// we can reuse the constructor parameters; no derived params are needed.
670
- DefDef (className.toTermName, constrTparams, constrVparamss , classTypeRef, creatorExpr)
671
- .withMods(companionMods | Synthetic | Implicit )
687
+ DefDef (className.toTermName, constrTparams, defParamss , classTypeRef, creatorExpr)
688
+ .withMods(companionMods | Synthetic | Implicit | Final )
672
689
.withSpan(cdef.span) :: Nil
690
+ }
673
691
674
692
val self1 = {
675
693
val selfType = if (self.tpt.isEmpty) classTypeRef else self.tpt
@@ -713,9 +731,9 @@ object desugar {
713
731
* <module> final class name$ extends parents { self: name.type => body }
714
732
*/
715
733
def moduleDef (mdef : ModuleDef )(implicit ctx : Context ): Tree = {
716
- val moduleName = checkNotReservedName(mdef).asTermName
717
734
val impl = mdef.impl
718
735
val mods = mdef.mods
736
+ val moduleName = normalizeName(mdef, impl).asTermName
719
737
def isEnumCase = mods.isEnumCase
720
738
721
739
def flagSourcePos (flag : FlagSet ) = mods.mods.find(_.flags == flag).fold(mdef.sourcePos)(_.sourcePos)
@@ -793,19 +811,69 @@ object desugar {
793
811
Thicket (aliasType :: companions.toList)
794
812
}
795
813
796
- /** The name of `mdef`, after checking that it does not redefine a Scala core class.
797
- * If it does redefine, issue an error and return a mangled name instead of the original one.
814
+ /** The normalized name of `mdef`. This means
815
+ * 1. Check that the name does not redefine a Scala core class.
816
+ * If it does redefine, issue an error and return a mangled name instead of the original one.
817
+ * 2. If the name is missing (this can be the case for instance definitions), invent one instead.
798
818
*/
799
- def checkNotReservedName (mdef : MemberDef )(implicit ctx : Context ): Name = {
800
- val name = mdef.name
819
+ def normalizeName (mdef : MemberDef , impl : Tree )(implicit ctx : Context ): Name = {
820
+ var name = mdef.name
821
+ if (name.isEmpty) name = name.likeSpaced(s " ${inventName(impl)}_instance " .toTermName)
801
822
if (ctx.owner == defn.ScalaPackageClass && defn.reservedScalaClassNames.contains(name.toTypeName)) {
802
823
def kind = if (name.isTypeName) " class" else " object"
803
824
ctx.error(em " illegal redefinition of standard $kind $name" , mdef.sourcePos)
804
- name.errorName
825
+ name = name .errorName
805
826
}
806
- else name
827
+ name
807
828
}
808
829
830
+ /** Invent a name for an anonymous instance with template `impl`.
831
+ */
832
+ private def inventName (impl : Tree )(implicit ctx : Context ): String = impl match {
833
+ case impl : Template =>
834
+ if (impl.parents.isEmpty)
835
+ impl.body.find {
836
+ case dd : DefDef if dd.mods.is(Extension ) => true
837
+ case _ => false
838
+ } match {
839
+ case Some (DefDef (name, _, (vparam :: _) :: _, _, _)) =>
840
+ s " ${name}_of_ ${inventTypeName(vparam.tpt)}"
841
+ case _ =>
842
+ ctx.error(i " anonymous instance must have `for` part or must define at least one extension method " , impl.sourcePos)
843
+ nme.ERROR .toString
844
+ }
845
+ else
846
+ impl.parents.map(inventTypeName(_)).mkString(" _" )
847
+ case impl : Tree =>
848
+ inventTypeName(impl)
849
+ }
850
+
851
+ private class NameExtractor (followArgs : Boolean ) extends UntypedTreeAccumulator [String ] {
852
+ private def extractArgs (args : List [Tree ])(implicit ctx : Context ): String =
853
+ args.map(argNameExtractor.apply(" " , _)).mkString(" _" )
854
+ override def apply (x : String , tree : Tree )(implicit ctx : Context ): String =
855
+ if (x.isEmpty)
856
+ tree match {
857
+ case Select (pre, nme.CONSTRUCTOR ) => foldOver(x, pre)
858
+ case tree : RefTree if tree.name.isTypeName => tree.name.toString
859
+ case tree : TypeDef => tree.name.toString
860
+ case tree : AppliedTypeTree if followArgs && tree.args.nonEmpty =>
861
+ s " ${apply(x, tree.tpt)}_ ${extractArgs(tree.args)}"
862
+ case tree : LambdaTypeTree =>
863
+ apply(x, tree.body)
864
+ case tree : Tuple =>
865
+ if (followArgs) extractArgs(tree.trees) else " Tuple"
866
+ case tree : Function if tree.args.nonEmpty =>
867
+ if (followArgs) s " ${extractArgs(tree.args)}_to_ ${apply(" " , tree.body)}" else " Function"
868
+ case _ => foldOver(x, tree)
869
+ }
870
+ else x
871
+ }
872
+ private val typeNameExtractor = new NameExtractor (followArgs = true )
873
+ private val argNameExtractor = new NameExtractor (followArgs = false )
874
+
875
+ private def inventTypeName (tree : Tree )(implicit ctx : Context ): String = typeNameExtractor(" " , tree)
876
+
809
877
/** val p1, ..., pN: T = E
810
878
* ==>
811
879
* makePatDef[[val p1: T1 = E ]]; ...; makePatDef[[val pN: TN = E ]]
@@ -960,14 +1028,11 @@ object desugar {
960
1028
* def $anonfun(params) = body
961
1029
* Closure($anonfun)
962
1030
*/
963
- def makeClosure (params : List [ValDef ], body : Tree , tpt : Tree = null , isImplicit : Boolean )(implicit ctx : Context ): Block = {
964
- val span = params.headOption.fold(body.span)(_.span.union(body.span))
1031
+ def makeClosure (params : List [ValDef ], body : Tree , tpt : Tree = null , isContextual : Boolean )(implicit ctx : Context ): Block =
965
1032
Block (
966
1033
DefDef (nme.ANON_FUN , Nil , params :: Nil , if (tpt == null ) TypeTree () else tpt, body)
967
- .withSpan(span)
968
1034
.withMods(synthetic | Artifact ),
969
- Closure (Nil , Ident (nme.ANON_FUN ), if (isImplicit) ImplicitEmptyTree else EmptyTree )).withSpan(span)
970
- }
1035
+ Closure (Nil , Ident (nme.ANON_FUN ), if (isContextual) ContextualEmptyTree else EmptyTree ))
971
1036
972
1037
/** If `nparams` == 1, expand partial function
973
1038
*
@@ -1020,9 +1085,9 @@ object desugar {
1020
1085
Function (param :: Nil , Block (vdefs, body))
1021
1086
}
1022
1087
1023
- def makeImplicitFunction (formals : List [Type ], body : Tree )(implicit ctx : Context ): Tree = {
1024
- val params = makeImplicitParameters(formals.map(TypeTree ))
1025
- new FunctionWithMods (params, body, Modifiers (Implicit ))
1088
+ def makeContextualFunction (formals : List [Type ], body : Tree )(implicit ctx : Context ): Tree = {
1089
+ val params = makeImplicitParameters(formals.map(TypeTree ), Contextual )
1090
+ new FunctionWithMods (params, body, Modifiers (Implicit | Contextual ))
1026
1091
}
1027
1092
1028
1093
/** Add annotation to tree:
0 commit comments