Skip to content

Commit 14ffb35

Browse files
committed
Insert conversions also on selections wrapped in type applications
In i12708.scala, the problematic function was a selection `qual.m[tvs]` that was already applied to type variables. In that case we need to backtrack, forget the type variables and try to insert a conversion or extension method on `qual`. Fixes #12708
1 parent 06df92b commit 14ffb35

File tree

2 files changed

+43
-5
lines changed

2 files changed

+43
-5
lines changed

compiler/src/dotty/tools/dotc/typer/Typer.scala

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3045,12 +3045,12 @@ class Typer extends Namer
30453045
}
30463046
}
30473047

3048-
/** If this tree is a select node `qual.name` that does not conform to `pt`,
3049-
* try to insert an implicit conversion `c` around `qual` so that
3050-
* `c(qual).name` conforms to `pt`.
3048+
/** If this tree is a select node `qual.name` (possibly applied to type variables)
3049+
* that does not conform to `pt`, try to insert an implicit conversion `c` around
3050+
* `qual` so that `c(qual).name` conforms to `pt`.
30513051
*/
30523052
def tryInsertImplicitOnQualifier(tree: Tree, pt: Type, locked: TypeVars)(using Context): Option[Tree] = trace(i"try insert impl on qualifier $tree $pt") {
3053-
tree match {
3053+
tree match
30543054
case tree @ Select(qual, name) if name != nme.CONSTRUCTOR =>
30553055
val selProto = SelectionProto(name, pt, NoViewsAllowed, privateOK = false)
30563056
if selProto.isMatchedBy(qual.tpe) then None
@@ -3061,8 +3061,9 @@ class Typer extends Namer
30613061
else Some(adapt(tree1, pt, locked))
30623062
} { (_, _) => None
30633063
}
3064+
case TypeApply(fn, args) if args.forall(_.isInstanceOf[TypeVarBinder[_]]) =>
3065+
tryInsertImplicitOnQualifier(fn, pt, locked)
30643066
case _ => None
3065-
}
30663067
}
30673068

30683069
/** Given a selection `qual.name`, try to convert to an extension method

tests/pos/i12708.scala

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import language.implicitConversions
2+
3+
trait AdditiveSemigroup[A]
4+
5+
final class AdditiveSemigroupOps[A](lhs: A)(implicit as: AdditiveSemigroup[A]) {
6+
def +(rhs: A): A = ???
7+
def ^(rhs: A): A = ???
8+
}
9+
10+
trait AdditiveSemigroupSyntax {
11+
implicit def additiveSemigroupOps[A: AdditiveSemigroup](a: A): AdditiveSemigroupOps[A] =
12+
new AdditiveSemigroupOps(a)
13+
}
14+
15+
object syntax {
16+
object additiveSemigroup extends AdditiveSemigroupSyntax
17+
}
18+
19+
object App {
20+
21+
def main(args: Array[String]): Unit = {
22+
import syntax.additiveSemigroup._
23+
24+
implicit def IntAlgebra[A]: AdditiveSemigroup[Map[Int, A]] = ???
25+
26+
def res[A]: Map[Int, A] = {
27+
val a: Map[Int, A] = Map.empty
28+
val b: Map[Int, A] = Map.empty
29+
// Calls the operator on AdditiveSemigroupOps
30+
a ^ b
31+
// Calls the operator + on AdditiveSemigroupOps only in Scala 2
32+
// In Scala 3 tries to call `+` on Map
33+
a + b
34+
}
35+
}
36+
37+
}

0 commit comments

Comments
 (0)