@@ -195,6 +195,7 @@ class Namer { typer: Typer =>
195
195
196
196
val TypedAhead : Property .Key [tpd.Tree ] = new Property .Key
197
197
val ExpandedTree : Property .Key [untpd.Tree ] = new Property .Key
198
+ val ExportForwarders : Property .Key [List [tpd.MemberDef ]] = new Property .Key
198
199
val SymOfTree : Property .Key [Symbol ] = new Property .Key
199
200
val Deriver : Property .Key [typer.Deriver ] = new Property .Key
200
201
@@ -932,6 +933,104 @@ class Namer { typer: Typer =>
932
933
933
934
def init (): Context = index(params)
934
935
936
+ /** Add forwarders as required by the export statements in this class */
937
+ private def processExports (implicit ctx : Context ): Unit = {
938
+
939
+ /** The forwarders defined by export `exp`.
940
+ */
941
+ def exportForwarders (exp : Export ): List [tpd.MemberDef ] = {
942
+ val buf = new mutable.ListBuffer [tpd.MemberDef ]
943
+ val Export (_, expr, selectors) = exp
944
+ val path = typedAheadExpr(expr, AnySelectionProto )
945
+ checkLegalImportPath(path)
946
+
947
+ def needsForwarder (sym : Symbol ) =
948
+ sym.is(ImplicitOrImplied ) == exp.impliedOnly &&
949
+ sym.isAccessibleFrom(path.tpe) &&
950
+ ! sym.isConstructor &&
951
+ ! cls.derivesFrom(sym.owner)
952
+
953
+ /** Add a forwarder with name `alias` or its type name equivalent to `mbr`,
954
+ * provided `mbr` is accessible and of the right implicit/non-implicit kind.
955
+ */
956
+ def addForwarder (alias : TermName , mbr : SingleDenotation , span : Span ): Unit =
957
+ if (needsForwarder(mbr.symbol)) {
958
+
959
+ /** The info of a forwarder to type `ref` which has info `info`
960
+ */
961
+ def fwdInfo (ref : Type , info : Type ): Type = info match {
962
+ case _ : ClassInfo =>
963
+ HKTypeLambda .fromParams(info.typeParams, ref)
964
+ case _ : TypeBounds =>
965
+ ref
966
+ case info : HKTypeLambda =>
967
+ info.derivedLambdaType(info.paramNames, info.paramInfos,
968
+ fwdInfo(ref.appliedTo(info.paramRefs), info.resultType))
969
+ case info => // should happen only in error cases
970
+ info
971
+ }
972
+
973
+ val forwarder =
974
+ if (mbr.isType)
975
+ ctx.newSymbol(
976
+ cls, alias.toTypeName,
977
+ Final ,
978
+ fwdInfo(path.tpe.select(mbr.symbol), mbr.info),
979
+ coord = span)
980
+ else
981
+ ctx.newSymbol(
982
+ cls, alias,
983
+ Method | Final | mbr.symbol.flags & ImplicitOrImplied ,
984
+ mbr.info,
985
+ coord = span)
986
+ val forwarderDef =
987
+ if (forwarder.isType) tpd.TypeDef (forwarder.asType)
988
+ else {
989
+ import tpd ._
990
+ val ref = path.select(mbr.symbol.asTerm)
991
+ tpd.polyDefDef(forwarder.asTerm, targs => prefss =>
992
+ ref.appliedToTypes(targs).appliedToArgss(prefss)
993
+ )
994
+ }
995
+ buf += forwarderDef.withSpan(span)
996
+ }
997
+
998
+ def addForwardersNamed (name : TermName , alias : TermName , span : Span ): Unit = {
999
+ val mbrs = List (name, name.toTypeName).flatMap(path.tpe.member(_).alternatives)
1000
+ if (mbrs.isEmpty)
1001
+ ctx.error(i " no accessible member $name at $path" , ctx.source.atSpan(span))
1002
+ mbrs.foreach(addForwarder(alias, _, span))
1003
+ }
1004
+
1005
+ def addForwardersExcept (seen : List [TermName ], span : Span ): Unit =
1006
+ for (mbr <- path.tpe.allMembers) {
1007
+ val alias = mbr.name.toTermName
1008
+ if (! seen.contains(alias)) addForwarder(alias, mbr, span)
1009
+ }
1010
+
1011
+ def recur (seen : List [TermName ], sels : List [untpd.Tree ]): Unit = sels match {
1012
+ case (sel @ Ident (nme.WILDCARD )) :: _ =>
1013
+ addForwardersExcept(seen, sel.span)
1014
+ case (sel @ Ident (name : TermName )) :: rest =>
1015
+ addForwardersNamed(name, name, sel.span)
1016
+ recur(name :: seen, rest)
1017
+ case Thicket ((sel @ Ident (fromName : TermName )) :: Ident (toName : TermName ) :: Nil ) :: rest =>
1018
+ if (toName != nme.WILDCARD ) addForwardersNamed(fromName, toName, sel.span)
1019
+ recur(fromName :: seen, rest)
1020
+ case _ =>
1021
+ }
1022
+
1023
+ recur(Nil , selectors)
1024
+ val forwarders = buf.toList
1025
+ exp.pushAttachment(ExportForwarders , forwarders)
1026
+ forwarders
1027
+ }
1028
+
1029
+ val forwarderss =
1030
+ for (exp @ Export (_, _, _) <- rest) yield exportForwarders(exp)
1031
+ forwarderss.foreach(_.foreach(fwdr => fwdr.symbol.entered))
1032
+ }
1033
+
935
1034
/** The type signature of a ClassDef with given symbol */
936
1035
override def completeInCreationContext (denot : SymDenotation ): Unit = {
937
1036
val parents = impl.parents
@@ -1068,12 +1167,15 @@ class Namer { typer: Typer =>
1068
1167
1069
1168
tempInfo.finalize(denot, parentTypes, finalSelfInfo)
1070
1169
1170
+
1171
+
1071
1172
Checking .checkWellFormed(cls)
1072
1173
if (isDerivedValueClass(cls)) cls.setFlag(Final )
1073
1174
cls.info = avoidPrivateLeaks(cls, cls.sourcePos)
1074
1175
cls.baseClasses.foreach(_.invalidateBaseTypeCache()) // we might have looked before and found nothing
1075
1176
cls.setNoInitsFlags(parentsKind(parents), bodyKind(rest))
1076
1177
if (cls.isNoInitsClass) cls.primaryConstructor.setFlag(StableRealizable )
1178
+ processExports(localCtx)
1077
1179
}
1078
1180
}
1079
1181
0 commit comments