diff --git a/compiler/src/dotty/tools/dotc/typer/Applications.scala b/compiler/src/dotty/tools/dotc/typer/Applications.scala index b7cabbebee71..e11afe261458 100644 --- a/compiler/src/dotty/tools/dotc/typer/Applications.scala +++ b/compiler/src/dotty/tools/dotc/typer/Applications.scala @@ -1935,11 +1935,19 @@ trait Applications extends Compatibility { val ptypes = tp.paramInfos val numParams = ptypes.length def isVarArgs = ptypes.nonEmpty && ptypes.last.isRepeatedParam - def hasDefault = alt.symbol.hasDefaultParams - if (numParams == numArgs) true - else if (numParams < numArgs) isVarArgs - else if (numParams > numArgs + 1) hasDefault - else isVarArgs || hasDefault + def numDefaultParams = + if alt.symbol.hasDefaultParams then + trimParamss(tp, alt.symbol.rawParamss) match + case params :: _ => params.count(_.is(HasDefault)) + case _ => 0 + else 0 + if numParams < numArgs then isVarArgs + else if numParams == numArgs then true + else + val numNecessaryArgs = numParams - numDefaultParams + if numNecessaryArgs <= numArgs then true + else if numNecessaryArgs == numArgs + 1 then isVarArgs + else false case _ => numArgs == 0 } @@ -2080,6 +2088,14 @@ trait Applications extends Compatibility { } end resolveOverloaded1 + /** The largest suffix of `paramss` that has the same first parameter name as `t` */ + def trimParamss(t: Type, paramss: List[List[Symbol]])(using Context): List[List[Symbol]] = t match + case MethodType(Nil) => trimParamss(t.resultType, paramss) + case t: MethodOrPoly => + val firstParamName = t.paramNames.head + paramss.dropWhile(_.head.name != firstParamName) + case _ => Nil + /** Resolve overloading by mapping to a different problem where each alternative's * type is mapped with `f`, alternatives with non-existing types are dropped, and the * expected type is `pt`. Map the results back to the original alternatives. @@ -2089,13 +2105,7 @@ trait Applications extends Compatibility { val t = f(alt) if t.exists then val mappedSym = alt.symbol.asTerm.copy(info = t) - mappedSym.rawParamss = alt.symbol.rawParamss - // we need rawParamss to find parameters with default arguments, - // but we do not need to be precise right now, since this is just a pre-test before - // we look up default getters. If at some point we extract default arguments from the - // parameter symbols themselves, we have to find the right parameter by name, not position. - // That means it's OK to copy parameters wholesale rather than tailoring them to always - // correspond to the type transformation. + mappedSym.rawParamss = trimParamss(t, alt.symbol.rawParamss) Some((TermRef(NoPrefix, mappedSym), alt)) else None diff --git a/tests/neg/i15898.scala b/tests/neg/i15898.scala new file mode 100644 index 000000000000..374fc49600eb --- /dev/null +++ b/tests/neg/i15898.scala @@ -0,0 +1,22 @@ +object O { + class AC(code: => Unit) { + def apply() = code + + def this(code: => Unit, key: Int = 1, modifiers: Int = 0) = { + this(code) + } + } + + class Doc { + def method: Boolean = true + } + + val doc = new Doc + + val ac = new AC(doc.method) // error + + def foo[T](code: => Unit): Unit = () + def foo[T](code: => Unit, key: Int = 1, modifiers: Int = 0): Unit = foo(code) + foo(doc.method) // error + foo[Int](doc.method) // error +} \ No newline at end of file diff --git a/tests/pending/pos/i15915.scala b/tests/pending/pos/i15915.scala new file mode 100644 index 000000000000..7c484b242cc7 --- /dev/null +++ b/tests/pending/pos/i15915.scala @@ -0,0 +1,24 @@ +class _Monoid[A] +object _Monoid { + implicit val Monoid: _Monoid[Int] = new _Monoid[Int] +} + +class Lifecycle[A] +object Lifecycle { + + implicit def monoidForLifecycle[Monoid[_], A]( + implicit + monoidType: GetMonoidType[Monoid], + monoidA: Monoid[A] + ): Monoid[Lifecycle[A]] = new _Monoid().asInstanceOf[Monoid[Lifecycle[A]]] + +} + +sealed class GetMonoidType[C[_]] +object GetMonoidType { + implicit val getMonoid: GetMonoidType[_Monoid] = new GetMonoidType[_Monoid] +} + +object App extends App { + println(implicitly[_Monoid[Lifecycle[Int]]]) +} \ No newline at end of file diff --git a/tests/pending/pos/i15926.scala b/tests/pending/pos/i15926.scala new file mode 100644 index 000000000000..44faf17ffd54 --- /dev/null +++ b/tests/pending/pos/i15926.scala @@ -0,0 +1,31 @@ +//@main def main(): Unit = +// println(summon[Sum[Minus[Succ[Zero]], Minus[Succ[Zero]]] =:= Minus[Succ[Succ[Zero]]]]) + +sealed trait IntT +sealed trait NatT extends IntT +final case class Zero() extends NatT +final case class Succ[+N <: NatT](n: N) extends NatT +final case class Minus[+N <: Succ[NatT]](n: N) extends IntT + +type NatSum[X <: NatT, Y <: NatT] <: NatT = Y match + case Zero => X + case Succ[y] => NatSum[Succ[X], y] + +type NatDif[X <: NatT, Y <: NatT] <: IntT = Y match + case Zero => X + case Succ[y] => X match + case Zero => Minus[Y] + case Succ[x] => NatDif[x, y] + +type Sum[X <: IntT, Y <: IntT] <: IntT = Y match + case Zero => X + case Minus[y] => X match + case Minus[x] => Minus[NatSum[x, y]] + case _ => NatDif[X, y] + case _ => X match + case Minus[x] => NatDif[Y, x] + case _ => NatSum[X, Y] + +def test = + val x: Sum[Minus[Succ[Zero]], Minus[Succ[Zero]]] = ??? + val y = x diff --git a/tests/pending/run/i15893.scala b/tests/pending/run/i15893.scala new file mode 100644 index 000000000000..dedec2138f2a --- /dev/null +++ b/tests/pending/run/i15893.scala @@ -0,0 +1,65 @@ +sealed trait NatT +case class Zero() extends NatT +case class Succ[+N <: NatT](n: N) extends NatT + +type Mod2[N <: NatT] <: NatT = N match + case Zero => Zero + case Succ[Zero] => Succ[Zero] + case Succ[Succ[predPredN]] => Mod2[predPredN] + + +def mod2(n: NatT): NatT = n match + case Zero() => Zero() + case Succ(Zero()) => Succ(Zero()) + case Succ(Succ(predPredN)) => mod2(predPredN) + +/* +inline def inlineMod2(inline n: NatT): NatT = inline n match + case Zero() => Zero() + case Succ(Zero()) => Succ(Zero()) + case Succ(Succ(predPredN)) => inlineMod2(predPredN) + +transparent inline def transparentInlineMod2(inline n: NatT): NatT = inline n match + case Zero() => Zero() + case Succ(Zero()) => Succ(Zero()) + case Succ(Succ(predPredN)) => transparentInlineMod2(predPredN) +*/ +def dependentlyTypedMod2[N <: NatT](n: N): Mod2[N] = n match // exhaustivity warning; unexpected + case Zero(): Zero => Zero() + case Succ(Zero()): Succ[Zero] => Succ(Zero()) + case Succ(Succ(predPredN)): Succ[Succ[_]] => dependentlyTypedMod2(predPredN) +/* +inline def inlineDependentlyTypedMod2[N <: NatT](inline n: N): Mod2[N] = inline n match + case Zero(): Zero => Zero() + case Succ(Zero()): Succ[Zero] => Succ(Zero()) + case Succ(Succ(predPredN)): Succ[Succ[_]] => inlineDependentlyTypedMod2(predPredN) + +transparent inline def transparentInlineDependentlyTypedMod2[N <: NatT](inline n: N): Mod2[N] = inline n match + case Zero(): Zero => Zero() + case Succ(Zero()): Succ[Zero] => Succ(Zero()) + case Succ(Succ(predPredN)): Succ[Succ[_]] => transparentInlineDependentlyTypedMod2(predPredN) + +def foo(n: NatT): NatT = mod2(n) match + case Succ(Zero()) => Zero() + case _ => n + +inline def inlineFoo(inline n: NatT): NatT = inline inlineMod2(n) match + case Succ(Zero()) => Zero() + case _ => n + +inline def transparentInlineFoo(inline n: NatT): NatT = inline transparentInlineMod2(n) match + case Succ(Zero()) => Zero() + case _ => n +*/ +@main def main(): Unit = +/* + println(mod2(Succ(Succ(Succ(Zero()))))) // prints Succ(Zero()), as expected + println(foo(Succ(Succ(Succ(Zero()))))) // prints Zero(), as expected + println(inlineMod2(Succ(Succ(Succ(Zero()))))) // prints Succ(Zero()), as expected + println(inlineFoo(Succ(Succ(Succ(Zero()))))) // prints Succ(Succ(Succ(Zero()))); unexpected + println(transparentInlineMod2(Succ(Succ(Succ(Zero()))))) // prints Succ(Zero()), as expected + println(transparentInlineFoo(Succ(Succ(Succ(Zero()))))) // prints Zero(), as expected +*/ + println(dependentlyTypedMod2(Succ(Succ(Succ(Zero()))))) // runtime error; unexpected +// println(inlineDependentlyTypedMod2(Succ(Succ(Succ(Zero()))))) // doesn't compile; unexpected +// println(transparentInlineDependentlyTypedMod2(Succ(Succ(Succ(Zero()))))) // doesn't compile; unexpected diff --git a/tests/pos/i15898.scala b/tests/pos/i15898.scala new file mode 100644 index 000000000000..31725bf1667a --- /dev/null +++ b/tests/pos/i15898.scala @@ -0,0 +1,22 @@ +object O { + class AC(code: => Unit) { + def apply() = code + + def this(code: => Unit, key: Int, modifiers: Int = 0) = { + this(code) + } + } + + class Doc { + def method: Boolean = true + } + + val doc = new Doc + + val ac = new AC(doc.method) + + def foo[T](code: => Unit): Unit = () + def foo[T](code: => Unit, key: Int, modifiers: Int = 0): Unit = foo(code) + foo(doc.method) + foo[Int](doc.method) +} \ No newline at end of file