Skip to content

Commit 213e94d

Browse files
committed
Do not approximate prefixes when using memberType in reflect API
1 parent 0e567c1 commit 213e94d

File tree

5 files changed

+40
-8
lines changed

5 files changed

+40
-8
lines changed

Diff for: compiler/src/dotty/tools/dotc/core/TypeOps.scala

+5-5
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ object TypeOps:
3131
/** The type `tp` as seen from prefix `pre` and owner `cls`. See the spec
3232
* for what this means.
3333
*/
34-
final def asSeenFrom(tp: Type, pre: Type, cls: Symbol)(using Context): Type = {
34+
final def asSeenFrom(tp: Type, pre: Type, cls: Symbol, approximateUnstablePrefixes: Boolean)(using Context): Type = {
3535
pre match {
3636
case pre: QualSkolemType =>
3737
// When a selection has an unstable qualifier, the qualifier type gets
@@ -42,7 +42,7 @@ object TypeOps:
4242
// compute the type as seen from the widened prefix, and in the rare
4343
// cases where this leads to an approximated type we recompute it with
4444
// the skolemized prefix. See the i6199* tests for usecases.
45-
val widenedAsf = new AsSeenFromMap(pre.info, cls)
45+
val widenedAsf = new AsSeenFromMap(pre.info, cls, approximateUnstablePrefixes)
4646
val ret = widenedAsf.apply(tp)
4747

4848
if widenedAsf.approxCount == 0 then
@@ -52,11 +52,11 @@ object TypeOps:
5252
case _ =>
5353
}
5454

55-
new AsSeenFromMap(pre, cls).apply(tp)
55+
new AsSeenFromMap(pre, cls, approximateUnstablePrefixes).apply(tp)
5656
}
5757

5858
/** The TypeMap handling the asSeenFrom */
59-
class AsSeenFromMap(pre: Type, cls: Symbol)(using Context) extends ApproximatingTypeMap, IdempotentCaptRefMap {
59+
class AsSeenFromMap(pre: Type, cls: Symbol, approximateUnstablePrefixes: Boolean)(using Context) extends ApproximatingTypeMap, IdempotentCaptRefMap {
6060

6161
/** The number of range approximations in invariant or contravariant positions
6262
* performed by this TypeMap.
@@ -81,7 +81,7 @@ object TypeOps:
8181
case pre: SuperType => toPrefix(pre.thistpe, cls, thiscls)
8282
case _ =>
8383
if (thiscls.derivesFrom(cls) && pre.baseType(thiscls).exists)
84-
if (variance <= 0 && !isLegalPrefix(pre))
84+
if (approximateUnstablePrefixes && variance <= 0 && !isLegalPrefix(pre))
8585
approxCount += 1
8686
range(defn.NothingType, pre)
8787
else pre

Diff for: compiler/src/dotty/tools/dotc/core/Types.scala

+5-2
Original file line numberDiff line numberDiff line change
@@ -1106,11 +1106,14 @@ object Types extends TypeUtils {
11061106

11071107
/** This type seen as if it were the type of a member of prefix type `pre`
11081108
* declared in class `cls`.
1109+
*
1110+
* @param approximateUnstablePrefixes - needed for mamberType method in quotes reflect API,
1111+
* where we want to approximate less
11091112
*/
1110-
final def asSeenFrom(pre: Type, cls: Symbol)(using Context): Type = {
1113+
final def asSeenFrom(pre: Type, cls: Symbol, approximateUnstablePrefixes: Boolean = true)(using Context): Type = {
11111114
record("asSeenFrom")
11121115
if (!cls.membersNeedAsSeenFrom(pre)) this
1113-
else TypeOps.asSeenFrom(this, pre, cls)
1116+
else TypeOps.asSeenFrom(this, pre, cls, approximateUnstablePrefixes)
11141117
}
11151118

11161119
// ----- Subtype-related --------------------------------------------

Diff for: compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -1826,7 +1826,7 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler
18261826
def termSymbol: Symbol = self.termSymbol
18271827
def isSingleton: Boolean = self.isSingleton
18281828
def memberType(member: Symbol): TypeRepr =
1829-
member.info.asSeenFrom(self, member.owner)
1829+
member.info.asSeenFrom(self, member.owner, approximateUnstablePrefixes = false)
18301830
def baseClasses: List[Symbol] = self.baseClasses
18311831
def baseType(cls: Symbol): TypeRepr = self.baseType(cls)
18321832
def derivesFrom(cls: Symbol): Boolean = self.derivesFrom(cls)

Diff for: tests/pos-macros/i22424/Macro_1.scala

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
2+
import scala.quoted.*
3+
4+
object MockMaker:
5+
inline def inlineMock[T]: Unit = ${instance[T]}
6+
transparent inline def transparentInlineMock[T]: Unit = ${instance[T]}
7+
8+
def instance[T: Type](using quotes: Quotes): Expr[Unit] =
9+
import quotes.reflect._
10+
val tpe = TypeRepr.of[T]
11+
val symbol = tpe.typeSymbol.methodMember("innerTraitInOptions").head
12+
tpe.memberType(symbol) match
13+
case mt @ MethodType(_, args, _) =>
14+
assert(args.head.typeSymbol != TypeRepr.of[Nothing].typeSymbol, "argument is incorrectly approximated")
15+
val shownType = mt.show
16+
val expectedType = "(x: m.Embedded#ATrait[scala.Predef.String, scala.Int])m.Embedded#ATrait[scala.Predef.String, scala.Int]"
17+
assert(shownType == expectedType, s"Incorrect type shown. Obtained: $shownType, Expected: $expectedType")
18+
'{()}
19+
20+
trait PolymorphicTrait {
21+
trait Embedded {
22+
trait ATrait[A, B]
23+
def innerTraitInOptions(x: ATrait[String, Int]): ATrait[String, Int]
24+
}
25+
}

Diff for: tests/pos-macros/i22424/Test_2.scala

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
@main def Test =
2+
val m = new PolymorphicTrait {}
3+
MockMaker.inlineMock[m.Embedded]
4+
MockMaker.transparentInlineMock[m.Embedded]

0 commit comments

Comments
 (0)