Skip to content

Commit 226e809

Browse files
committed
Recover the denotation of constant-folded selections
With this change, the only term selections without a symbol after Typer and before Pickler come from polymorphic function calls or outer selects. This should be good enough to let us use SELECTin in all situations where overloads can appear as #11210 is attempting.
1 parent 3c837f9 commit 226e809

File tree

3 files changed

+22
-3
lines changed

3 files changed

+22
-3
lines changed

compiler/src/dotty/tools/dotc/ast/Trees.scala

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ package ast
44

55
import core._
66
import Types._, Names._, NameOps._, Flags._, util.Spans._, Contexts._, Constants._
7-
import typer.ProtoTypes
7+
import typer.{ ConstFold, ProtoTypes }
88
import SymDenotations._, Symbols._, Denotations._, StdNames._, Comments._
99
import language.higherKinds
1010
import collection.mutable.ListBuffer
@@ -408,6 +408,13 @@ object Trees {
408408
case class Select[-T >: Untyped] private[ast] (qualifier: Tree[T], name: Name)(implicit @constructorOnly src: SourceFile)
409409
extends RefTree[T] {
410410
type ThisTree[-T >: Untyped] = Select[T]
411+
412+
override def denot(using Context): Denotation = typeOpt match
413+
case ConstantType(_) if ConstFold.foldedUnops.contains(name) =>
414+
// Recover the denotation of a constant-folded selection
415+
qualifier.typeOpt.member(name).atSignature(Signature.NotAMethod, name)
416+
case _ =>
417+
super.denot
411418
}
412419

413420
class SelectWithSig[-T >: Untyped] private[ast] (qualifier: Tree[T], name: Name, val sig: Signature)(implicit @constructorOnly src: SourceFile)

compiler/src/dotty/tools/dotc/transform/TreeChecker.scala

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -380,14 +380,25 @@ class TreeChecker extends Phase with SymTransformer {
380380
override def typedSelect(tree: untpd.Select, pt: Type)(using Context): Tree = {
381381
assert(tree.isTerm || !ctx.isAfterTyper, tree.show + " at " + ctx.phase)
382382
val tpe = tree.typeOpt
383+
384+
// Polymorphic apply methods stay structural until Erasure
385+
val isPolyFunctionApply = (tree.name eq nme.apply) && (tree.qualifier.typeOpt <:< defn.PolyFunctionType)
386+
// Outer selects are pickled specially so don't require a symbol
387+
val isOuterSelect = tree.name.is(OuterSelectName)
388+
val isPrimitiveArrayOp = ctx.erasedTypes && nme.isPrimitiveName(tree.name)
389+
if !(tree.isType || isPolyFunctionApply || isOuterSelect || isPrimitiveArrayOp) then
390+
val denot = tree.denot
391+
assert(denot.exists, i"Selection $tree with type $tpe does not have a denotation")
392+
assert(denot.symbol.exists, i"Denotation $denot of selection $tree with type $tpe does not have a symbol")
393+
383394
val sym = tree.symbol
384395
val symIsFixed = tpe match {
385396
case tpe: TermRef => ctx.erasedTypes || !tpe.isMemberRef
386397
case _ => false
387398
}
388399
if (sym.exists && !sym.is(Private) &&
389400
!symIsFixed &&
390-
!tree.name.is(OuterSelectName)) { // outer selects have effectively fixed symbols
401+
!isOuterSelect) { // outer selects have effectively fixed symbols
391402
val qualTpe = tree.qualifier.typeOpt
392403
val member =
393404
if (sym.is(Private)) qualTpe.member(tree.name)
@@ -403,6 +414,7 @@ class TreeChecker extends Phase with SymTransformer {
403414
|qualifier type : ${tree.qualifier.typeOpt}
404415
|tree type : ${tree.typeOpt} of class ${tree.typeOpt.getClass}""")
405416
}
417+
406418
checkNotRepeated(super.typedSelect(tree, pt))
407419
}
408420

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ object ConstFold:
2323
nme.LT, nme.GT, nme.LE, nme.GE, nme.LSL, nme.LSR, nme.ASR,
2424
nme.ADD, nme.SUB, nme.MUL, nme.DIV, nme.MOD)
2525

26-
private val foldedUnops = Set[Name](
26+
val foldedUnops = Set[Name](
2727
nme.UNARY_!, nme.UNARY_~, nme.UNARY_+, nme.UNARY_-)
2828

2929
def Apply[T <: Apply](tree: T)(using Context): T =

0 commit comments

Comments
 (0)