From 83d18835bb430c67b55cbb6095b6dfe5806f21e2 Mon Sep 17 00:00:00 2001 From: Liu Fengyun Date: Tue, 25 May 2021 14:56:01 +0200 Subject: [PATCH] Don't force info to get signature in TreeChecker When we are reading a new definition from tasty and setting `info` of a symbol in `readNewDef`: sym.info = methodType(paramss, resType) The line above will reach `TreeChecker.transformSym`: assert(symd.signature == initial.signature At the time, the `symd` is not yet completed. Getting signature of the denotation will force the symbol and trigger completion of the info, which reaches the `PositionTree` in `readIndexedDef. --- compiler/src/dotty/tools/dotc/core/NamerOps.scala | 15 +++++++-------- .../dotty/tools/dotc/core/tasty/TreePickler.scala | 1 + .../tools/dotc/core/tasty/TreeUnpickler.scala | 6 +++++- .../dotty/tools/dotc/transform/TreeChecker.scala | 2 +- .../tools/dotc/transform/init/Semantic.scala | 1 + compiler/src/dotty/tools/dotc/typer/Namer.scala | 2 +- 6 files changed, 16 insertions(+), 11 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/NamerOps.scala b/compiler/src/dotty/tools/dotc/core/NamerOps.scala index e8199b6e7040..9444270ccb05 100644 --- a/compiler/src/dotty/tools/dotc/core/NamerOps.scala +++ b/compiler/src/dotty/tools/dotc/core/NamerOps.scala @@ -11,15 +11,14 @@ import ast.untpd /** Operations that are shared between Namer and TreeUnpickler */ object NamerOps: - /** The given type, unless `sym` is a constructor, in which case the - * type of the constructed instance is returned + /** The type of the constructed instance is returned + * + * @param ctor the constructor */ - def effectiveResultType(sym: Symbol, paramss: List[List[Symbol]], givenTp: Type)(using Context): Type = - if sym.name == nme.CONSTRUCTOR then - paramss match - case TypeSymbols(tparams) :: _ => sym.owner.typeRef.appliedTo(tparams.map(_.typeRef)) - case _ => sym.owner.typeRef - else givenTp + def effectiveResultType(ctor: Symbol, paramss: List[List[Symbol]])(using Context): Type = + paramss match + case TypeSymbols(tparams) :: _ => ctor.owner.typeRef.appliedTo(tparams.map(_.typeRef)) + case _ => ctor.owner.typeRef /** if isConstructor, make sure it has one leading non-implicit parameter list */ def normalizeIfConstructor(paramss: List[List[Symbol]], isConstructor: Boolean)(using Context): List[List[Symbol]] = diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala index af66ccd3ecc4..825df846ae0e 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala @@ -332,6 +332,7 @@ class TreePickler(pickler: TastyPickler) { def pickleDef(tag: Int, mdef: MemberDef, tpt: Tree, rhs: Tree = EmptyTree, pickleParams: => Unit = ())(using Context): Unit = { val sym = mdef.symbol + assert(symRefs(sym) == NoAddr, sym) registerDef(sym) writeByte(tag) diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala index 10d4e780b6f9..c8220d7e7604 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala @@ -831,7 +831,11 @@ class TreeUnpickler(reader: TastyReader, val tpt = readTpt()(using localCtx) val paramss = normalizeIfConstructor( paramDefss.nestedMap(_.symbol), name == nme.CONSTRUCTOR) - val resType = effectiveResultType(sym, paramss, tpt.tpe) + val resType = + if name == nme.CONSTRUCTOR then + effectiveResultType(sym, paramss) + else + tpt.tpe sym.info = methodType(paramss, resType) DefDef(paramDefss, tpt) case VALDEF => diff --git a/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala b/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala index 5946e0b07d9b..a0334df601f6 100644 --- a/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala +++ b/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala @@ -91,7 +91,7 @@ class TreeChecker extends Phase with SymTransformer { // until erasure, see the comment above `Compiler#phases`. if (ctx.phaseId <= erasurePhase.id) { val initial = symd.initial - assert(symd.signature == initial.signature, + assert(symd == initial || symd.signature == initial.signature, i"""Signature of ${sym.showLocated} changed at phase ${ctx.base.fusedContaining(ctx.phase.prev)} |Initial info: ${initial.info} |Initial sig : ${initial.signature} diff --git a/compiler/src/dotty/tools/dotc/transform/init/Semantic.scala b/compiler/src/dotty/tools/dotc/transform/init/Semantic.scala index ccbdac812342..68dd41dfae4a 100644 --- a/compiler/src/dotty/tools/dotc/transform/init/Semantic.scala +++ b/compiler/src/dotty/tools/dotc/transform/init/Semantic.scala @@ -795,6 +795,7 @@ class Semantic { // follow constructor if cls.hasSource then + printer.println("init super class " + cls.show) val res2 = thisV.call(ctor, superType = NoType, source)(using heap, ctx, trace.add(source)) errorBuffer ++= res2.errors diff --git a/compiler/src/dotty/tools/dotc/typer/Namer.scala b/compiler/src/dotty/tools/dotc/typer/Namer.scala index f421c75f9287..bb66963f6980 100644 --- a/compiler/src/dotty/tools/dotc/typer/Namer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Namer.scala @@ -1680,7 +1680,7 @@ class Namer { typer: Typer => if (isConstructor) { // set result type tree to unit, but take the current class as result type of the symbol typedAheadType(ddef.tpt, defn.UnitType) - wrapMethType(effectiveResultType(sym, paramSymss, NoType)) + wrapMethType(effectiveResultType(sym, paramSymss)) } else valOrDefDefSig(ddef, sym, paramSymss, wrapMethType) }