diff --git a/compiler/src/dotty/tools/dotc/ast/Desugar.scala b/compiler/src/dotty/tools/dotc/ast/Desugar.scala index 47ad30e0ea5b..644b7620ae06 100644 --- a/compiler/src/dotty/tools/dotc/ast/Desugar.scala +++ b/compiler/src/dotty/tools/dotc/ast/Desugar.scala @@ -149,7 +149,7 @@ object desugar { * def f$default$1[T] = 1 * def f$default$2[T](x: Int) = x + "m" */ - def defDef(meth: DefDef, isPrimaryConstructor: Boolean = false)(implicit ctx: Context): Tree = { + private def defDef(meth: DefDef, isPrimaryConstructor: Boolean = false)(implicit ctx: Context): Tree = { val DefDef(name, tparams, vparamss, tpt, rhs) = meth val mods = meth.mods val epbuf = new ListBuffer[ValDef] @@ -254,11 +254,17 @@ object desugar { .withFlags((mods.flags & AccessFlags).toCommonFlags) .withMods(Nil) - val (constr1, defaultGetters) = defDef(constr0, isPrimaryConstructor = true) match { - case meth: DefDef => (meth, Nil) - case Thicket((meth: DefDef) :: defaults) => (meth, defaults) + var defaultGetters: List[Tree] = Nil + + def decompose(ddef: Tree): DefDef = ddef match { + case meth: DefDef => meth + case Thicket((meth: DefDef) :: defaults) => + defaultGetters = defaults + meth } + val constr1 = decompose(defDef(constr0, isPrimaryConstructor = true)) + // The original type and value parameters in the constructor already have the flags // needed to be type members (i.e. param, and possibly also private and local unless // prefixed by type or val). `tparams` and `vparamss` are the type parameters that @@ -299,9 +305,11 @@ object desugar { // to auxiliary constructors val normalizedBody = impl.body map { case ddef: DefDef if ddef.name.isConstructorName => - addEvidenceParams( - cpy.DefDef(ddef)(tparams = constrTparams), - evidenceParams(constr1).map(toDefParam)) + decompose( + defDef( + addEvidenceParams( + cpy.DefDef(ddef)(tparams = constrTparams), + evidenceParams(constr1).map(toDefParam)))) case stat => stat } @@ -680,7 +688,9 @@ object desugar { def defTree(tree: Tree)(implicit ctx: Context): Tree = tree match { case tree: ValDef => valDef(tree) case tree: TypeDef => if (tree.isClassDef) classDef(tree) else tree - case tree: DefDef => defDef(tree) + case tree: DefDef => + if (tree.name.isConstructorName) tree // was already handled by enclosing classDef + else defDef(tree) case tree: ModuleDef => moduleDef(tree) case tree: PatDef => patDef(tree) } diff --git a/compiler/src/dotty/tools/dotc/typer/Checking.scala b/compiler/src/dotty/tools/dotc/typer/Checking.scala index 6ee57d5cd220..3a143f826ea4 100644 --- a/compiler/src/dotty/tools/dotc/typer/Checking.scala +++ b/compiler/src/dotty/tools/dotc/typer/Checking.scala @@ -625,7 +625,7 @@ trait Checking { else doubleDefError(decl, other) } if ((decl is HasDefaultParams) && (other is HasDefaultParams)) { - ctx.error(em"two or more overloaded variants of $decl have default arguments") + ctx.error(em"two or more overloaded variants of $decl have default arguments", decl.pos) decl resetFlag HasDefaultParams } } diff --git a/tests/neg/i3171.scala b/tests/neg/i3171.scala new file mode 100644 index 000000000000..3034e020d61c --- /dev/null +++ b/tests/neg/i3171.scala @@ -0,0 +1,10 @@ +object Test { + class C(x: Int = 1, y: Int) { + def this(x: Int = 1)(y: String) = // error: two or more overloaded methods have default getters + this(x, y.toInt) + } + + def test: Unit = { + new C()("1") // error: missing argument + } +} diff --git a/tests/pos/i3171.scala b/tests/pos/i3171.scala new file mode 100644 index 000000000000..fbc7d9700a35 --- /dev/null +++ b/tests/pos/i3171.scala @@ -0,0 +1,10 @@ +object Test { + class C(x: Int, y: Int) { + def this(x: Int = 1)(y: String) = + this(x, y.toInt) + } + + def test: Unit = { + new C()("1") + } +}