Skip to content

Fix #3596: Handle supercall arguments in unpickler #3628

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/ast/TreeInfo.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/core/Flags.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 4 additions & 0 deletions compiler/src/dotty/tools/dotc/core/NameTags.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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 `<num>_outer`, used by the inliner to indicate an
// outer accessor that will be filled in by ExplicitOuter.
// <num> 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;
Expand Down
30 changes: 14 additions & 16 deletions compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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*

Expand Down Expand Up @@ -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*
Expand All @@ -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*
Expand Down Expand Up @@ -248,10 +248,6 @@ object TastyFormat {
final val VARIANT = 12 // A name `+<name>` o `-<name>` indicating
// a co- or contra-variant parameter of a type lambda.

final val OUTERSELECT = 13 // A name `<num>_outer`, used by the inliner to indicate an
// outer accessor that will be filled in by ExplicitOuter.
// <num> 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$<name>` created by SuperAccesors.
Expand Down Expand Up @@ -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

Expand All @@ -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
Expand Down Expand Up @@ -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"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
22 changes: 17 additions & 5 deletions compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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) }
Expand Down
56 changes: 27 additions & 29 deletions compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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 =
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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) =
Expand All @@ -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)
Expand All @@ -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 =>
Expand All @@ -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)
Expand All @@ -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)
Expand Down Expand Up @@ -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)
Expand All @@ -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))
}

Expand Down Expand Up @@ -913,24 +915,20 @@ class TreeUnpickler(reader: TastyReader, nameAtRef: NameRef => TermName, posUnpi
SingletonTypeTree(readTerm())
case BYNAMEtpt =>
ByNameTypeTree(readTpt())
case NAMEDARG =>
NamedArg(readName(), readTerm())
case _ =>
readPathTerm()
}

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)
}

Expand Down Expand Up @@ -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 =>
Expand All @@ -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)
Expand Down Expand Up @@ -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())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/typer/Typer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
10 changes: 10 additions & 0 deletions tests/pickling/i3608.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
class A {
class Foo {
inline def inlineMeth: Unit = new Bar
}
class Bar
}

class B extends A {
(new Foo).inlineMeth
}
2 changes: 2 additions & 0 deletions tests/pos-from-tasty/i3596.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
class Bar(ctor : Int => Int)
class Foo extends Bar(x => x)
3 changes: 3 additions & 0 deletions tests/pos-from-tasty/i3597.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
object Test {
def bar(inline n: Int) = n
}
6 changes: 3 additions & 3 deletions tests/run/i3006b.check
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
Foo$$_$bar$1
Foo$$_$bar$2
Bar$$_$bar$1
bar$1
bar$2
bar$1