Skip to content

Commit 21cb490

Browse files
authored
Merge pull request #6491 from dotty-staging/implicit-alias-rhs
Cache Right Hand Side of Parameterless Alias Implicits
2 parents 4693a88 + 659e1f1 commit 21cb490

37 files changed

+435
-186
lines changed

compiler/src/dotty/tools/dotc/Compiler.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ class Compiler {
6262
new ExpandSAMs, // Expand single abstract method closures to anonymous classes
6363
new ProtectedAccessors, // Add accessors for protected members
6464
new ExtensionMethods, // Expand methods of value classes with extension methods
65+
new CacheAliasImplicits, // Cache RHS of parameterless alias implicits
6566
new ShortcutImplicits, // Allow implicit functions without creating closures
6667
new ByNameClosures, // Expand arguments to by-name parameters to closures
6768
new HoistSuperArgs, // Hoist complex arguments of supercalls to enclosing scope

compiler/src/dotty/tools/dotc/ast/Desugar.scala

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -512,7 +512,15 @@ object desugar {
512512
case _ =>
513513
constrVparamss
514514
}
515-
New(classTypeRef, vparamss.nestedMap(refOfDef))
515+
val nu = (makeNew(classTypeRef) /: vparamss) { (nu, vparams) =>
516+
val app = Apply(nu, vparams.map(refOfDef))
517+
vparams match {
518+
case vparam :: _ if vparam.mods.is(Given) => app.pushAttachment(ApplyGiven, ())
519+
case _ =>
520+
}
521+
app
522+
}
523+
ensureApplied(nu)
516524
}
517525

518526
val copiedAccessFlags = if (ctx.scala2Setting) EmptyFlags else AccessFlags

compiler/src/dotty/tools/dotc/ast/tpd.scala

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
5757
def unitLiteral(implicit ctx: Context): Literal =
5858
Literal(Constant(()))
5959

60+
def nullLiteral(implicit ctx: Context): Literal =
61+
Literal(Constant(null))
62+
6063
def New(tpt: Tree)(implicit ctx: Context): New =
6164
ta.assignType(untpd.New(tpt), tpt)
6265

@@ -496,7 +499,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
496499
else if (tpw isRef defn.DoubleClass) Literal(Constant(0d))
497500
else if (tpw isRef defn.ByteClass) Literal(Constant(0.toByte))
498501
else if (tpw isRef defn.ShortClass) Literal(Constant(0.toShort))
499-
else Literal(Constant(null)).select(defn.Any_asInstanceOf).appliedToType(tpe)
502+
else nullLiteral.select(defn.Any_asInstanceOf).appliedToType(tpe)
500503
}
501504

502505
private class FindLocalDummyAccumulator(cls: ClassSymbol)(implicit ctx: Context) extends TreeAccumulator[Symbol] {
@@ -915,7 +918,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
915918
Typed(tree, TypeTree(defn.AnyRefType))
916919
}
917920
else tree.ensureConforms(defn.ObjectType)
918-
receiver.select(defn.Object_ne).appliedTo(Literal(Constant(null)))
921+
receiver.select(defn.Object_ne).appliedTo(nullLiteral)
919922
}
920923

921924
/** If inititializer tree is `_', the default value of its type,

compiler/src/dotty/tools/dotc/ast/untpd.scala

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
6868
override def isType: Boolean = body.isType
6969
}
7070

71-
/** A function type with `implicit`, `erased`, or `contextual` modifiers */
71+
/** A function type with `implicit`, `erased`, or `given` modifiers */
7272
class FunctionWithMods(args: List[Tree], body: Tree, val mods: Modifiers)(implicit @constructorOnly src: SourceFile)
7373
extends Function(args, body)
7474

@@ -352,7 +352,13 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
352352
* navigation into these arguments from the IDE, and to do the right thing in
353353
* PrepareInlineable.
354354
*/
355-
def New(tpt: Tree, argss: List[List[Tree]])(implicit ctx: Context): Tree = {
355+
def New(tpt: Tree, argss: List[List[Tree]])(implicit ctx: Context): Tree =
356+
ensureApplied((makeNew(tpt) /: argss)(Apply(_, _)))
357+
358+
/** A new expression with constrictor and possibly type arguments. See
359+
* `New(tpt, argss)` for details.
360+
*/
361+
def makeNew(tpt: Tree)(implicit ctx: Context): Tree = {
356362
val (tycon, targs) = tpt match {
357363
case AppliedTypeTree(tycon, targs) =>
358364
(tycon, targs)
@@ -363,9 +369,8 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
363369
case _ =>
364370
(tpt, Nil)
365371
}
366-
var prefix: Tree = Select(New(tycon), nme.CONSTRUCTOR)
367-
if (targs.nonEmpty) prefix = TypeApply(prefix, targs)
368-
ensureApplied((prefix /: argss)(Apply(_, _)))
372+
val nu: Tree = Select(New(tycon), nme.CONSTRUCTOR)
373+
if (targs.nonEmpty) TypeApply(nu, targs) else nu
369374
}
370375

371376
def Block(stat: Tree, expr: Tree)(implicit src: SourceFile): Block =

compiler/src/dotty/tools/dotc/core/Flags.scala

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,9 @@ object Flags {
394394
/** Symbol is an enum class or enum case (if used with case) */
395395
final val Enum: FlagSet = commonFlag(40, "<enum>")
396396

397+
/** An export forwarder */
398+
final val Exported: FlagSet = commonFlag(41, "exported")
399+
397400
/** Labeled with `erased` modifier (erased value) */
398401
final val Erased: FlagSet = termFlag(42, "erased")
399402

@@ -459,7 +462,7 @@ object Flags {
459462

460463
/** Flags representing source modifiers */
461464
private val CommonSourceModifierFlags: FlagSet =
462-
commonFlags(Private, Protected, Final, Case, Implicit, Implied, Override, JavaStatic)
465+
commonFlags(Private, Protected, Final, Case, Implicit, Implied, Given, Override, JavaStatic)
463466

464467
final val TypeSourceModifierFlags: FlagSet =
465468
CommonSourceModifierFlags.toTypeFlags | Abstract | Sealed | Opaque

compiler/src/dotty/tools/dotc/core/NameKinds.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,7 @@ object NameKinds {
359359
val InlineAccessorName: PrefixNameKind = new PrefixNameKind(INLINEACCESSOR, "inline$")
360360

361361
val AvoidClashName: SuffixNameKind = new SuffixNameKind(AVOIDCLASH, "$_avoid_name_clash_$")
362+
val CacheName = new SuffixNameKind(CACHE, "$_cache")
362363
val DirectMethodName: SuffixNameKind = new SuffixNameKind(DIRECT, "$direct") { override def definesNewName = true }
363364
val FieldName: SuffixNameKind = new SuffixNameKind(FIELD, "$$local") {
364365
override def mkString(underlying: TermName, info: ThisInfo) = underlying.toString

compiler/src/dotty/tools/dotc/core/NameTags.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ object NameTags extends TastyFormat.NameTags {
3636
final val IMPLMETH = 32 // Used to define methods in implementation classes
3737
// (can probably be removed).
3838

39+
final val CACHE = 33 // Used as a cache for the rhs of an alias implicit.
40+
3941
def nameTagToString(tag: Int): String = tag match {
4042
case UTF8 => "UTF8"
4143
case QUALIFIED => "QUALIFIED"

compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,7 @@ Standard-Section: "ASTs" TopLevelStat*
208208
EXTENSION -- An extension method
209209
GIVEN -- A new style implicit parameter, introduced with `given`
210210
PARAMsetter -- The setter part `x_=` of a var parameter `x` which itself is pickled as a PARAM
211+
EXPORTED -- An export forwarder
211212
Annotation
212213
213214
Annotation = ANNOTATION Length tycon_Type fullAnnotation_Term -- An annotation, given (class) type of constructor, and full application tree
@@ -329,6 +330,7 @@ object TastyFormat {
329330
final val GIVEN = 37
330331
final val IMPLIED = 38
331332
final val PARAMsetter = 39
333+
final val EXPORTED = 40
332334

333335
// Cat. 2: tag Nat
334336

@@ -457,7 +459,7 @@ object TastyFormat {
457459

458460
/** Useful for debugging */
459461
def isLegalTag(tag: Int): Boolean =
460-
firstSimpleTreeTag <= tag && tag <= PARAMsetter ||
462+
firstSimpleTreeTag <= tag && tag <= EXPORTED ||
461463
firstNatTreeTag <= tag && tag <= SYMBOLconst ||
462464
firstASTTreeTag <= tag && tag <= SINGLETONtpt ||
463465
firstNatASTTreeTag <= tag && tag <= NAMEDARG ||
@@ -500,6 +502,7 @@ object TastyFormat {
500502
| EXTENSION
501503
| GIVEN
502504
| PARAMsetter
505+
| EXPORTED
503506
| ANNOTATION
504507
| PRIVATEqualified
505508
| PROTECTEDqualified => true
@@ -560,6 +563,7 @@ object TastyFormat {
560563
case EXTENSION => "EXTENSION"
561564
case GIVEN => "GIVEN"
562565
case PARAMsetter => "PARAMsetter"
566+
case EXPORTED => "EXPORTED"
563567

564568
case SHAREDterm => "SHAREDterm"
565569
case SHAREDtype => "SHAREDtype"

compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -656,6 +656,7 @@ class TreePickler(pickler: TastyPickler) {
656656
if (flags is Extension) writeByte(EXTENSION)
657657
if (flags is Given) writeByte(GIVEN)
658658
if (flags is ParamAccessor) writeByte(PARAMsetter)
659+
if (flags is Exported) writeByte(EXPORTED)
659660
assert(!(flags is Label))
660661
} else {
661662
if (flags is Sealed) writeByte(SEALED)

compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -632,8 +632,8 @@ class TreeUnpickler(reader: TastyReader,
632632
case STABLE => addFlag(StableRealizable)
633633
case EXTENSION => addFlag(Extension)
634634
case GIVEN => addFlag(Given)
635-
case PARAMsetter =>
636-
addFlag(ParamAccessor)
635+
case PARAMsetter => addFlag(ParamAccessor)
636+
case EXPORTED => addFlag(Exported)
637637
case PRIVATEqualified =>
638638
readByte()
639639
privateWithin = readWithin(ctx)

0 commit comments

Comments
 (0)