diff --git a/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala b/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala index 77e38410990f..d44fb91aad63 100644 --- a/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala +++ b/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala @@ -264,7 +264,7 @@ trait UntypedTreeInfo extends TreeInfo[Untyped] { self: Trees.Instance[Untyped] */ def lacksDefinition(mdef: MemberDef)(implicit ctx: Context) = mdef match { case mdef: ValOrDefDef => - mdef.unforcedRhs == EmptyTree && !mdef.name.isConstructorName && !mdef.mods.is(ParamAccessor) + mdef.unforcedRhs == EmptyTree && !mdef.name.isConstructorName && !mdef.mods.is(TermParamOrAccessor) case mdef: TypeDef => def isBounds(rhs: Tree): Boolean = rhs match { case _: TypeBoundsTree => true diff --git a/compiler/src/dotty/tools/dotc/core/Flags.scala b/compiler/src/dotty/tools/dotc/core/Flags.scala index 66f17a3c7f85..60438a125334 100644 --- a/compiler/src/dotty/tools/dotc/core/Flags.scala +++ b/compiler/src/dotty/tools/dotc/core/Flags.scala @@ -575,7 +575,7 @@ object Flags { final val SyntheticOrPrivate = Synthetic | Private /** A deferred member or a parameter accessor (these don't have right hand sides) */ - final val DeferredOrParamAccessor = Deferred | ParamAccessor + final val DeferredOrParamOrAccessor = Deferred | Param | ParamAccessor /** value that's final or inline */ final val FinalOrInline = Final | Inline 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..8052deda72e5 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala @@ -383,10 +383,8 @@ class TreeUnpickler(reader: TastyReader, nameAtRef: NameRef => TermName, posUnpi private def noRhs(end: Addr): Boolean = currentAddr == end || isModifierTag(nextByte) - private def localContext(owner: Symbol)(implicit ctx: Context) = { - val lctx = ctx.fresh.setOwner(owner) - if (owner.isClass) lctx.setScope(owner.unforcedDecls) else lctx.setNewScope - } + private def localContext(owner: Symbol)(implicit ctx: Context) = + ctx.fresh.setOwner(owner) private def normalizeFlags(tag: Int, givenFlags: FlagSet, name: Name, isAbsType: Boolean, rhsIsEmpty: Boolean)(implicit ctx: Context): FlagSet = { val lacksDefinition = @@ -475,7 +473,10 @@ class TreeUnpickler(reader: TastyReader, nameAtRef: NameRef => TermName, posUnpi ctx.newSymbol(ctx.owner, name, flags, completer, privateWithin, coord) } sym.annotations = annots - ctx.enter(sym) + ctx.owner match { + case cls: ClassSymbol => cls.enter(sym) + case _ => + } registerSym(start, sym) if (isClass) { sym.completer.withDecls(newScope) @@ -639,19 +640,18 @@ class TreeUnpickler(reader: TastyReader, nameAtRef: NameRef => TermName, posUnpi } } + val localCtx = localContext(sym) + def readRhs(implicit ctx: Context) = if (noRhs(end)) EmptyTree else readLater(end, rdr => ctx => rdr.readTerm()(ctx)) - def localCtx = localContext(sym) - def ValDef(tpt: Tree) = ta.assignType(untpd.ValDef(sym.name.asTermName, tpt, readRhs(localCtx)), sym) def DefDef(tparams: List[TypeDef], vparamss: List[List[ValDef]], tpt: Tree) = ta.assignType( - untpd.DefDef( - sym.name.asTermName, tparams, vparamss, tpt, readRhs(localCtx)), + untpd.DefDef(sym.name.asTermName, tparams, vparamss, tpt, readRhs(localCtx)), sym) def TypeDef(rhs: Tree) = @@ -665,7 +665,7 @@ class TreeUnpickler(reader: TastyReader, nameAtRef: NameRef => TermName, posUnpi case DEFDEF => val tparams = readParams[TypeDef](TYPEPARAM)(localCtx) val vparamss = readParamss(localCtx) - val tpt = readTpt() + val tpt = readTpt()(localCtx) val typeParams = tparams.map(_.symbol) val valueParamss = ctx.normalizeIfConstructor( vparamss.nestedMap(_.symbol), name == nme.CONSTRUCTOR) @@ -678,7 +678,7 @@ class TreeUnpickler(reader: TastyReader, nameAtRef: NameRef => TermName, posUnpi } DefDef(tparams, vparamss, tpt) case VALDEF => - val tpt = readTpt() + val tpt = readTpt()(localCtx) sym.info = tpt.tpe ValDef(tpt) case TYPEDEF | TYPEPARAM => @@ -697,7 +697,7 @@ class TreeUnpickler(reader: TastyReader, nameAtRef: NameRef => TermName, posUnpi } TypeDef(readTemplate(localCtx)) } else { - val rhs = readTpt() + val rhs = readTpt()(localCtx) sym.info = NoCompleter sym.info = rhs.tpe match { case _: TypeBounds | _: ClassInfo => checkNonCyclic(sym, rhs.tpe, reportErrors = false) @@ -706,7 +706,7 @@ class TreeUnpickler(reader: TastyReader, nameAtRef: NameRef => TermName, posUnpi TypeDef(rhs) } case PARAM => - val tpt = readTpt() + val tpt = readTpt()(localCtx) if (noRhs(end)) { sym.info = tpt.tpe ValDef(tpt) @@ -745,14 +745,15 @@ class TreeUnpickler(reader: TastyReader, nameAtRef: NameRef => TermName, posUnpi else NoType cls.info = new TempClassInfo(cls.owner.thisType, cls, cls.unforcedDecls, assumedSelfType) val localDummy = symbolAtCurrent() + val parentCtx = ctx.withOwner(localDummy) assert(readByte() == TEMPLATE) val end = readEnd() val tparams = readIndexedParams[TypeDef](TYPEPARAM) val vparams = readIndexedParams[ValDef](PARAM) val parents = collectWhile(nextByte != SELFDEF && nextByte != DEFDEF) { nextByte match { - case APPLY | TYPEAPPLY => readTerm() - case _ => readTpt() + case APPLY | TYPEAPPLY => readTerm()(parentCtx) + case _ => readTpt()(parentCtx) } } val parentTypes = parents.map(_.tpe.dealias) @@ -766,13 +767,14 @@ class TreeUnpickler(reader: TastyReader, nameAtRef: NameRef => TermName, posUnpi if (self.isEmpty) NoType else self.tpt.tpe) cls.setNoInitsFlags(fork.indexStats(end)) val constr = readIndexedDef().asInstanceOf[DefDef] + val mappedParents = parents.map(_.changeOwner(localDummy, constr.symbol)) val lazyStats = readLater(end, rdr => implicit ctx => { val stats = rdr.readIndexedStats(localDummy, end) tparams ++ vparams ++ stats }) setPos(start, - untpd.Template(constr, parents, self, lazyStats) + untpd.Template(constr, mappedParents, self, lazyStats) .withType(localDummy.termRef)) } @@ -913,6 +915,8 @@ class TreeUnpickler(reader: TastyReader, nameAtRef: NameRef => TermName, posUnpi SingletonTypeTree(readTerm()) case BYNAMEtpt => ByNameTypeTree(readTpt()) + case NAMEDARG => + NamedArg(readName(), readTerm()) case _ => readPathTerm() } @@ -920,17 +924,11 @@ class TreeUnpickler(reader: TastyReader, nameAtRef: NameRef => TermName, posUnpi def readLengthTerm(): Tree = { val end = readEnd() - def localNonClassCtx = { - val ctx1 = ctx.fresh.setNewScope - if (ctx.owner.isClass) ctx1.setOwner(ctx1.newLocalDummy(ctx.owner)) else ctx1 - } - def readBlock(mkTree: (List[Tree], Tree) => Tree): Tree = { val exprReader = fork skipTree() - val localCtx = localNonClassCtx - val stats = readStats(ctx.owner, end)(localCtx) - val expr = exprReader.readTerm()(localCtx) + val stats = readStats(ctx.owner, end) + val expr = exprReader.readTerm() mkTree(stats, expr) } @@ -960,8 +958,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 +979,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) @@ -1027,9 +1026,8 @@ class TreeUnpickler(reader: TastyReader, nameAtRef: NameRef => TermName, posUnpi case ANNOTATEDtpt => Annotated(readTpt(), readTerm()) case LAMBDAtpt => - val localCtx = localNonClassCtx - val tparams = readParams[TypeDef](TYPEPARAM)(localCtx) - val body = readTpt()(localCtx) + val tparams = readParams[TypeDef](TYPEPARAM) + val body = readTpt() LambdaTypeTree(tparams, body) case TYPEBOUNDStpt => TypeBoundsTree(readTpt(), readTpt()) diff --git a/compiler/src/dotty/tools/dotc/transform/ExpandPrivate.scala b/compiler/src/dotty/tools/dotc/transform/ExpandPrivate.scala index 34bc6c6e2694..e5ee8556ec88 100644 --- a/compiler/src/dotty/tools/dotc/transform/ExpandPrivate.scala +++ b/compiler/src/dotty/tools/dotc/transform/ExpandPrivate.scala @@ -74,7 +74,7 @@ class ExpandPrivate extends MiniPhase with IdentityDenotTransformer { thisPhase private def ensurePrivateAccessible(d: SymDenotation)(implicit ctx: Context) = if (isVCPrivateParamAccessor(d)) d.ensureNotPrivate.installAfter(thisPhase) - else if (d.is(PrivateTerm) && !d.owner.is(Package) && d.owner != ctx.owner.enclosingClass) { + else if (d.is(PrivateTerm) && !d.owner.is(Package) && d.owner != ctx.owner.lexicallyEnclosingClass) { // Paths `p1` and `p2` are similar if they have a common suffix that follows // possibly different directory paths. That is, their common suffix extends // in both cases either to the start of the path or to a file separator character. diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 1519780ea8be..fcfdce97cc97 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -1300,7 +1300,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit case rhs => typedExpr(rhs, tpt1.tpe) } val vdef1 = assignType(cpy.ValDef(vdef)(name, tpt1, rhs1), sym) - if (sym.is(Inline, butNot = DeferredOrParamAccessor)) + if (sym.is(Inline, butNot = DeferredOrParamOrAccessor)) checkInlineConformant(rhs1, em"right-hand side of inline $sym") patchIfLazy(vdef1) patchFinalVals(vdef1) 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 +} diff --git a/tests/pos-from-tasty/i3596.scala b/tests/pos-from-tasty/i3596.scala new file mode 100644 index 000000000000..6f122631779f --- /dev/null +++ b/tests/pos-from-tasty/i3596.scala @@ -0,0 +1,2 @@ +class Bar(ctor : Int => Int) +class Foo extends Bar(x => x) diff --git a/tests/pos-from-tasty/i3597.scala b/tests/pos-from-tasty/i3597.scala new file mode 100644 index 000000000000..04e33975ea2c --- /dev/null +++ b/tests/pos-from-tasty/i3597.scala @@ -0,0 +1,3 @@ +object Test { + def bar(inline n: Int) = n +} diff --git a/tests/run/i3006b.check b/tests/run/i3006b.check index b62605500d51..3698829ef115 100644 --- a/tests/run/i3006b.check +++ b/tests/run/i3006b.check @@ -1,3 +1,3 @@ -Foo$$_$bar$1 -Foo$$_$bar$2 -Bar$$_$bar$1 +bar$1 +bar$2 +bar$1