Skip to content

Commit cd8c5ed

Browse files
authored
Map over refs of ImportTypes in TypeMap (#20837)
The inliner replaces references to parameters by their corresponding proxys, including in singleton types. It did not handle the mapping over import types, the symbols of which way have depended on parameters. Both i19493 and i19436 require mapping the type of the expr in an `ImportType` which is itself the info of a `TermRef`. In the first issue, for the substitution of an inline def parameter proxy. In the second issue, for the parameter of a lambda returned from an inline def. Both can be handled in `TypeMap` by mapping over references to `ImportType`s. The second case also requires modifying `TreeTypeMap#mapType` such that the logic mapping over imports is done within a `TypeMap` doing the symbol substitutions. Also note these mappings are only necessary for `summonInline`s (which could have just been made non-inline) resolving post-inlining to givens imported within the inline definition. Fix #19493 Fix #19436
2 parents af93578 + ff003fd commit cd8c5ed

File tree

5 files changed

+81
-1
lines changed

5 files changed

+81
-1
lines changed

Diff for: compiler/src/dotty/tools/dotc/ast/TreeTypeMap.scala

+6-1
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,12 @@ class TreeTypeMap(
6969
}
7070

7171
def mapType(tp: Type): Type =
72-
mapOwnerThis(typeMap(tp).substSym(substFrom, substTo))
72+
val substMap = new TypeMap():
73+
def apply(tp: Type): Type = tp match
74+
case tp: TermRef if tp.symbol.isImport => mapOver(tp)
75+
case tp => tp.substSym(substFrom, substTo)
76+
mapOwnerThis(substMap(typeMap(tp)))
77+
end mapType
7378

7479
private def updateDecls(prevStats: List[Tree], newStats: List[Tree]): Unit =
7580
if (prevStats.isEmpty) assert(newStats.isEmpty)

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

+6
Original file line numberDiff line numberDiff line change
@@ -6295,6 +6295,12 @@ object Types extends TypeUtils {
62956295
val ctx = this.mapCtx // optimization for performance
62966296
given Context = ctx
62976297
tp match {
6298+
case tp: TermRef if tp.symbol.isImport =>
6299+
// see tests/pos/i19493.scala for examples requiring mapping over imports
6300+
val ImportType(e) = tp.info: @unchecked
6301+
val e1 = singleton(apply(e.tpe))
6302+
newImportSymbol(tp.symbol.owner, e1).termRef
6303+
62986304
case tp: NamedType =>
62996305
if stopBecauseStaticOrLocal(tp) then tp
63006306
else

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

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
2+
import scala.quoted.*
3+
import scala.compiletime.summonInline
4+
5+
trait SomeImplicits:
6+
given int: Int
7+
8+
object Macro:
9+
10+
transparent inline def testSummon: SomeImplicits => Int = ${ testSummonImpl }
11+
12+
private def testSummonImpl(using Quotes): Expr[SomeImplicits => Int] =
13+
import quotes.reflect.*
14+
'{
15+
(x: SomeImplicits) =>
16+
import x.given
17+
summonInline[Int]
18+
}

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

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
2+
def fn: Unit = Macro.testSummon

Diff for: tests/pos/i19493.scala

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import scala.compiletime.{summonAll, summonInline}
2+
import deriving.Mirror
3+
4+
type Sc[X] = X
5+
case class Row[T[_]](name: T[String])
6+
7+
class DialectTypeMappers:
8+
given String = ???
9+
10+
inline def metadata(dialect: DialectTypeMappers)(using m: Mirror.Of[Row[Sc]]): m.MirroredElemTypes =
11+
import dialect.given
12+
summonAll[m.MirroredElemTypes]
13+
14+
def f = metadata(???)
15+
16+
17+
object Minimization:
18+
19+
class GivesString:
20+
given aString: String = ???
21+
22+
inline def foo(x: GivesString): Unit =
23+
import x.aString
24+
summon[String] // ok
25+
summonInline[String] // was error
26+
27+
foo(???)
28+
29+
30+
trait A:
31+
val x: GivesString
32+
33+
inline def bar: Unit =
34+
import this.x.aString
35+
summon[String] // ok
36+
summonInline[String] // was error
37+
38+
val a: A = ???
39+
a.bar
40+
41+
42+
inline def baz() = (x: GivesString) =>
43+
import x.aString
44+
summon[String] // ok
45+
summonInline[String] // was error
46+
47+
baz()
48+
49+
end Minimization

0 commit comments

Comments
 (0)