diff --git a/compiler/src/dotty/tools/dotc/transform/ElimRepeated.scala b/compiler/src/dotty/tools/dotc/transform/ElimRepeated.scala index ae2fc578728f..42ffa50d7129 100644 --- a/compiler/src/dotty/tools/dotc/transform/ElimRepeated.scala +++ b/compiler/src/dotty/tools/dotc/transform/ElimRepeated.scala @@ -13,6 +13,7 @@ import Decorators.* import Denotations.*, SymDenotations.* import DenotTransformers.* import NullOpsDecorator.* +import util.Spans.Span object ElimRepeated { val name: String = "elimRepeated" @@ -183,7 +184,7 @@ class ElimRepeated extends MiniPhase with InfoTransformer { thisPhase => .get .symbol.asTerm // Generate the method - val forwarderDef = DefDef(forwarderSym, prefss => { + val forwarderDef = DefDef(forwarderSym, prefss => val init :+ (last :+ vararg) = prefss: @unchecked // Can't call `.argTypes` here because the underlying array type is of the // form `Array[? <: SomeType]`, so we need `.argInfos` to get the `TypeBounds`. @@ -191,7 +192,8 @@ class ElimRepeated extends MiniPhase with InfoTransformer { thisPhase => ref(sym.termRef) .appliedToArgss(init) .appliedToTermArgs(last :+ wrapArray(vararg, elemtp)) - }) + .withSpan(Span(tree.span.start)) + ).withSpan(tree.span.toSynthetic) Thicket(tree, forwarderDef) else tree diff --git a/compiler/src/dotty/tools/dotc/transform/ForwardDepChecks.scala b/compiler/src/dotty/tools/dotc/transform/ForwardDepChecks.scala index afe78ce1296d..043ec41d6d56 100644 --- a/compiler/src/dotty/tools/dotc/transform/ForwardDepChecks.scala +++ b/compiler/src/dotty/tools/dotc/transform/ForwardDepChecks.scala @@ -122,7 +122,8 @@ class ForwardDepChecks extends MiniPhase: override def transformApply(tree: Apply)(using Context): Apply = if (isSelfConstrCall(tree)) assert(ctx.owner.isConstructor) - checkSelfConstructorCall() + if currentLevel.isInstanceOf[LevelInfo] then // ElimRepeated can introduce RHS of ctor which is not a block + checkSelfConstructorCall() tree override def transformNew(tree: New)(using Context): New = { diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index c57ced36f2d8..bb5f148cef92 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -3115,10 +3115,15 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer def checkThisConstrCall(tree: Tree): Unit = tree match case app: Apply if untpd.isSelfConstrCall(app) => if !sym.is(Synthetic) - && sym.span.exists && app.symbol.span.exists && sym.span.start <= app.symbol.span.start + && sym.span.exists + && app.symbol.span.exists + && sym.span.start <= app.symbol.span.start + && tree.span.exists && !tree.span.isSynthetic then report.error("secondary constructor must call a preceding constructor", app.srcPos) - case Block(call :: _, _) => checkThisConstrCall(call) + case Block(call :: _, expr) => + checkThisConstrCall(call) + checkThisConstrCall(expr) case _ => checkThisConstrCall(rhs1) diff --git a/tests/neg/i24249.scala b/tests/neg/i24249.scala new file mode 100644 index 000000000000..2bac54550d2e --- /dev/null +++ b/tests/neg/i24249.scala @@ -0,0 +1,9 @@ + + +class C(i: Int) { + def this(s: String) = this(j = s.toInt, i = 27) // error + + def this(i: Int, j: Int) = this(i + j) + + def c = 42 * i +} diff --git a/tests/pos/i24249.scala b/tests/pos/i24249.scala new file mode 100644 index 000000000000..1918136889ea --- /dev/null +++ b/tests/pos/i24249.scala @@ -0,0 +1,5 @@ + +import annotation.* + +class Foo: + @varargs def this(x: Int*) = this()