Skip to content

Commit

Permalink
Don't generate a Select for a TermRef with NoPrefix (scala#16754)
Browse files Browse the repository at this point in the history
In TreeTypeMap, don't generate a Select node if the new type of the tree
is a TermRef with NoPrefix. Generate an Ident node instead.

Fixes scala#16740
  • Loading branch information
odersky committed Jan 24, 2023
2 parents 8d0c307 + d91f66f commit 43d0ec4
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 16 deletions.
40 changes: 25 additions & 15 deletions compiler/src/dotty/tools/dotc/ast/TreeTypeMap.scala
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class TreeTypeMap(

def copy(
typeMap: Type => Type,
treeMap: tpd.Tree => tpd.Tree,
treeMap: Tree => Tree,
oldOwners: List[Symbol],
newOwners: List[Symbol],
substFrom: List[Symbol],
Expand Down Expand Up @@ -85,13 +85,13 @@ class TreeTypeMap(
updateDecls(prevStats.tail, newStats.tail)
}

def transformInlined(tree: tpd.Inlined)(using Context): tpd.Tree =
def transformInlined(tree: Inlined)(using Context): Tree =
val Inlined(call, bindings, expanded) = tree
val (tmap1, bindings1) = transformDefs(bindings)
val expanded1 = tmap1.transform(expanded)
cpy.Inlined(tree)(call, bindings1, expanded1)

override def transform(tree: tpd.Tree)(using Context): tpd.Tree = treeMap(tree) match {
override def transform(tree: Tree)(using Context): Tree = treeMap(tree) match {
case impl @ Template(constr, _, self, _) =>
val tmap = withMappedSyms(localSyms(impl :: self :: Nil))
cpy.Template(impl)(
Expand All @@ -103,8 +103,24 @@ class TreeTypeMap(
).withType(tmap.mapType(impl.tpe))
case tree1 =>
tree1.withType(mapType(tree1.tpe)) match {
case id: Ident if tpd.needsSelect(id.tpe) =>
ref(id.tpe.asInstanceOf[TermRef]).withSpan(id.span)
case id: Ident =>
if needsSelect(id.tpe) then
ref(id.tpe.asInstanceOf[TermRef]).withSpan(id.span)
else
super.transform(id)
case sel: Select =>
if needsIdent(sel.tpe) then
ref(sel.tpe.asInstanceOf[TermRef]).withSpan(sel.span)
else
super.transform(sel)
case app: Apply =>
super.transform(app)
case blk @ Block(stats, expr) =>
val (tmap1, stats1) = transformDefs(stats)
val expr1 = tmap1.transform(expr)
cpy.Block(blk)(stats1, expr1)
case lit @ Literal(Constant(tpe: Type)) =>
cpy.Literal(lit)(Constant(mapType(tpe)))
case ddef @ DefDef(name, paramss, tpt, _) =>
val (tmap1, paramss1) = transformAllParamss(paramss)
val res = cpy.DefDef(ddef)(name, paramss1, tmap1.transform(tpt), tmap1.transform(ddef.rhs))
Expand All @@ -117,10 +133,6 @@ class TreeTypeMap(
case tdef @ LambdaTypeTree(tparams, body) =>
val (tmap1, tparams1) = transformDefs(tparams)
cpy.LambdaTypeTree(tdef)(tparams1, tmap1.transform(body))
case blk @ Block(stats, expr) =>
val (tmap1, stats1) = transformDefs(stats)
val expr1 = tmap1.transform(expr)
cpy.Block(blk)(stats1, expr1)
case inlined: Inlined =>
transformInlined(inlined)
case cdef @ CaseDef(pat, guard, rhs) =>
Expand All @@ -139,18 +151,16 @@ class TreeTypeMap(
val content1 = transform(content)
val tpt1 = transform(tpt)
cpy.Hole(tree)(args = args1, content = content1, tpt = tpt1)
case lit @ Literal(Constant(tpe: Type)) =>
cpy.Literal(lit)(Constant(mapType(tpe)))
case tree1 =>
super.transform(tree1)
}
}

override def transformStats(trees: List[tpd.Tree], exprOwner: Symbol)(using Context): List[Tree] =
override def transformStats(trees: List[Tree], exprOwner: Symbol)(using Context): List[Tree] =
transformDefs(trees)._2

def transformDefs[TT <: tpd.Tree](trees: List[TT])(using Context): (TreeTypeMap, List[TT]) = {
val tmap = withMappedSyms(tpd.localSyms(trees))
def transformDefs[TT <: Tree](trees: List[TT])(using Context): (TreeTypeMap, List[TT]) = {
val tmap = withMappedSyms(localSyms(trees))
(tmap, tmap.transformSub(trees))
}

Expand All @@ -165,7 +175,7 @@ class TreeTypeMap(
case nil =>
(this, paramss)

def apply[ThisTree <: tpd.Tree](tree: ThisTree): ThisTree = transform(tree).asInstanceOf[ThisTree]
def apply[ThisTree <: Tree](tree: ThisTree): ThisTree = transform(tree).asInstanceOf[ThisTree]

def apply(annot: Annotation): Annotation = annot.derivedAnnotation(apply(annot.tree))

Expand Down
4 changes: 4 additions & 0 deletions compiler/src/dotty/tools/dotc/ast/tpd.scala
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,10 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
case _ => false
}

def needsIdent(tp: Type)(using Context): Boolean = tp match
case tp: TermRef => tp.prefix eq NoPrefix
case _ => false

/** A tree representing the same reference as the given type */
def ref(tp: NamedType, needLoad: Boolean = true)(using Context): Tree =
if (tp.isType) TypeTree(tp)
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/transform/Erasure.scala
Original file line number Diff line number Diff line change
Expand Up @@ -774,7 +774,7 @@ object Erasure {
select(qual1, sym)
else
val castTarget = // Avoid inaccessible cast targets, see i8661
if isJvmAccessible(sym.owner)
if isJvmAccessible(sym.owner) && sym.owner.isType
then
sym.owner.typeRef
else
Expand Down
8 changes: 8 additions & 0 deletions tests/pos/i16740.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
class Enclosing:
object Tags:
opaque type Ref[T, S <: String & Singleton] = S
inline def require[T, S <: String & Singleton]: Ref[T, S] = ???
import Tags.*

val t1 = require[Int, "t1"]
val t2 = require[Double, "t2"]

0 comments on commit 43d0ec4

Please sign in to comment.