Skip to content

Commit dab4880

Browse files
committed
Recover the denotation of constant-folded selections
With this change, the only term selections without a symbol after Typer 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 dab4880

File tree

3 files changed

+21
-3
lines changed

3 files changed

+21
-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: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -380,14 +380,24 @@ 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+
if !(tree.isType || isPolyFunctionApply || isOuterSelect) then
389+
val denot = tree.denot
390+
assert(denot.exists, i"Selection $tree with type $tpe does not have a denotation")
391+
assert(denot.symbol.exists, i"Denotation $denot of selection $tree with type $tpe does not have a symbol")
392+
383393
val sym = tree.symbol
384394
val symIsFixed = tpe match {
385395
case tpe: TermRef => ctx.erasedTypes || !tpe.isMemberRef
386396
case _ => false
387397
}
388398
if (sym.exists && !sym.is(Private) &&
389399
!symIsFixed &&
390-
!tree.name.is(OuterSelectName)) { // outer selects have effectively fixed symbols
400+
!isOuterSelect) { // outer selects have effectively fixed symbols
391401
val qualTpe = tree.qualifier.typeOpt
392402
val member =
393403
if (sym.is(Private)) qualTpe.member(tree.name)
@@ -403,6 +413,7 @@ class TreeChecker extends Phase with SymTransformer {
403413
|qualifier type : ${tree.qualifier.typeOpt}
404414
|tree type : ${tree.typeOpt} of class ${tree.typeOpt.getClass}""")
405415
}
416+
406417
checkNotRepeated(super.typedSelect(tree, pt))
407418
}
408419

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)