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 f7308c021fd3..8972a1e12ddd 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 630d10703dff..28228f845590 100644 --- a/compiler/src/dotty/tools/dotc/transform/init/Semantic.scala +++ b/compiler/src/dotty/tools/dotc/transform/init/Semantic.scala @@ -830,6 +830,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 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 7893114b86d9..0f6f7e46a39a 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) } diff --git a/compiler/test/dotty/tools/dotc/CompilationTests.scala b/compiler/test/dotty/tools/dotc/CompilationTests.scala index 2ac17ab05a95..78b90952768b 100644 --- a/compiler/test/dotty/tools/dotc/CompilationTests.scala +++ b/compiler/test/dotty/tools/dotc/CompilationTests.scala @@ -325,6 +325,27 @@ class CompilationTests { compileFilesInDir("tests/init/neg", options).checkExpectedErrors() compileFilesInDir("tests/init/pos", options).checkCompile() compileFilesInDir("tests/init/crash", options.without("-Xfatal-warnings")).checkCompile() + + // The regression test for i12128 has some atypical classpath requirements. + // The test consists of three files: (a) Reflect_1 (b) Macro_2 (c) Test_3 + // which must be compiled separately. In addition: + // - the output from (a) must be on the classpath while compiling (b) + // - the output from (b) must be on the classpath while compiling (c) + // - the output from (a) _must not_ be on the classpath while compiling (c) + locally { + val i12128Group = TestGroup("checkInit/i12128") + val i12128Options = options.without("-Xfatal-warnings") + val outDir1 = defaultOutputDir + i12128Group + "/Reflect_1/i12128/Reflect_1" + val outDir2 = defaultOutputDir + i12128Group + "/Macro_2/i12128/Macro_2" + + val tests = List( + compileFile("tests/init/special/i12128/Reflect_1.scala", i12128Options)(i12128Group), + compileFile("tests/init/special/i12128/Macro_2.scala", i12128Options.withClasspath(outDir1))(i12128Group), + compileFile("tests/init/special/i12128/Test_3.scala", options.withClasspath(outDir2))(i12128Group) + ).map(_.keepOutput.checkCompile()) + + tests.foreach(_.delete()) + } } } diff --git a/tests/init/special/i12128/Macro_2.scala b/tests/init/special/i12128/Macro_2.scala new file mode 100644 index 000000000000..0f5b866e6f1c --- /dev/null +++ b/tests/init/special/i12128/Macro_2.scala @@ -0,0 +1,21 @@ +import scala.quoted._ +import scala.language.experimental.macros + +class Location(val line: Int) + +object MacroCompat { + trait LocationMacro { + inline implicit def generate: Location = ${ locationImpl() } + implicit def generate: Location = macro MacroCompatScala2.locationImpl + } + + def locationImpl()(using Quotes): Expr[Location] = '{ new Location(${Expr(0)}) } +} + +object MacroCompatScala2 { + def locationImpl(c: Context): c.Tree = { + import c.universe._ + val line = Literal(Constant(c.enclosingPosition.line)) + New(c.mirror.staticClass(classOf[Location].getName()), line) + } +} diff --git a/tests/init/special/i12128/Reflect_1.scala b/tests/init/special/i12128/Reflect_1.scala new file mode 100644 index 000000000000..2c2e39de73a3 --- /dev/null +++ b/tests/init/special/i12128/Reflect_1.scala @@ -0,0 +1,30 @@ +trait Context: // Dummy scala.reflect.macros.Context + type Tree = universe.Tree + val universe: Universe + + trait Universe { + type Tree >: Null <: AnyRef with TreeApi + type Literal >: Null <: LiteralApi with TermTree + type TermTree >: Null <: TermTreeApi with Tree + + trait TermTreeApi extends TreeApi { this: TermTree => } + trait LiteralApi extends TermTreeApi { this: Literal => } + trait TreeApi extends Product { this: Tree => } + + type Constant + + type Type + + def Literal(const: Constant): Tree + def Constant(i: Int): Constant + def New(tpe: Type, arg: Tree): Tree + } + + def enclosingPosition: Position + + trait Mirror { + def staticClass(name: String): universe.Type + } + val mirror: Mirror + +class Position(val line: Int) diff --git a/tests/init/special/i12128/Test_3.scala b/tests/init/special/i12128/Test_3.scala new file mode 100644 index 000000000000..070465a7e950 --- /dev/null +++ b/tests/init/special/i12128/Test_3.scala @@ -0,0 +1 @@ +object Test extends MacroCompat.LocationMacro