Skip to content

Commit 833f5b9

Browse files
authored
Merge pull request #12592 from dotty-staging/fix-12128
Fix #12128: Add test
2 parents 8df379e + 7a0ca56 commit 833f5b9

File tree

10 files changed

+89
-11
lines changed

10 files changed

+89
-11
lines changed

compiler/src/dotty/tools/dotc/core/NamerOps.scala

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,14 @@ import ast.untpd
1111
/** Operations that are shared between Namer and TreeUnpickler */
1212
object NamerOps:
1313

14-
/** The given type, unless `sym` is a constructor, in which case the
15-
* type of the constructed instance is returned
14+
/** The type of the constructed instance is returned
15+
*
16+
* @param ctor the constructor
1617
*/
17-
def effectiveResultType(sym: Symbol, paramss: List[List[Symbol]], givenTp: Type)(using Context): Type =
18-
if sym.name == nme.CONSTRUCTOR then
19-
paramss match
20-
case TypeSymbols(tparams) :: _ => sym.owner.typeRef.appliedTo(tparams.map(_.typeRef))
21-
case _ => sym.owner.typeRef
22-
else givenTp
18+
def effectiveResultType(ctor: Symbol, paramss: List[List[Symbol]])(using Context): Type =
19+
paramss match
20+
case TypeSymbols(tparams) :: _ => ctor.owner.typeRef.appliedTo(tparams.map(_.typeRef))
21+
case _ => ctor.owner.typeRef
2322

2423
/** if isConstructor, make sure it has one leading non-implicit parameter list */
2524
def normalizeIfConstructor(paramss: List[List[Symbol]], isConstructor: Boolean)(using Context): List[List[Symbol]] =

compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,7 @@ class TreePickler(pickler: TastyPickler) {
332332

333333
def pickleDef(tag: Int, mdef: MemberDef, tpt: Tree, rhs: Tree = EmptyTree, pickleParams: => Unit = ())(using Context): Unit = {
334334
val sym = mdef.symbol
335+
335336
assert(symRefs(sym) == NoAddr, sym)
336337
registerDef(sym)
337338
writeByte(tag)

compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -831,7 +831,11 @@ class TreeUnpickler(reader: TastyReader,
831831
val tpt = readTpt()(using localCtx)
832832
val paramss = normalizeIfConstructor(
833833
paramDefss.nestedMap(_.symbol), name == nme.CONSTRUCTOR)
834-
val resType = effectiveResultType(sym, paramss, tpt.tpe)
834+
val resType =
835+
if name == nme.CONSTRUCTOR then
836+
effectiveResultType(sym, paramss)
837+
else
838+
tpt.tpe
835839
sym.info = methodType(paramss, resType)
836840
DefDef(paramDefss, tpt)
837841
case VALDEF =>

compiler/src/dotty/tools/dotc/transform/TreeChecker.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ class TreeChecker extends Phase with SymTransformer {
9191
// until erasure, see the comment above `Compiler#phases`.
9292
if (ctx.phaseId <= erasurePhase.id) {
9393
val initial = symd.initial
94-
assert(symd.signature == initial.signature,
94+
assert(symd == initial || symd.signature == initial.signature,
9595
i"""Signature of ${sym.showLocated} changed at phase ${ctx.base.fusedContaining(ctx.phase.prev)}
9696
|Initial info: ${initial.info}
9797
|Initial sig : ${initial.signature}

compiler/src/dotty/tools/dotc/transform/init/Semantic.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -830,6 +830,7 @@ class Semantic {
830830

831831
// follow constructor
832832
if cls.hasSource then
833+
printer.println("init super class " + cls.show)
833834
val res2 = thisV.call(ctor, superType = NoType, source)(using ctx, trace.add(source))
834835
errorBuffer ++= res2.errors
835836

compiler/src/dotty/tools/dotc/typer/Namer.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1680,7 +1680,7 @@ class Namer { typer: Typer =>
16801680
if (isConstructor) {
16811681
// set result type tree to unit, but take the current class as result type of the symbol
16821682
typedAheadType(ddef.tpt, defn.UnitType)
1683-
wrapMethType(effectiveResultType(sym, paramSymss, NoType))
1683+
wrapMethType(effectiveResultType(sym, paramSymss))
16841684
}
16851685
else valOrDefDefSig(ddef, sym, paramSymss, wrapMethType)
16861686
}

compiler/test/dotty/tools/dotc/CompilationTests.scala

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,27 @@ class CompilationTests {
325325
compileFilesInDir("tests/init/neg", options).checkExpectedErrors()
326326
compileFilesInDir("tests/init/pos", options).checkCompile()
327327
compileFilesInDir("tests/init/crash", options.without("-Xfatal-warnings")).checkCompile()
328+
329+
// The regression test for i12128 has some atypical classpath requirements.
330+
// The test consists of three files: (a) Reflect_1 (b) Macro_2 (c) Test_3
331+
// which must be compiled separately. In addition:
332+
// - the output from (a) must be on the classpath while compiling (b)
333+
// - the output from (b) must be on the classpath while compiling (c)
334+
// - the output from (a) _must not_ be on the classpath while compiling (c)
335+
locally {
336+
val i12128Group = TestGroup("checkInit/i12128")
337+
val i12128Options = options.without("-Xfatal-warnings")
338+
val outDir1 = defaultOutputDir + i12128Group + "/Reflect_1/i12128/Reflect_1"
339+
val outDir2 = defaultOutputDir + i12128Group + "/Macro_2/i12128/Macro_2"
340+
341+
val tests = List(
342+
compileFile("tests/init/special/i12128/Reflect_1.scala", i12128Options)(i12128Group),
343+
compileFile("tests/init/special/i12128/Macro_2.scala", i12128Options.withClasspath(outDir1))(i12128Group),
344+
compileFile("tests/init/special/i12128/Test_3.scala", options.withClasspath(outDir2))(i12128Group)
345+
).map(_.keepOutput.checkCompile())
346+
347+
tests.foreach(_.delete())
348+
}
328349
}
329350
}
330351

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import scala.quoted._
2+
import scala.language.experimental.macros
3+
4+
class Location(val line: Int)
5+
6+
object MacroCompat {
7+
trait LocationMacro {
8+
inline implicit def generate: Location = ${ locationImpl() }
9+
implicit def generate: Location = macro MacroCompatScala2.locationImpl
10+
}
11+
12+
def locationImpl()(using Quotes): Expr[Location] = '{ new Location(${Expr(0)}) }
13+
}
14+
15+
object MacroCompatScala2 {
16+
def locationImpl(c: Context): c.Tree = {
17+
import c.universe._
18+
val line = Literal(Constant(c.enclosingPosition.line))
19+
New(c.mirror.staticClass(classOf[Location].getName()), line)
20+
}
21+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
trait Context: // Dummy scala.reflect.macros.Context
2+
type Tree = universe.Tree
3+
val universe: Universe
4+
5+
trait Universe {
6+
type Tree >: Null <: AnyRef with TreeApi
7+
type Literal >: Null <: LiteralApi with TermTree
8+
type TermTree >: Null <: TermTreeApi with Tree
9+
10+
trait TermTreeApi extends TreeApi { this: TermTree => }
11+
trait LiteralApi extends TermTreeApi { this: Literal => }
12+
trait TreeApi extends Product { this: Tree => }
13+
14+
type Constant
15+
16+
type Type
17+
18+
def Literal(const: Constant): Tree
19+
def Constant(i: Int): Constant
20+
def New(tpe: Type, arg: Tree): Tree
21+
}
22+
23+
def enclosingPosition: Position
24+
25+
trait Mirror {
26+
def staticClass(name: String): universe.Type
27+
}
28+
val mirror: Mirror
29+
30+
class Position(val line: Int)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
object Test extends MacroCompat.LocationMacro

0 commit comments

Comments
 (0)