@@ -972,162 +972,171 @@ class Namer { typer: Typer =>
972
972
973
973
def init (): Context = index(params)
974
974
975
- /** Add forwarders as required by the export statements in this class */
976
- private def processExports (using Context ): Unit = {
975
+ /** The forwarders defined by export `exp` */
976
+ 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
978
+ val buf = new mutable.ListBuffer [tpd.MemberDef ]
979
+ val Export (expr, selectors) = exp
980
+ if expr.isEmpty then
981
+ report.error(em " Export selector must have prefix and `.` " , exp.srcPos)
982
+ return Nil
983
+
984
+ val path = typedAheadExpr(expr, AnySelectionProto )
985
+ checkLegalExportPath(path, selectors)
986
+ lazy val wildcardBound = importBound(selectors, isGiven = false )
987
+ lazy val givenBound = importBound(selectors, isGiven = true )
988
+
989
+ def whyNoForwarder (mbr : SingleDenotation ): String = {
990
+ 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 ))
996
+ 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 " "
1002
+ }
977
1003
978
- /** A string indicating that no forwarders for this kind of symbol are emitted */
979
- val SKIP = " (skip)"
1004
+ /** Add a forwarder with name `alias` or its type name equivalent to `mbr`,
1005
+ * provided `mbr` is accessible and of the right implicit/non-implicit kind.
1006
+ */
1007
+ def addForwarder (alias : TermName , mbr : SingleDenotation , span : Span ): Unit =
1008
+
1009
+ def adaptForwarderParams (acc : List [List [tpd.Tree ]], tp : Type , prefss : List [List [tpd.Tree ]])
1010
+ : List [List [tpd.Tree ]] = tp match
1011
+ case mt : MethodType
1012
+ if mt.paramInfos.nonEmpty && mt.paramInfos.last.isRepeatedParam =>
1013
+ // Note: in this branch we use the assumptions
1014
+ // that `prefss.head` corresponds to `mt.paramInfos` and
1015
+ // that `prefss.tail` corresponds to `mt.resType`
1016
+ val init :+ vararg = prefss.head
1017
+ val prefs = init :+ ctx.typeAssigner.seqToRepeated(vararg)
1018
+ adaptForwarderParams(prefs :: acc, mt.resType, prefss.tail)
1019
+ case mt : MethodOrPoly =>
1020
+ adaptForwarderParams(prefss.head :: acc, mt.resultType, prefss.tail)
1021
+ case _ =>
1022
+ acc.reverse ::: prefss
980
1023
981
- /** The forwarders defined by export `exp`.
982
- */
983
- def exportForwarders (exp : Export ): List [tpd.MemberDef ] = {
984
- val buf = new mutable.ListBuffer [tpd.MemberDef ]
985
- val Export (expr, selectors) = exp
986
- if expr.isEmpty then
987
- report.error(em " Export selector must have prefix and `.` " , exp.srcPos)
988
- return Nil
989
-
990
- val path = typedAheadExpr(expr, AnySelectionProto )
991
- checkLegalExportPath(path, selectors)
992
- lazy val wildcardBound = importBound(selectors, isGiven = false )
993
- lazy val givenBound = importBound(selectors, isGiven = true )
994
-
995
- def whyNoForwarder (mbr : SingleDenotation ): String = {
1024
+ if whyNoForwarder(mbr) == " " then
996
1025
val sym = mbr.symbol
997
- if (! sym.isAccessibleFrom(path.tpe)) " is not accessible"
998
- else if (sym.isConstructor || sym.is(ModuleClass ) || sym.is(Bridge ) || sym.is(ConstructorProxy )) SKIP
999
- else if (cls.derivesFrom(sym.owner) &&
1000
- (sym.owner == cls || ! sym.is(Deferred ))) i " is already a member of $cls"
1001
- else if (sym.is(Override ))
1002
- sym.allOverriddenSymbols.find(
1003
- other => cls.derivesFrom(other.owner) && ! other.is(Deferred )) match {
1004
- case Some (other) => i " overrides ${other.showLocated}, which is already a member of $cls"
1005
- case None => " "
1026
+ val forwarder =
1027
+ if mbr.isType then
1028
+ val forwarderName = checkNoConflict(alias.toTypeName, isPrivate = false , span)
1029
+ var target = path.tpe.select(sym)
1030
+ if target.typeParams.nonEmpty then
1031
+ target = target.EtaExpand (target.typeParams)
1032
+ newSymbol(
1033
+ cls, forwarderName,
1034
+ Exported | Final ,
1035
+ TypeAlias (target),
1036
+ coord = span)
1037
+ // Note: This will always create unparameterzied aliases. So even if the original type is
1038
+ // a parameterized class, say `C[X]` the alias will read `type C = d.C`. We currently do
1039
+ // allow such type aliases. If we forbid them at some point (requiring the referred type to be
1040
+ // fully applied), we'd have to change the scheme here as well.
1041
+ else {
1042
+ def refersToPrivate (tp : Type ): Boolean = tp match
1043
+ case tp : TermRef => tp.termSymbol.is(Private ) || refersToPrivate(tp.prefix)
1044
+ case _ => false
1045
+ val (maybeStable, mbrInfo) =
1046
+ if sym.isStableMember && sym.isPublic && ! refersToPrivate(path.tpe) then
1047
+ (StableRealizable , ExprType (path.tpe.select(sym)))
1048
+ else
1049
+ (EmptyFlags , mbr.info.ensureMethodic)
1050
+ var mbrFlags = Exported | Method | Final | maybeStable | sym.flags & RetainedExportFlags
1051
+ if sym.is(ExtensionMethod ) then mbrFlags |= ExtensionMethod
1052
+ val forwarderName = checkNoConflict(alias, isPrivate = false , span)
1053
+ newSymbol(cls, forwarderName, mbrFlags, mbrInfo, coord = span)
1006
1054
}
1007
- else " "
1008
- }
1009
-
1010
- /** Add a forwarder with name `alias` or its type name equivalent to `mbr`,
1011
- * provided `mbr` is accessible and of the right implicit/non-implicit kind.
1012
- */
1013
- def addForwarder (alias : TermName , mbr : SingleDenotation , span : Span ): Unit =
1014
-
1015
- def adaptForwarderParams (acc : List [List [tpd.Tree ]], tp : Type , prefss : List [List [tpd.Tree ]])
1016
- : List [List [tpd.Tree ]] = tp match
1017
- case mt : MethodType
1018
- if mt.paramInfos.nonEmpty && mt.paramInfos.last.isRepeatedParam =>
1019
- // Note: in this branch we use the assumptions
1020
- // that `prefss.head` corresponds to `mt.paramInfos` and
1021
- // that `prefss.tail` corresponds to `mt.resType`
1022
- val init :+ vararg = prefss.head
1023
- val prefs = init :+ ctx.typeAssigner.seqToRepeated(vararg)
1024
- adaptForwarderParams(prefs :: acc, mt.resType, prefss.tail)
1025
- case mt : MethodOrPoly =>
1026
- adaptForwarderParams(prefss.head :: acc, mt.resultType, prefss.tail)
1027
- case _ =>
1028
- acc.reverse ::: prefss
1029
-
1030
- if whyNoForwarder(mbr) == " " then
1031
- val sym = mbr.symbol
1032
- val forwarder =
1033
- if mbr.isType then
1034
- val forwarderName = checkNoConflict(alias.toTypeName, isPrivate = false , span)
1035
- var target = path.tpe.select(sym)
1036
- if target.typeParams.nonEmpty then
1037
- target = target.EtaExpand (target.typeParams)
1038
- newSymbol(
1039
- cls, forwarderName,
1040
- Exported | Final ,
1041
- TypeAlias (target),
1042
- coord = span)
1043
- // Note: This will always create unparameterzied aliases. So even if the original type is
1044
- // a parameterized class, say `C[X]` the alias will read `type C = d.C`. We currently do
1045
- // allow such type aliases. If we forbid them at some point (requiring the referred type to be
1046
- // fully applied), we'd have to change the scheme here as well.
1047
- else {
1048
- def refersToPrivate (tp : Type ): Boolean = tp match
1049
- case tp : TermRef => tp.termSymbol.is(Private ) || refersToPrivate(tp.prefix)
1050
- case _ => false
1051
- val (maybeStable, mbrInfo) =
1052
- if sym.isStableMember && sym.isPublic && ! refersToPrivate(path.tpe) then
1053
- (StableRealizable , ExprType (path.tpe.select(sym)))
1054
- else
1055
- (EmptyFlags , mbr.info.ensureMethodic)
1056
- var mbrFlags = Exported | Method | Final | maybeStable | sym.flags & RetainedExportFlags
1057
- if sym.is(ExtensionMethod ) then mbrFlags |= ExtensionMethod
1058
- val forwarderName = checkNoConflict(alias, isPrivate = false , span)
1059
- newSymbol(cls, forwarderName, mbrFlags, mbrInfo, coord = span)
1060
- }
1061
- forwarder.info = avoidPrivateLeaks(forwarder)
1062
- forwarder.addAnnotations(sym.annotations)
1063
- val forwarderDef =
1064
- if (forwarder.isType) tpd.TypeDef (forwarder.asType)
1065
- else {
1066
- import tpd ._
1067
- val ref = path.select(sym.asTerm)
1068
- val ddef = tpd.DefDef (forwarder.asTerm, prefss =>
1069
- ref.appliedToArgss(adaptForwarderParams(Nil , sym.info, prefss))
1070
- )
1071
- if forwarder.isInlineMethod then
1072
- PrepareInlineable .registerInlineInfo(forwarder, ddef.rhs)
1073
- ddef
1074
- }
1075
-
1076
- buf += forwarderDef.withSpan(span)
1077
- end addForwarder
1078
-
1079
- def addForwardersNamed (name : TermName , alias : TermName , span : Span ): Unit = {
1080
- val size = buf.size
1081
- val mbrs = List (name, name.toTypeName).flatMap(path.tpe.member(_).alternatives)
1082
- mbrs.foreach(addForwarder(alias, _, span))
1083
- if (buf.size == size) {
1084
- val reason = mbrs.map(whyNoForwarder).dropWhile(_ == SKIP ) match {
1085
- case Nil => " "
1086
- case why :: _ => i " \n $path. $name cannot be exported because it $why"
1055
+ forwarder.info = avoidPrivateLeaks(forwarder)
1056
+ forwarder.addAnnotations(sym.annotations)
1057
+ val forwarderDef =
1058
+ if (forwarder.isType) tpd.TypeDef (forwarder.asType)
1059
+ else {
1060
+ import tpd ._
1061
+ val ref = path.select(sym.asTerm)
1062
+ val ddef = tpd.DefDef (forwarder.asTerm, prefss =>
1063
+ ref.appliedToArgss(adaptForwarderParams(Nil , sym.info, prefss))
1064
+ )
1065
+ if forwarder.isInlineMethod then
1066
+ PrepareInlineable .registerInlineInfo(forwarder, ddef.rhs)
1067
+ ddef
1087
1068
}
1088
- report.error(i """ no eligible member $name at $path$reason""" , ctx.source.atSpan(span))
1069
+
1070
+ buf += forwarderDef.withSpan(span)
1071
+ end addForwarder
1072
+
1073
+ def addForwardersNamed (name : TermName , alias : TermName , span : Span ): Unit = {
1074
+ val size = buf.size
1075
+ val mbrs = List (name, name.toTypeName).flatMap(path.tpe.member(_).alternatives)
1076
+ 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"
1089
1081
}
1082
+ report.error(i """ no eligible member $name at $path$reason""" , ctx.source.atSpan(span))
1090
1083
}
1084
+ }
1091
1085
1092
- def addWildcardForwardersNamed (name : TermName , span : Span ): Unit =
1093
- List (name, name.toTypeName)
1094
- .flatMap(path.tpe.memberBasedOnFlags(_, excluded = Private | Given | ConstructorProxy ).alternatives)
1095
- .foreach(addForwarder(name, _, span)) // ignore if any are not added
1096
-
1097
- def addWildcardForwarders (seen : List [TermName ], span : Span ): Unit =
1098
- val nonContextual = mutable.HashSet (seen : _* )
1099
- for mbr <- path.tpe.membersBasedOnFlags(required = EmptyFlags , excluded = PrivateOrSynthetic ) do
1100
- if ! mbr.symbol.isSuperAccessor then
1101
- // Scala 2 superaccessors have neither Synthetic nor Artfact set, so we
1102
- // need to filter them out here (by contrast, Scala 3 superaccessors are Artifacts)
1103
- val alias = mbr.name.toTermName
1104
- if mbr.symbol.is(Given ) then
1105
- if ! seen.contains(alias) && mbr.matchesImportBound(givenBound) then
1106
- addForwarder(alias, mbr, span)
1107
- else if ! nonContextual.contains(alias) && mbr.matchesImportBound(wildcardBound) then
1108
- nonContextual += alias
1109
- addWildcardForwardersNamed(alias, span)
1110
-
1111
- def addForwarders (sels : List [untpd.ImportSelector ], seen : List [TermName ]): Unit = sels match
1112
- case sel :: sels1 =>
1113
- if sel.isWildcard then
1114
- addWildcardForwarders(seen, sel.span)
1115
- else
1116
- if sel.rename != nme.WILDCARD then
1117
- addForwardersNamed(sel.name, sel.rename, sel.span)
1118
- addForwarders(sels1, sel.name :: seen)
1119
- case _ =>
1086
+ def addWildcardForwardersNamed (name : TermName , span : Span ): Unit =
1087
+ List (name, name.toTypeName)
1088
+ .flatMap(path.tpe.memberBasedOnFlags(_, excluded = Private | Given | ConstructorProxy ).alternatives)
1089
+ .foreach(addForwarder(name, _, span)) // ignore if any are not added
1090
+
1091
+ def addWildcardForwarders (seen : List [TermName ], span : Span ): Unit =
1092
+ val nonContextual = mutable.HashSet (seen : _* )
1093
+ for mbr <- path.tpe.membersBasedOnFlags(required = EmptyFlags , excluded = PrivateOrSynthetic ) do
1094
+ if ! mbr.symbol.isSuperAccessor then
1095
+ // Scala 2 superaccessors have neither Synthetic nor Artfact set, so we
1096
+ // need to filter them out here (by contrast, Scala 3 superaccessors are Artifacts)
1097
+ val alias = mbr.name.toTermName
1098
+ if mbr.symbol.is(Given ) then
1099
+ if ! seen.contains(alias) && mbr.matchesImportBound(givenBound) then
1100
+ addForwarder(alias, mbr, span)
1101
+ else if ! nonContextual.contains(alias) && mbr.matchesImportBound(wildcardBound) then
1102
+ nonContextual += alias
1103
+ addWildcardForwardersNamed(alias, span)
1104
+
1105
+ def addForwarders (sels : List [untpd.ImportSelector ], seen : List [TermName ]): Unit = sels match
1106
+ case sel :: sels1 =>
1107
+ if sel.isWildcard then
1108
+ addWildcardForwarders(seen, sel.span)
1109
+ else
1110
+ if sel.rename != nme.WILDCARD then
1111
+ addForwardersNamed(sel.name, sel.rename, sel.span)
1112
+ addForwarders(sels1, sel.name :: seen)
1113
+ case _ =>
1120
1114
1121
- addForwarders(selectors, Nil )
1122
- val forwarders = buf.toList
1123
- exp.pushAttachment(ExportForwarders , forwarders)
1124
- forwarders
1125
- }
1115
+ addForwarders(selectors, Nil )
1116
+ val forwarders = buf.toList
1117
+ exp.pushAttachment(ExportForwarders , forwarders)
1118
+ forwarders
1119
+ end exportForwarders
1126
1120
1127
- for case exp @ Export (_, _) <- rest do
1128
- for forwarder <- exportForwarders(exp) do
1129
- forwarder.symbol.entered
1130
- }
1121
+ /** Add forwarders as required by the export statements in this class */
1122
+ private def processExports (using Context ): Unit =
1123
+
1124
+ def process (stats : List [Tree ])(using Context ): Unit = stats match
1125
+ case (stat : Export ) :: stats1 =>
1126
+ for forwarder <- exportForwarders(stat) do
1127
+ forwarder.symbol.entered
1128
+ process(stats1)
1129
+ case (stat : Import ) :: stats1 =>
1130
+ process(stats1)(using ctx.importContext(stat, symbolOfTree(stat)))
1131
+ case stat :: stats1 =>
1132
+ process(stats1)
1133
+ case Nil =>
1134
+
1135
+ // Do a quick scan whether we need to process at all. This avoids creating
1136
+ // import contexts for nothing.
1137
+ if rest.exists(_.isInstanceOf [Export ]) then
1138
+ process(rest)
1139
+ end processExports
1131
1140
1132
1141
/** Ensure constructor is completed so that any parameter accessors
1133
1142
* which have type trees deriving from its parameters can be
0 commit comments