diff --git a/compiler/src/dotty/tools/dotc/typer/Applications.scala b/compiler/src/dotty/tools/dotc/typer/Applications.scala index fc0cfb436088..f4cf358d5218 100644 --- a/compiler/src/dotty/tools/dotc/typer/Applications.scala +++ b/compiler/src/dotty/tools/dotc/typer/Applications.scala @@ -2037,7 +2037,9 @@ trait Applications extends Compatibility { def isAsGood(alt1: TermRef, tp1: Type, alt2: TermRef, tp2: Type): Boolean = trace(i"isAsGood $tp1 $tp2", overload) { tp1 match case tp1: MethodType => // (1) - tp1.paramInfos.isEmpty && tp2.isInstanceOf[LambdaType] + tp1.paramInfos.isEmpty + && tp2.isInstanceOf[LambdaType] + && !tp2.isVarArgsMethod || { if tp1.isVarArgsMethod then tp2.isVarArgsMethod diff --git a/compiler/src/dotty/tools/dotc/typer/Checking.scala b/compiler/src/dotty/tools/dotc/typer/Checking.scala index ed2b3a08a139..3053c276154c 100644 --- a/compiler/src/dotty/tools/dotc/typer/Checking.scala +++ b/compiler/src/dotty/tools/dotc/typer/Checking.scala @@ -1373,10 +1373,14 @@ trait Checking { if decl.name.is(DefaultGetterName) && ctx.reporter.errorsReported then () // do nothing; we already have reported an error that overloaded variants cannot have default arguments else if decl.is(Synthetic) then doubleDefError(other, decl) - else doubleDefError(decl, other) - if decl.hasDefaultParams && other.hasDefaultParams then - report.error(em"two or more overloaded variants of $decl have default arguments", decl.srcPos) - decl.resetFlag(HasDefaultParams) + else + doubleDefError(decl, other) + if decl.hasDefaultParams && other.hasDefaultParams then + + report.error(em"two or more overloaded variants of $decl have default arguments", decl.srcPos) + decl.resetFlag(HasDefaultParams) + + if !excludeFromDoubleDeclCheck(decl) then seen(decl.name) = decl :: seen(decl.name) diff --git a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala index 47f355aa8aea..d725efe86006 100644 --- a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala +++ b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala @@ -59,12 +59,30 @@ object RefChecks { if (haveDefaults.length > 1) { val owners = haveDefaults map (_.owner) // constructors of different classes are allowed to have defaults - if (haveDefaults.exists(x => !x.isConstructor) || owners.distinct.size < haveDefaults.size) - report.error( - em"in $clazz, multiple overloaded alternatives of ${haveDefaults.head} define default arguments${ - if owners.forall(_ == clazz) then "." - else i".\nThe members with defaults are defined in ${owners.map(_.showLocated).mkString("", " and ", ".")}"}", - clazz.srcPos) + if (haveDefaults.exists(x => !x.isConstructor) || owners.distinct.size < haveDefaults.size) { + def generatedDefaultGetters(sym: Symbol)(using Context): Set[TermName] = + val paramSyms = sym.paramSymss.flatten.filter(_.isTerm) + val defaults = paramSyms.zipWithIndex.collect { + case (p, i) if p.is(HasDefault) => + DefaultGetterName(sym.name.asTermName, i + 1) + } + defaults.toSet + + val defaults = haveDefaults.map(generatedDefaultGetters) + val hasCollision = defaults.combinations(2).exists { case List(d1, d2) => + d1.intersect(d2).nonEmpty + } + + if hasCollision then + report.error( + em"in $clazz, multiple overloaded alternatives of ${haveDefaults.head} define default arguments${ + if owners.forall(_ == clazz) then "." + else i".\nThe members with defaults are defined in ${owners.map(_.showLocated).mkString("", " and ", ".")}"}", + clazz.srcPos) + } + + + } } } diff --git a/tests/pos/i24886.scala b/tests/pos/i24886.scala new file mode 100644 index 000000000000..5a4ce77a4098 --- /dev/null +++ b/tests/pos/i24886.scala @@ -0,0 +1,17 @@ + +package i24886 + +var default: Option[String] = Some("test") +var value: String = "0" + +extension (self: String) + (using key: () => String = () => default.get) + + def int(`type`: String = "an integer"): Int = + try + self.toInt + catch _ => throw new RuntimeException(`type`) + +def int(`type`: String = "an integer"): Int = value.int(`type`) + +