@@ -19,6 +19,7 @@ import printing.Formatting.hl
19
19
import config .Printers
20
20
21
21
import scala .annotation .internal .sharable
22
+ import scala .annotation .threadUnsafe
22
23
23
24
object desugar {
24
25
import untpd ._
@@ -363,6 +364,31 @@ object desugar {
363
364
adaptToExpectedTpt(tree)
364
365
}
365
366
367
+ /** Split out the quoted pattern type variable definition from the pattern.
368
+ *
369
+ * Type variable definitions are all the `type t` defined at the start of a quoted pattern.
370
+ * Where name `t` is a pattern type variable name (i.e. lower case letters).
371
+ *
372
+ * ```
373
+ * type t1; ...; type tn; <pattern>
374
+ * ```
375
+ * is split into
376
+ * ```
377
+ * (List(<type t1>; ...; <type tn>), <pattern>)
378
+ * ```
379
+ */
380
+ def quotedPatternTypeVariables (tree : untpd.Tree )(using Context ): (List [untpd.TypeDef ], untpd.Tree ) =
381
+ tree match
382
+ case untpd.Block (stats, expr) =>
383
+ val (untpdTypeVariables, otherStats) = stats.span {
384
+ case tdef @ untpd.TypeDef (name, _) => name.isVarPattern
385
+ case _ => false
386
+ }
387
+ val pattern = if otherStats.isEmpty then expr else untpd.cpy.Block (tree)(otherStats, expr)
388
+ (untpdTypeVariables.asInstanceOf [List [untpd.TypeDef ]], pattern)
389
+ case _ =>
390
+ (Nil , tree)
391
+
366
392
/** Add all evidence parameters in `params` as implicit parameters to `meth`.
367
393
* If the parameters of `meth` end in an implicit parameter list or using clause,
368
394
* evidence parameters are added in front of that list. Otherwise they are added
@@ -462,6 +488,7 @@ object desugar {
462
488
def isNonEnumCase = ! isEnumCase && (isCaseClass || isCaseObject)
463
489
val isValueClass = parents.nonEmpty && isAnyVal(parents.head)
464
490
// This is not watertight, but `extends AnyVal` will be replaced by `inline` later.
491
+ val caseClassInScala2StdLib = isCaseClass && ctx.settings.Yscala2Stdlib .value
465
492
466
493
val originalTparams = constr1.leadingTypeParams
467
494
val originalVparamss = asTermOnly(constr1.trailingParamss)
@@ -637,10 +664,7 @@ object desugar {
637
664
// new C[...](p1, ..., pN)(moreParams)
638
665
val (caseClassMeths, enumScaffolding) = {
639
666
def syntheticProperty (name : TermName , tpt : Tree , rhs : Tree ) =
640
- val mods =
641
- if ctx.settings.Yscala2Stdlib .value then synthetic | Inline
642
- else synthetic
643
- DefDef (name, Nil , tpt, rhs).withMods(mods)
667
+ DefDef (name, Nil , tpt, rhs).withMods(synthetic)
644
668
645
669
def productElemMeths =
646
670
val caseParams = derivedVparamss.head.toArray
@@ -671,12 +695,14 @@ object desugar {
671
695
cpy.ValDef (vparam)(rhs = refOfDef(vparam)))
672
696
val copyRestParamss = derivedVparamss.tail.nestedMap(vparam =>
673
697
cpy.ValDef (vparam)(rhs = EmptyTree ))
698
+ var flags = Synthetic | constr1.mods.flags & copiedAccessFlags
699
+ if ctx.settings.Yscala2Stdlib .value then flags &~= Private
674
700
DefDef (
675
701
nme.copy,
676
702
joinParams(derivedTparams, copyFirstParams :: copyRestParamss),
677
703
TypeTree (),
678
704
creatorExpr
679
- ).withMods(Modifiers (Synthetic | constr1.mods. flags & copiedAccessFlags , constr1.mods.privateWithin)) :: Nil
705
+ ).withMods(Modifiers (flags, constr1.mods.privateWithin)) :: Nil
680
706
}
681
707
}
682
708
@@ -730,7 +756,9 @@ object desugar {
730
756
if (mods.is(Abstract )) Nil
731
757
else {
732
758
val appMods =
733
- Modifiers (Synthetic | constr1.mods.flags & copiedAccessFlags).withPrivateWithin(constr1.mods.privateWithin)
759
+ var flags = Synthetic | constr1.mods.flags & copiedAccessFlags
760
+ if ctx.settings.Yscala2Stdlib .value then flags &~= Private
761
+ Modifiers (flags).withPrivateWithin(constr1.mods.privateWithin)
734
762
val appParamss =
735
763
derivedVparamss.nestedZipWithConserve(constrVparamss)((ap, cp) =>
736
764
ap.withMods(ap.mods | (cp.mods.flags & HasDefault )))
@@ -753,7 +781,7 @@ object desugar {
753
781
val unapplyParam = makeSyntheticParameter(tpt = classTypeRef)
754
782
val unapplyRHS =
755
783
if (arity == 0 ) Literal (Constant (true ))
756
- else if ctx.settings. Yscala2Stdlib .value then scala2LibCompatUnapplyRhs(unapplyParam.name)
784
+ else if caseClassInScala2StdLib then scala2LibCompatUnapplyRhs(unapplyParam.name)
757
785
else Ident (unapplyParam.name)
758
786
val unapplyResTp = if (arity == 0 ) Literal (Constant (true )) else TypeTree ()
759
787
@@ -1036,6 +1064,40 @@ object desugar {
1036
1064
name
1037
1065
}
1038
1066
1067
+ /** Strip parens and empty blocks around the body of `tree`. */
1068
+ def normalizePolyFunction (tree : PolyFunction )(using Context ): PolyFunction =
1069
+ def stripped (body : Tree ): Tree = body match
1070
+ case Parens (body1) =>
1071
+ stripped(body1)
1072
+ case Block (Nil , body1) =>
1073
+ stripped(body1)
1074
+ case _ => body
1075
+ cpy.PolyFunction (tree)(tree.targs, stripped(tree.body)).asInstanceOf [PolyFunction ]
1076
+
1077
+ /** Desugar [T_1, ..., T_M] => (P_1, ..., P_N) => R
1078
+ * Into scala.PolyFunction { def apply[T_1, ..., T_M](x$1: P_1, ..., x$N: P_N): R }
1079
+ */
1080
+ def makePolyFunctionType (tree : PolyFunction )(using Context ): RefinedTypeTree =
1081
+ val PolyFunction (tparams : List [untpd.TypeDef ] @ unchecked, fun @ untpd.Function (vparamTypes, res)) = tree : @ unchecked
1082
+ val funFlags = fun match
1083
+ case fun : FunctionWithMods =>
1084
+ fun.mods.flags
1085
+ case _ => EmptyFlags
1086
+
1087
+ // TODO: make use of this in the desugaring when pureFuns is enabled.
1088
+ // val isImpure = funFlags.is(Impure)
1089
+
1090
+ // Function flags to be propagated to each parameter in the desugared method type.
1091
+ val paramFlags = funFlags.toTermFlags & Given
1092
+ val vparams = vparamTypes.zipWithIndex.map:
1093
+ case (p : ValDef , _) => p.withAddedFlags(paramFlags)
1094
+ case (p, n) => makeSyntheticParameter(n + 1 , p).withAddedFlags(paramFlags)
1095
+
1096
+ RefinedTypeTree (ref(defn.PolyFunctionType ), List (
1097
+ DefDef (nme.apply, tparams :: vparams :: Nil , res, EmptyTree ).withFlags(Synthetic )
1098
+ )).withSpan(tree.span)
1099
+ end makePolyFunctionType
1100
+
1039
1101
/** Invent a name for an anonympus given of type or template `impl`. */
1040
1102
def inventGivenOrExtensionName (impl : Tree )(using Context ): SimpleName =
1041
1103
val str = impl match
@@ -1429,17 +1491,20 @@ object desugar {
1429
1491
}
1430
1492
1431
1493
/** Make closure corresponding to function.
1432
- * params => body
1494
+ * [tparams] => params => body
1433
1495
* ==>
1434
- * def $anonfun(params) = body
1496
+ * def $anonfun[tparams] (params) = body
1435
1497
* Closure($anonfun)
1436
1498
*/
1437
- def makeClosure (params : List [ValDef ], body : Tree , tpt : Tree | Null = null , isContextual : Boolean , span : Span )(using Context ): Block =
1499
+ def makeClosure (tparams : List [TypeDef ], vparams : List [ValDef ], body : Tree , tpt : Tree | Null = null , span : Span )(using Context ): Block =
1500
+ val paramss : List [ParamClause ] =
1501
+ if tparams.isEmpty then vparams :: Nil
1502
+ else tparams :: vparams :: Nil
1438
1503
Block (
1439
- DefDef (nme.ANON_FUN , params :: Nil , if (tpt == null ) TypeTree () else tpt, body)
1504
+ DefDef (nme.ANON_FUN , paramss , if (tpt == null ) TypeTree () else tpt, body)
1440
1505
.withSpan(span)
1441
1506
.withMods(synthetic | Artifact ),
1442
- Closure (Nil , Ident (nme.ANON_FUN ), if (isContextual) ContextualEmptyTree else EmptyTree ))
1507
+ Closure (Nil , Ident (nme.ANON_FUN ), EmptyTree ))
1443
1508
1444
1509
/** If `nparams` == 1, expand partial function
1445
1510
*
@@ -1728,62 +1793,6 @@ object desugar {
1728
1793
}
1729
1794
}
1730
1795
1731
- def makePolyFunction (targs : List [Tree ], body : Tree , pt : Type ): Tree = body match {
1732
- case Parens (body1) =>
1733
- makePolyFunction(targs, body1, pt)
1734
- case Block (Nil , body1) =>
1735
- makePolyFunction(targs, body1, pt)
1736
- case Function (vargs, res) =>
1737
- assert(targs.nonEmpty)
1738
- // TODO: Figure out if we need a `PolyFunctionWithMods` instead.
1739
- val mods = body match {
1740
- case body : FunctionWithMods => body.mods
1741
- case _ => untpd.EmptyModifiers
1742
- }
1743
- val polyFunctionTpt = ref(defn.PolyFunctionType )
1744
- val applyTParams = targs.asInstanceOf [List [TypeDef ]]
1745
- if (ctx.mode.is(Mode .Type )) {
1746
- // Desugar [T_1, ..., T_M] -> (P_1, ..., P_N) => R
1747
- // Into scala.PolyFunction { def apply[T_1, ..., T_M](x$1: P_1, ..., x$N: P_N): R }
1748
-
1749
- val applyVParams = vargs.zipWithIndex.map {
1750
- case (p : ValDef , _) => p.withAddedFlags(mods.flags)
1751
- case (p, n) => makeSyntheticParameter(n + 1 , p).withAddedFlags(mods.flags.toTermFlags)
1752
- }
1753
- RefinedTypeTree (polyFunctionTpt, List (
1754
- DefDef (nme.apply, applyTParams :: applyVParams :: Nil , res, EmptyTree ).withFlags(Synthetic )
1755
- ))
1756
- }
1757
- else {
1758
- // Desugar [T_1, ..., T_M] -> (x_1: P_1, ..., x_N: P_N) => body
1759
- // with pt [S_1, ..., S_M] -> (O_1, ..., O_N) => R
1760
- // Into new scala.PolyFunction { def apply[T_1, ..., T_M](x_1: P_1, ..., x_N: P_N): R2 = body }
1761
- // where R2 is R, with all references to S_1..S_M replaced with T1..T_M.
1762
-
1763
- def typeTree (tp : Type ) = tp match
1764
- case RefinedType (parent, nme.apply, PolyType (_, mt)) if parent.typeSymbol eq defn.PolyFunctionClass =>
1765
- var bail = false
1766
- def mapper (tp : Type , topLevel : Boolean = false ): Tree = tp match
1767
- case tp : TypeRef => ref(tp)
1768
- case tp : TypeParamRef => Ident (applyTParams(tp.paramNum).name)
1769
- case AppliedType (tycon, args) => AppliedTypeTree (mapper(tycon), args.map(mapper(_)))
1770
- case _ => if topLevel then TypeTree () else { bail = true ; genericEmptyTree }
1771
- val mapped = mapper(mt.resultType, topLevel = true )
1772
- if bail then TypeTree () else mapped
1773
- case _ => TypeTree ()
1774
-
1775
- val applyVParams = vargs.asInstanceOf [List [ValDef ]]
1776
- .map(varg => varg.withAddedFlags(mods.flags | Param ))
1777
- New (Template (emptyConstructor, List (polyFunctionTpt), Nil , EmptyValDef ,
1778
- List (DefDef (nme.apply, applyTParams :: applyVParams :: Nil , typeTree(pt), res))
1779
- ))
1780
- }
1781
- case _ =>
1782
- // may happen for erroneous input. An error will already have been reported.
1783
- assert(ctx.reporter.errorsReported)
1784
- EmptyTree
1785
- }
1786
-
1787
1796
// begin desugar
1788
1797
1789
1798
// Special case for `Parens` desugaring: unlike all the desugarings below,
@@ -1796,8 +1805,6 @@ object desugar {
1796
1805
}
1797
1806
1798
1807
val desugared = tree match {
1799
- case PolyFunction (targs, body) =>
1800
- makePolyFunction(targs, body, pt) orElse tree
1801
1808
case SymbolLit (str) =>
1802
1809
Apply (
1803
1810
ref(defn.ScalaSymbolClass .companionModule.termRef),
0 commit comments