Skip to content

Commit c32adc2

Browse files
committed
Avoid embedding SelectionProtos in Conversions
1 parent d0b790e commit c32adc2

File tree

3 files changed

+38
-6
lines changed

3 files changed

+38
-6
lines changed

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

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1122,17 +1122,29 @@ trait Implicits:
11221122
adapt(generated, pt.widenExpr, locked)
11231123
else {
11241124
def untpdGenerated = untpd.TypedSplice(generated)
1125-
def producesConversion(info: Type): Boolean = info match
1126-
case info: PolyType => producesConversion(info.resType)
1127-
case info: MethodType if info.isImplicitMethod => producesConversion(info.resType)
1128-
case _ => info.derivesFrom(defn.ConversionClass)
1125+
def conversionResultType(info: Type): Type = info match
1126+
case info: PolyType => conversionResultType(info.resType)
1127+
case info: MethodType if info.isImplicitMethod => conversionResultType(info.resType)
1128+
case _ if info.derivesFrom(defn.ConversionClass) => pt match
1129+
case selProto: SelectionProto =>
1130+
info.baseType(defn.ConversionClass) match
1131+
case AppliedType(_, List(_, restpe)) if selProto.isMatchedBy(restpe) =>
1132+
// if we embed the SelectionProto as the Conversion result type
1133+
// it might end up within a GADT cast type
1134+
// so instead replace it with the targeted conversion type, if it matches
1135+
// see tests/pos/i15867.scala.
1136+
restpe
1137+
case _ => pt
1138+
case _ => pt
1139+
case _ => NoType
11291140
def tryConversion(using Context) = {
1141+
val restpeConv = if ref.symbol.is(Given) then conversionResultType(ref.symbol.info) else NoType
11301142
val untpdConv =
1131-
if ref.symbol.is(Given) && producesConversion(ref.symbol.info) then
1143+
if restpeConv.exists then
11321144
untpd.Select(
11331145
untpd.TypedSplice(
11341146
adapt(generated,
1135-
defn.ConversionClass.typeRef.appliedTo(argument.tpe, pt),
1147+
defn.ConversionClass.typeRef.appliedTo(argument.tpe, restpeConv),
11361148
locked)),
11371149
nme.apply)
11381150
else untpdGenerated

compiler/test/dotc/pos-test-pickling.blacklist

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ i4176-gadt.scala
9494

9595
# GADT difference
9696
i13974a.scala
97+
i15867.scala
9798

9899
java-inherited-type1
99100

tests/pos/i15867.scala

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
enum SUB[-A, +B]:
2+
case Refl[S]() extends SUB[S, S]
3+
4+
class Pow(self: Int):
5+
def **(other: Int): Int = math.pow(self, other).toInt
6+
7+
given fromList[T]: Conversion[List[T], Pow] = ???
8+
9+
given fromInt: Conversion[Int, Pow] = Pow(_)
10+
11+
def foo[T](t1: T, ev: T SUB List[Int]) =
12+
ev match { case SUB.Refl() =>
13+
t1 ** 2 // error
14+
}
15+
16+
def baz[T](t2: T, ev: T SUB Int) =
17+
ev match { case SUB.Refl() =>
18+
t2 ** 2 // works
19+
}

0 commit comments

Comments
 (0)