diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index bce9aff02be1..885dc86a7fd4 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -3045,12 +3045,12 @@ class Typer extends Namer } } - /** If this tree is a select node `qual.name` that does not conform to `pt`, - * try to insert an implicit conversion `c` around `qual` so that - * `c(qual).name` conforms to `pt`. + /** If this tree is a select node `qual.name` (possibly applied to type variables) + * that does not conform to `pt`, try to insert an implicit conversion `c` around + * `qual` so that `c(qual).name` conforms to `pt`. */ def tryInsertImplicitOnQualifier(tree: Tree, pt: Type, locked: TypeVars)(using Context): Option[Tree] = trace(i"try insert impl on qualifier $tree $pt") { - tree match { + tree match case tree @ Select(qual, name) if name != nme.CONSTRUCTOR => val selProto = SelectionProto(name, pt, NoViewsAllowed, privateOK = false) if selProto.isMatchedBy(qual.tpe) then None @@ -3061,8 +3061,9 @@ class Typer extends Namer else Some(adapt(tree1, pt, locked)) } { (_, _) => None } + case TypeApply(fn, args) if args.forall(_.isInstanceOf[TypeVarBinder[_]]) => + tryInsertImplicitOnQualifier(fn, pt, locked) case _ => None - } } /** Given a selection `qual.name`, try to convert to an extension method diff --git a/tests/neg/i8861.scala b/tests/neg/i8861.scala index 87f1884f6155..744b49b0107b 100644 --- a/tests/neg/i8861.scala +++ b/tests/neg/i8861.scala @@ -20,7 +20,7 @@ object Test { ) def minimalFail[M](c: Container { type A = M }): M = c.visit( int = vi => vi.i : vi.A, - str = vs => vs.t : vs.A // error + str = vs => vs.t : vs.A // error // error ) def main(args: Array[String]): Unit = { diff --git a/tests/pos/i12708.scala b/tests/pos/i12708.scala new file mode 100644 index 000000000000..f8149f0732d0 --- /dev/null +++ b/tests/pos/i12708.scala @@ -0,0 +1,37 @@ +import language.implicitConversions + +trait AdditiveSemigroup[A] + +final class AdditiveSemigroupOps[A](lhs: A)(implicit as: AdditiveSemigroup[A]) { + def +(rhs: A): A = ??? + def ^(rhs: A): A = ??? +} + +trait AdditiveSemigroupSyntax { + implicit def additiveSemigroupOps[A: AdditiveSemigroup](a: A): AdditiveSemigroupOps[A] = + new AdditiveSemigroupOps(a) +} + +object syntax { + object additiveSemigroup extends AdditiveSemigroupSyntax +} + +object App { + + def main(args: Array[String]): Unit = { + import syntax.additiveSemigroup._ + + implicit def IntAlgebra[A]: AdditiveSemigroup[Map[Int, A]] = ??? + + def res[A]: Map[Int, A] = { + val a: Map[Int, A] = Map.empty + val b: Map[Int, A] = Map.empty + // Calls the operator on AdditiveSemigroupOps + a ^ b + // Calls the operator + on AdditiveSemigroupOps only in Scala 2 + // In Scala 3 tries to call `+` on Map + a + b + } + } + +} \ No newline at end of file diff --git a/tests/neg/zipped.scala b/tests/pos/zipped.scala similarity index 71% rename from tests/neg/zipped.scala rename to tests/pos/zipped.scala index c7d55da6000a..2453b880cbc3 100644 --- a/tests/neg/zipped.scala +++ b/tests/pos/zipped.scala @@ -22,17 +22,14 @@ object Test { xs.lazyZip(xs).lazyZip(xs) .map( (x: Int, y: Int, z: Int) => x + y + z ) // OK - // 4. The single parameter map does not work. + // 4. The single parameter map works through an inserted conversion xs.lazyZip(xs).lazyZip(xs) - .map( (x: (Int, Int, Int)) => x match { case (x, y, z) => x + y + z }) // error + .map( (x: (Int, Int, Int)) => x match { case (x, y, z) => x + y + z }) // now also OK - // 5. If we leave out the parameter type, we get a "Wrong number of parameters" error instead + // 5. If we leave out the parameter type, it now works as well. xs.lazyZip(xs).lazyZip(xs) - .map( x => x match { case (x, y, z) => x + y + z }) // error + .map( x => x match { case (x, y, z) => x + y + z }) // now also OK - // This means that the following works in Dotty in normal mode, since a `withFilter` - // is inserted. But it does no work under -strict. And it will not work in Scala 3.1. - // The reason is that without -strict, the code below is mapped to (1), but with -strict - // it is mapped to (5). + // This means that the following works in Dotty 3.0 as well as 3.x for ((x, y, z) <- xs.lazyZip(xs).lazyZip(xs)) yield x + y + z } \ No newline at end of file