Skip to content

Commit 8b4509d

Browse files
authored
Merge pull request #6953 from dotty-staging/fix-#6914
Fix #6914: Improve type inference for implicit Conversions
2 parents 4f071a0 + 4cb4f4c commit 8b4509d

File tree

2 files changed

+63
-25
lines changed

2 files changed

+63
-25
lines changed

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

Lines changed: 34 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1359,31 +1359,40 @@ trait Implicits { self: Typer =>
13591359
//println(i"search implicits $pt / ${eligible.map(_.ref)}")
13601360

13611361
/** Try to typecheck an implicit reference */
1362-
def typedImplicit(cand: Candidate, contextual: Boolean)(implicit ctx: Context): SearchResult =
1363-
trace(i"typed implicit ${cand.ref}, pt = $pt, implicitsEnabled == ${ctx.mode is ImplicitsEnabled}", implicits, show = true) {
1364-
record("typedImplicit")
1365-
val ref = cand.ref
1366-
val generated: Tree = tpd.ref(ref).withSpan(span.startPos)
1367-
val locked = ctx.typerState.ownedVars
1368-
val adapted =
1369-
if (argument.isEmpty)
1370-
adapt(generated, pt.widenExpr, locked)
1371-
else {
1372-
val untpdGenerated = untpd.TypedSplice(generated)
1373-
def tryConversion(implicit ctx: Context) =
1374-
typed(
1375-
untpd.Apply(untpdGenerated, untpd.TypedSplice(argument) :: Nil),
1376-
pt, locked)
1377-
if (cand.isExtension) {
1378-
val SelectionProto(name: TermName, mbrType, _, _) = pt
1379-
val result = extMethodApply(untpd.Select(untpdGenerated, name), argument, mbrType)
1380-
if (!ctx.reporter.hasErrors && cand.isConversion) {
1381-
val testCtx = ctx.fresh.setExploreTyperState()
1382-
tryConversion(testCtx)
1383-
if (testCtx.reporter.hasErrors)
1384-
ctx.error(em"ambiguous implicit: $generated is eligible both as an implicit conversion and as an extension method container")
1385-
}
1386-
result
1362+
def typedImplicit(cand: Candidate, contextual: Boolean)(implicit ctx: Context): SearchResult = trace(i"typed implicit ${cand.ref}, pt = $pt, implicitsEnabled == ${ctx.mode is ImplicitsEnabled}", implicits, show = true) {
1363+
record("typedImplicit")
1364+
val ref = cand.ref
1365+
val generated: Tree = tpd.ref(ref).withSpan(span.startPos)
1366+
val locked = ctx.typerState.ownedVars
1367+
val adapted =
1368+
if (argument.isEmpty)
1369+
adapt(generated, pt.widenExpr, locked)
1370+
else {
1371+
def untpdGenerated = untpd.TypedSplice(generated)
1372+
def tryConversion(implicit ctx: Context) = {
1373+
val untpdConv =
1374+
if (ref.symbol.is(Given))
1375+
untpd.Select(
1376+
untpd.TypedSplice(
1377+
adapt(generated,
1378+
defn.ConversionClass.typeRef.appliedTo(argument.tpe.widen, pt),
1379+
locked)),
1380+
nme.apply)
1381+
else untpdGenerated
1382+
typed(
1383+
untpd.Apply(untpdConv, untpd.TypedSplice(argument) :: Nil),
1384+
pt, locked)
1385+
}
1386+
if (cand.isExtension) {
1387+
val SelectionProto(name: TermName, mbrType, _, _) = pt
1388+
val result = extMethodApply(untpd.Select(untpdGenerated, name), argument, mbrType)
1389+
if (!ctx.reporter.hasErrors && cand.isConversion) {
1390+
val testCtx = ctx.fresh.setExploreTyperState()
1391+
tryConversion(testCtx)
1392+
if (testCtx.reporter.hasErrors)
1393+
ctx.error(em"ambiguous implicit: $generated is eligible both as an implicit conversion and as an extension method container")
1394+
}
1395+
result
13871396
}
13881397
else tryConversion
13891398
}

tests/pos/i6914.scala

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
trait Expr[T]
2+
trait Liftable[T]
3+
4+
object test1 {
5+
class ToExpr[T] given Liftable[T] extends Conversion[T, Expr[T]] {
6+
def apply(x: T): Expr[T] = ???
7+
}
8+
given toExpr[T] as ToExpr[T] given Liftable[T]
9+
10+
given as Liftable[Int] = ???
11+
given as Liftable[String] = ???
12+
13+
def x = the[ToExpr[String]]
14+
def y = the[Conversion[String, Expr[String]]]
15+
16+
def a: Expr[String] = "abc"
17+
}
18+
19+
object test2 {
20+
21+
given autoToExpr[T] as Conversion[T, Expr[T]] given Liftable[T] {
22+
def apply(x: T): Expr[T] = ???
23+
}
24+
25+
given as Liftable[Int] = ???
26+
given as Liftable[String] = ???
27+
28+
def a: Expr[String] = "abc"
29+
}

0 commit comments

Comments
 (0)