diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 210104c4ab93..24f69137d3cc 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -4352,72 +4352,64 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer val allDenots = ref.denot.alternatives if pt.isExtensionApplyProto then allDenots.filter(_.symbol.is(ExtensionMethod)) else allDenots + def altRef(alt: SingleDenotation) = TermRef(ref.prefix, ref.name, alt) + val alts = altDenots.map(altRef) typr.println(i"adapt overloaded $ref with alternatives ${altDenots map (_.info)}%\n\n %") /** Search for an alternative that does not take parameters. * If there is one, return it, otherwise return the error tree. */ - def tryParameterless(alts: List[TermRef])(error: => tpd.Tree): Tree = + def tryParameterless(error: => tpd.Tree): Tree = alts.filter(_.info.isParameterless) match case alt :: Nil => readaptSimplified(tree.withType(alt)) case _ => altDenots.find(_.info.paramInfoss == ListOfNil) match - case Some(alt) => readaptSimplified(tree.withType(alt.symbol.denot.termRef)) + case Some(alt) => readaptSimplified(tree.withType(altRef(alt))) case _ => error - def altRef(alt: SingleDenotation) = TermRef(ref.prefix, ref.name, alt) - val alts = altDenots.map(altRef) - resolveOverloaded(alts, pt) match - case alt :: Nil => - readaptSimplified(tree.withType(alt)) - case Nil => - // If no alternative matches, there are still two ways to recover: - // 1. If context is an application, try to insert an apply or implicit - // 2. If context is not an application, pick a alternative that does - // not take parameters. - - def errorNoMatch = errorTree(tree, NoMatchingOverload(altDenots, pt)) - - pt match - case pt: FunOrPolyProto if pt.applyKind != ApplyKind.Using => - // insert apply or convert qualifier, but only for a regular application - tryInsertApplyOrImplicit(tree, pt, locked)(errorNoMatch) - case _ => - tryParameterless(alts)(errorNoMatch) - - case ambiAlts => - // If there are ambiguous alternatives, and: - // 1. the types aren't erroneous - // 2. the expected type is not a function type - // 3. there exist a parameterless alternative - // - // Then, pick the parameterless alternative. - // See tests/pos/i10715-scala and tests/pos/i10715-java. - - /** Constructs an "ambiguous overload" error */ - def errorAmbiguous = - val remainingDenots = altDenots.filter(denot => ambiAlts.contains(altRef(denot))) - val addendum = - if ambiAlts.exists(!_.symbol.exists) then - i"""| - | - |Note: Overloaded definitions introduced by refinements cannot be resolved""" - else "" - errorTree(tree, AmbiguousOverload(tree, remainingDenots, pt, addendum)) - end errorAmbiguous - - if tree.tpe.isErroneous || pt.isErroneous then - tree.withType(UnspecifiedErrorType) - else - pt match - case _: FunProto => - errorAmbiguous - case _ => - tryParameterless(alts)(errorAmbiguous) - - end match + case alt :: Nil => + readaptSimplified(tree.withType(alt)) + case Nil => + // If no alternative matches, there are still two ways to recover: + // 1. If context is an application, try to insert an apply or implicit + // 2. If context is not an application, pick an alternative that does + // not take parameters. + def errorNoMatch = errorTree(tree, NoMatchingOverload(altDenots, pt)) + + pt match + case pt: FunOrPolyProto if pt.applyKind != ApplyKind.Using => + // insert apply or convert qualifier, but only for a regular application + tryInsertApplyOrImplicit(tree, pt, locked)(errorNoMatch) + case _ => + tryParameterless(errorNoMatch) + case ambiAlts => + // If there are ambiguous alternatives, and: + // 1. the types aren't erroneous + // 2. the expected type is not a function type + // 3. there exists a parameterless alternative + // + // Then, pick the parameterless alternative. See tests/pos/i10715-* + + /** Constructs an "ambiguous overload" error */ + def errorAmbiguous = + val remainingDenots = altDenots.filter(denot => ambiAlts.contains(altRef(denot))) + val addendum = + if ambiAlts.exists(!_.symbol.exists) then + i"""| + | + |Note: Overloaded definitions introduced by refinements cannot be resolved""" + else "" + errorTree(tree, AmbiguousOverload(tree, remainingDenots, pt, addendum)) + + pt match + case pt if tree.tpe.isErroneous || pt.isErroneous => + tree.withType(UnspecifiedErrorType) + case _: FunProto => + errorAmbiguous + case _ => + tryParameterless(errorAmbiguous) end adaptOverloaded def adaptToArgs(wtp: Type, pt: FunProto): Tree = wtp match { diff --git a/tests/pos/i24631/TestJava.java b/tests/pos/i24631/TestJava.java new file mode 100644 index 000000000000..1a869cbdd6db --- /dev/null +++ b/tests/pos/i24631/TestJava.java @@ -0,0 +1,12 @@ +package example; + +public abstract class TestJava { + public abstract T create(String foo); + + // Note that this is the method that's called from Scala code + public T create() { return create(""); } + + public static class Concrete extends TestJava { + @Override public String create(String foo) { return foo; } + } +} diff --git a/tests/pos/i24631/test.scala b/tests/pos/i24631/test.scala new file mode 100644 index 000000000000..c54eb7f98c69 --- /dev/null +++ b/tests/pos/i24631/test.scala @@ -0,0 +1,2 @@ +val s = new example.TestJava.Concrete().create +val s2: String = s diff --git a/tests/pos/i24631b.scala b/tests/pos/i24631b.scala new file mode 100644 index 000000000000..9e408729c6c3 --- /dev/null +++ b/tests/pos/i24631b.scala @@ -0,0 +1,11 @@ +//> using options -source:3.0-migration + +abstract class C[A]: + def create(s: String): A + def create(): A = create("") + +class D extends C[String]: + def create(s: String): String = s + +val s = D().create +val s2: String = s