Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 34 additions & 25 deletions compiler/src/dotty/tools/dotc/typer/Implicits.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1359,31 +1359,40 @@ trait Implicits { self: Typer =>
//println(i"search implicits $pt / ${eligible.map(_.ref)}")

/** Try to typecheck an implicit reference */
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) {
record("typedImplicit")
val ref = cand.ref
val generated: Tree = tpd.ref(ref).withSpan(span.startPos)
val locked = ctx.typerState.ownedVars
val adapted =
if (argument.isEmpty)
adapt(generated, pt.widenExpr, locked)
else {
val untpdGenerated = untpd.TypedSplice(generated)
def tryConversion(implicit ctx: Context) =
typed(
untpd.Apply(untpdGenerated, untpd.TypedSplice(argument) :: Nil),
pt, locked)
if (cand.isExtension) {
val SelectionProto(name: TermName, mbrType, _, _) = pt
val result = extMethodApply(untpd.Select(untpdGenerated, name), argument, mbrType)
if (!ctx.reporter.hasErrors && cand.isConversion) {
val testCtx = ctx.fresh.setExploreTyperState()
tryConversion(testCtx)
if (testCtx.reporter.hasErrors)
ctx.error(em"ambiguous implicit: $generated is eligible both as an implicit conversion and as an extension method container")
}
result
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) {
record("typedImplicit")
val ref = cand.ref
val generated: Tree = tpd.ref(ref).withSpan(span.startPos)
val locked = ctx.typerState.ownedVars
val adapted =
if (argument.isEmpty)
adapt(generated, pt.widenExpr, locked)
else {
def untpdGenerated = untpd.TypedSplice(generated)
def tryConversion(implicit ctx: Context) = {
val untpdConv =
if (ref.symbol.is(Given))
untpd.Select(
untpd.TypedSplice(
adapt(generated,
defn.ConversionClass.typeRef.appliedTo(argument.tpe.widen, pt),
locked)),
nme.apply)
else untpdGenerated
typed(
untpd.Apply(untpdConv, untpd.TypedSplice(argument) :: Nil),
pt, locked)
}
if (cand.isExtension) {
val SelectionProto(name: TermName, mbrType, _, _) = pt
val result = extMethodApply(untpd.Select(untpdGenerated, name), argument, mbrType)
if (!ctx.reporter.hasErrors && cand.isConversion) {
val testCtx = ctx.fresh.setExploreTyperState()
tryConversion(testCtx)
if (testCtx.reporter.hasErrors)
ctx.error(em"ambiguous implicit: $generated is eligible both as an implicit conversion and as an extension method container")
}
result
}
else tryConversion
}
Expand Down
19 changes: 19 additions & 0 deletions tests/pos/i6914.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
trait Expr[T]
trait Liftable[T]

/*given autoToExpr[T] as Conversion[T, Expr[T]] given Liftable[T] {
def apply(x: T): Expr[T] = ???
}
*/
class ToExpr[T] given Liftable[T] extends Conversion[T, Expr[T]] {
def apply(x: T): Expr[T] = ???
}
given toExpr[T] as ToExpr[T] given Liftable[T]

given as Liftable[Int] = ???
given as Liftable[String] = ???

def x = the[ToExpr[String]]
def y = the[Conversion[String, Expr[String]]]

def a: Expr[String] = "abc"