Skip to content

Commit f3a4263

Browse files
committed
Make forwarder logic more explicit
1 parent aadc10f commit f3a4263

File tree

1 file changed

+30
-24
lines changed

1 file changed

+30
-24
lines changed

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

Lines changed: 30 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -974,7 +974,6 @@ class Namer { typer: Typer =>
974974

975975
/** The forwarders defined by export `exp` */
976976
private def exportForwarders(exp: Export)(using Context): List[tpd.MemberDef] =
977-
val SKIP = "(skip)" // A string indicating that no forwarders for this kind of symbol are emitted
978977
val buf = new mutable.ListBuffer[tpd.MemberDef]
979978
val Export(expr, selectors) = exp
980979
if expr.isEmpty then
@@ -986,19 +985,22 @@ class Namer { typer: Typer =>
986985
lazy val wildcardBound = importBound(selectors, isGiven = false)
987986
lazy val givenBound = importBound(selectors, isGiven = true)
988987

989-
def whyNoForwarder(mbr: SingleDenotation): String = {
988+
def canForward(mbr: SingleDenotation): CanForward = {
989+
import CanForward.*
990990
val sym = mbr.symbol
991-
if (!sym.isAccessibleFrom(path.tpe)) "is not accessible"
992-
else if (sym.isConstructor || sym.is(ModuleClass) || sym.is(Bridge) || sym.is(ConstructorProxy)) SKIP
993-
else if (cls.derivesFrom(sym.owner) &&
994-
(sym.owner == cls || !sym.is(Deferred))) i"is already a member of $cls"
995-
else if (sym.is(Override))
991+
if !sym.isAccessibleFrom(path.tpe) then
992+
No("is not accessible")
993+
else if sym.isConstructor || sym.is(ModuleClass) || sym.is(Bridge) || sym.is(ConstructorProxy) then
994+
Skip
995+
else if cls.derivesFrom(sym.owner) && (sym.owner == cls || !sym.is(Deferred)) then
996+
No(i"is already a member of $cls")
997+
else if sym.is(Override) then
996998
sym.allOverriddenSymbols.find(
997-
other => cls.derivesFrom(other.owner) && !other.is(Deferred)) match {
998-
case Some(other) => i"overrides ${other.showLocated}, which is already a member of $cls"
999-
case None => ""
1000-
}
1001-
else ""
999+
other => cls.derivesFrom(other.owner) && !other.is(Deferred)
1000+
) match
1001+
case Some(other) => No(i"overrides ${other.showLocated}, which is already a member of $cls")
1002+
case None => Yes
1003+
else Yes
10021004
}
10031005

10041006
/** Add a forwarder with name `alias` or its type name equivalent to `mbr`,
@@ -1021,7 +1023,7 @@ class Namer { typer: Typer =>
10211023
case _ =>
10221024
acc.reverse ::: prefss
10231025

1024-
if whyNoForwarder(mbr) == "" then
1026+
if canForward(mbr) == CanForward.Yes then
10251027
val sym = mbr.symbol
10261028
val forwarder =
10271029
if mbr.isType then
@@ -1038,7 +1040,7 @@ class Namer { typer: Typer =>
10381040
// a parameterized class, say `C[X]` the alias will read `type C = d.C`. We currently do
10391041
// allow such type aliases. If we forbid them at some point (requiring the referred type to be
10401042
// fully applied), we'd have to change the scheme here as well.
1041-
else {
1043+
else
10421044
def refersToPrivate(tp: Type): Boolean = tp match
10431045
case tp: TermRef => tp.termSymbol.is(Private) || refersToPrivate(tp.prefix)
10441046
case _ => false
@@ -1051,16 +1053,17 @@ class Namer { typer: Typer =>
10511053
if sym.is(ExtensionMethod) then mbrFlags |= ExtensionMethod
10521054
val forwarderName = checkNoConflict(alias, isPrivate = false, span)
10531055
newSymbol(cls, forwarderName, mbrFlags, mbrInfo, coord = span)
1054-
}
1056+
10551057
forwarder.info = avoidPrivateLeaks(forwarder)
10561058
forwarder.addAnnotations(sym.annotations)
1059+
10571060
val forwarderDef =
10581061
if (forwarder.isType) tpd.TypeDef(forwarder.asType)
10591062
else {
10601063
import tpd._
10611064
val ref = path.select(sym.asTerm)
10621065
val ddef = tpd.DefDef(forwarder.asTerm, prefss =>
1063-
ref.appliedToArgss(adaptForwarderParams(Nil, sym.info, prefss))
1066+
ref.appliedToArgss(adaptForwarderParams(Nil, sym.info, prefss))
10641067
)
10651068
if forwarder.isInlineMethod then
10661069
PrepareInlineable.registerInlineInfo(forwarder, ddef.rhs)
@@ -1070,18 +1073,15 @@ class Namer { typer: Typer =>
10701073
buf += forwarderDef.withSpan(span)
10711074
end addForwarder
10721075

1073-
def addForwardersNamed(name: TermName, alias: TermName, span: Span): Unit = {
1076+
def addForwardersNamed(name: TermName, alias: TermName, span: Span): Unit =
10741077
val size = buf.size
10751078
val mbrs = List(name, name.toTypeName).flatMap(path.tpe.member(_).alternatives)
10761079
mbrs.foreach(addForwarder(alias, _, span))
1077-
if (buf.size == size) {
1078-
val reason = mbrs.map(whyNoForwarder).dropWhile(_ == SKIP) match {
1079-
case Nil => ""
1080-
case why :: _ => i"\n$path.$name cannot be exported because it $why"
1081-
}
1080+
if buf.size == size then
1081+
val reason = mbrs.map(canForward).collect {
1082+
case CanForward.No(whyNot) => i"\n$path.$name cannot be exported because it $whyNot"
1083+
}.headOption.getOrElse("")
10821084
report.error(i"""no eligible member $name at $path$reason""", ctx.source.atSpan(span))
1083-
}
1084-
}
10851085

10861086
def addWildcardForwardersNamed(name: TermName, span: Span): Unit =
10871087
List(name, name.toTypeName)
@@ -1357,6 +1357,12 @@ class Namer { typer: Typer =>
13571357
}
13581358
}
13591359

1360+
/** Possible actions to perform when deciding on a forwarder for a member */
1361+
private enum CanForward:
1362+
case Yes
1363+
case No(whyNot: String)
1364+
case Skip // for members that have never forwarders
1365+
13601366
class SuspendCompleter extends LazyType, SymbolLoaders.SecondCompleter {
13611367

13621368
final override def complete(denot: SymDenotation)(using Context): Unit =

0 commit comments

Comments
 (0)