Skip to content

Commit

Permalink
Map over refs of ImportTypes in TypeMap (#20837)
Browse files Browse the repository at this point in the history
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
  • Loading branch information
odersky authored Jul 2, 2024
2 parents af93578 + ff003fd commit cd8c5ed
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 1 deletion.
7 changes: 6 additions & 1 deletion compiler/src/dotty/tools/dotc/ast/TreeTypeMap.scala
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,12 @@ class TreeTypeMap(
}

def mapType(tp: Type): Type =
mapOwnerThis(typeMap(tp).substSym(substFrom, substTo))
val substMap = new TypeMap():
def apply(tp: Type): Type = tp match
case tp: TermRef if tp.symbol.isImport => mapOver(tp)
case tp => tp.substSym(substFrom, substTo)
mapOwnerThis(substMap(typeMap(tp)))
end mapType

private def updateDecls(prevStats: List[Tree], newStats: List[Tree]): Unit =
if (prevStats.isEmpty) assert(newStats.isEmpty)
Expand Down
6 changes: 6 additions & 0 deletions compiler/src/dotty/tools/dotc/core/Types.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6295,6 +6295,12 @@ object Types extends TypeUtils {
val ctx = this.mapCtx // optimization for performance
given Context = ctx
tp match {
case tp: TermRef if tp.symbol.isImport =>
// see tests/pos/i19493.scala for examples requiring mapping over imports
val ImportType(e) = tp.info: @unchecked
val e1 = singleton(apply(e.tpe))
newImportSymbol(tp.symbol.owner, e1).termRef

case tp: NamedType =>
if stopBecauseStaticOrLocal(tp) then tp
else
Expand Down
18 changes: 18 additions & 0 deletions tests/pos-macros/i19436/Macro_1.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@

import scala.quoted.*
import scala.compiletime.summonInline

trait SomeImplicits:
given int: Int

object Macro:

transparent inline def testSummon: SomeImplicits => Int = ${ testSummonImpl }

private def testSummonImpl(using Quotes): Expr[SomeImplicits => Int] =
import quotes.reflect.*
'{
(x: SomeImplicits) =>
import x.given
summonInline[Int]
}
2 changes: 2 additions & 0 deletions tests/pos-macros/i19436/Test_2.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@

def fn: Unit = Macro.testSummon
49 changes: 49 additions & 0 deletions tests/pos/i19493.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import scala.compiletime.{summonAll, summonInline}
import deriving.Mirror

type Sc[X] = X
case class Row[T[_]](name: T[String])

class DialectTypeMappers:
given String = ???

inline def metadata(dialect: DialectTypeMappers)(using m: Mirror.Of[Row[Sc]]): m.MirroredElemTypes =
import dialect.given
summonAll[m.MirroredElemTypes]

def f = metadata(???)


object Minimization:

class GivesString:
given aString: String = ???

inline def foo(x: GivesString): Unit =
import x.aString
summon[String] // ok
summonInline[String] // was error

foo(???)


trait A:
val x: GivesString

inline def bar: Unit =
import this.x.aString
summon[String] // ok
summonInline[String] // was error

val a: A = ???
a.bar


inline def baz() = (x: GivesString) =>
import x.aString
summon[String] // ok
summonInline[String] // was error

baz()

end Minimization

0 comments on commit cd8c5ed

Please sign in to comment.