From dd0e68e422d1c793ce5656795fd621f9b576fc24 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sat, 2 Dec 2017 11:43:18 +0100 Subject: [PATCH] Fix #3608: Treat outer selections as separate Tasty tree Tasty needs to know about outer selections as separate trees. So instead of exposing a name for outer selects we expose a tree format. This allows us to store the type of tree selection in the tree, which got lost before. Also: Change format of NAMEDarg to no longer require a length. --- .../src/dotty/tools/dotc/core/NameTags.scala | 4 +++ .../tools/dotc/core/tasty/TastyFormat.scala | 30 +++++++++---------- .../dotc/core/tasty/TastyUnpickler.scala | 2 +- .../tools/dotc/core/tasty/TreePickler.scala | 22 ++++++++++---- .../tools/dotc/core/tasty/TreeUnpickler.scala | 7 +++-- tests/pickling/i3608.scala | 10 +++++++ 6 files changed, 51 insertions(+), 24 deletions(-) create mode 100644 tests/pickling/i3608.scala diff --git a/compiler/src/dotty/tools/dotc/core/NameTags.scala b/compiler/src/dotty/tools/dotc/core/NameTags.scala index 3afe715147b4..11c890823100 100644 --- a/compiler/src/dotty/tools/dotc/core/NameTags.scala +++ b/compiler/src/dotty/tools/dotc/core/NameTags.scala @@ -11,6 +11,10 @@ object NameTags extends TastyFormat.NameTags { final val TRAITSETTER = 6 // A Scala-2 trait setter, generated by AugmentScala2Traits + final val OUTERSELECT = 13 // A name `_outer`, used by the inliner to indicate an + // outer accessor that will be filled in by ExplicitOuter. + // indicates the number of hops needed to select the outer field. + final val INITIALIZER = 24 // A mixin initializer method final val AVOIDCLASH = 25 // Adds a suffix to avoid a name clash; diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala b/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala index f2c8db08e2f4..82824495513d 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala @@ -37,12 +37,11 @@ Macro-format: UNIQUE Length separator_NameRef uniqid_Nat underlying_NameRef? DEFAULTGETTER Length underlying_NameRef index_Nat VARIANT Length underlying_NameRef variance_Nat // 0: Contravariant, 1: Covariant - OUTERSELECT Length underlying_NameRef nhops_Nat SUPERACCESSOR Length underlying_NameRef PROTECTEDACCESSOR Length underlying_NameRef PROTECTEDSETTER Length underlying_NameRef - INITIALIZER Length underlying_NameRef + OBJECTCLASS Length underlying_NameRef SIGNED Length original_NameRef resultSig_NameRef paramSig_NameRef* @@ -81,9 +80,9 @@ Standard-Section: "ASTs" TopLevelStat* SELECT possiblySigned_NameRef qual_Term QUALTHIS typeIdent_Tree NEW cls_Type + NAMEDARG paramName_NameRef arg_Term SUPER Length this_Term mixinTypeIdent_Tree? TYPED Length expr_Term ascription_Type - NAMEDARG Length paramName_NameRef arg_Term ASSIGN Length lhs_Term rhs_Term BLOCK Length expr_Term Stat* INLINED Length call_Term expr_Term Stat* @@ -93,6 +92,7 @@ Standard-Section: "ASTs" TopLevelStat* TRY Length expr_Term CaseDef* finalizer_Term? RETURN Length meth_ASTRef expr_Term? REPEATED Length elem_Type elem_Term* + SELECTouter Length levels_Nat qual_Term underlying_Type BIND Length boundName_NameRef patType_Type pat_Term ALTERNATIVE Length alt_Term* UNAPPLY Length fun_Term ImplicitArg* pat_Type pat_Term* @@ -248,10 +248,6 @@ object TastyFormat { final val VARIANT = 12 // A name `+` o `-` indicating // a co- or contra-variant parameter of a type lambda. - final val OUTERSELECT = 13 // A name `_outer`, used by the inliner to indicate an - // outer accessor that will be filled in by ExplicitOuter. - // indicates the number of hops needed to select the outer field. - final val SUPERACCESSOR = 20 // The name of a super accessor `super$name` created by SuperAccesors. final val PROTECTEDACCESSOR = 21 // The name of a protected accessor `protected$` created by SuperAccesors. @@ -336,6 +332,7 @@ object TastyFormat { final val RECtype = 90 final val TYPEALIAS = 91 final val SINGLETONtpt = 92 + final val NAMEDARG = 93 // Cat. 4: tag Nat AST @@ -362,15 +359,15 @@ object TastyFormat { final val APPLY = 136 final val TYPEAPPLY = 137 final val TYPED = 138 - final val NAMEDARG = 139 - final val ASSIGN = 140 - final val BLOCK = 141 - final val IF = 142 - final val LAMBDA = 143 - final val MATCH = 144 - final val RETURN = 145 - final val TRY = 146 - final val INLINED = 147 + final val ASSIGN = 139 + final val BLOCK = 140 + final val IF = 141 + final val LAMBDA = 142 + final val MATCH = 143 + final val RETURN = 144 + final val TRY = 145 + final val INLINED = 146 + final val SELECTouter = 147 final val REPEATED = 148 final val BIND = 149 final val ALTERNATIVE = 150 @@ -536,6 +533,7 @@ object TastyFormat { case MATCH => "MATCH" case RETURN => "RETURN" case INLINED => "INLINED" + case SELECTouter => "SELECTouter" case TRY => "TRY" case REPEATED => "REPEATED" case BIND => "BIND" diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TastyUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TastyUnpickler.scala index 87b074054ce7..f3ae3292776f 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TastyUnpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TastyUnpickler.scala @@ -58,7 +58,7 @@ class TastyUnpickler(reader: TastyReader) { val originals = until(end)(readName()) val original = if (originals.isEmpty) EmptyTermName else originals.head uniqueNameKindOfSeparator(separator)(original, num) - case DEFAULTGETTER | VARIANT | OUTERSELECT => + case DEFAULTGETTER | VARIANT => numberedNameKindOfTag(tag)(readName(), readNat()) case SIGNED => val original = readName() diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala index 6986392c8e35..37e82f8fdf37 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala @@ -342,10 +342,21 @@ class TreePickler(pickler: TastyPickler) { pickleTree(qual.withType(tref)) } case Select(qual, name) => - writeByte(if (name.isTypeName) SELECTtpt else SELECT) - val sig = tree.tpe.signature - pickleNameAndSig(name, sig) - pickleTree(qual) + name match { + case OuterSelectName(_, levels) => + writeByte(SELECTouter) + withLength { + writeNat(levels) + pickleTree(qual) + val SkolemType(tp) = tree.tpe + pickleType(tp) + } + case _ => + writeByte(if (name.isTypeName) SELECTtpt else SELECT) + val sig = tree.tpe.signature + pickleNameAndSig(name, sig) + pickleTree(qual) + } case Apply(fun, args) => writeByte(APPLY) withLength { @@ -382,7 +393,8 @@ class TreePickler(pickler: TastyPickler) { withLength { pickleTree(expr); pickleTpt(tpt) } case NamedArg(name, arg) => writeByte(NAMEDARG) - withLength { pickleName(name); pickleTree(arg) } + pickleName(name) + pickleTree(arg) case Assign(lhs, rhs) => writeByte(ASSIGN) withLength { pickleTree(lhs); pickleTree(rhs) } diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala index 41a98c8edae9..c1a06769a7c4 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala @@ -913,6 +913,8 @@ class TreeUnpickler(reader: TastyReader, nameAtRef: NameRef => TermName, posUnpi SingletonTypeTree(readTerm()) case BYNAMEtpt => ByNameTypeTree(readTpt()) + case NAMEDARG => + NamedArg(readName(), readTerm()) case _ => readPathTerm() } @@ -960,8 +962,6 @@ class TreeUnpickler(reader: TastyReader, nameAtRef: NameRef => TermName, posUnpi case expr => expr } Typed(expr1, tpt) - case NAMEDARG => - NamedArg(readName(), readTerm()) case ASSIGN => Assign(readTerm(), readTerm()) case BLOCK => @@ -983,6 +983,9 @@ class TreeUnpickler(reader: TastyReader, nameAtRef: NameRef => TermName, posUnpi Return(expr, Ident(from.termRef)) case TRY => Try(readTerm(), readCases(end), ifBefore(end)(readTerm(), EmptyTree)) + case SELECTouter => + val levels = readNat() + readTerm().outerSelect(levels, SkolemType(readType())) case REPEATED => val elemtpt = readTpt() SeqLiteral(until(end)(readTerm()), elemtpt) diff --git a/tests/pickling/i3608.scala b/tests/pickling/i3608.scala new file mode 100644 index 000000000000..2751d5d017dd --- /dev/null +++ b/tests/pickling/i3608.scala @@ -0,0 +1,10 @@ +class A { + class Foo { + inline def inlineMeth: Unit = new Bar + } + class Bar +} + +class B extends A { + (new Foo).inlineMeth +}