@@ -195,6 +195,7 @@ class Namer { typer: Typer =>
195195
196196 val TypedAhead : Property .Key [tpd.Tree ] = new Property .Key
197197 val ExpandedTree : Property .Key [untpd.Tree ] = new Property .Key
198+ val ExportForwarders : Property .Key [List [tpd.MemberDef ]] = new Property .Key
198199 val SymOfTree : Property .Key [Symbol ] = new Property .Key
199200 val Deriver : Property .Key [typer.Deriver ] = new Property .Key
200201
@@ -932,6 +933,104 @@ class Namer { typer: Typer =>
932933
933934 def init (): Context = index(params)
934935
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+
9351034 /** The type signature of a ClassDef with given symbol */
9361035 override def completeInCreationContext (denot : SymDenotation ): Unit = {
9371036 val parents = impl.parents
@@ -1068,12 +1167,15 @@ class Namer { typer: Typer =>
10681167
10691168 tempInfo.finalize(denot, parentTypes, finalSelfInfo)
10701169
1170+
1171+
10711172 Checking .checkWellFormed(cls)
10721173 if (isDerivedValueClass(cls)) cls.setFlag(Final )
10731174 cls.info = avoidPrivateLeaks(cls, cls.sourcePos)
10741175 cls.baseClasses.foreach(_.invalidateBaseTypeCache()) // we might have looked before and found nothing
10751176 cls.setNoInitsFlags(parentsKind(parents), bodyKind(rest))
10761177 if (cls.isNoInitsClass) cls.primaryConstructor.setFlag(StableRealizable )
1178+ processExports(localCtx)
10771179 }
10781180 }
10791181
0 commit comments