Skip to content

Commit f79059f

Browse files
committed
fix #10857: export from wildcard more definitions
a wildcard export will first search for all public and non-synthetic members to add. Then once a valid member is found, that name is then used to search for all term or type members that use that name and are not given or private. As a consequence members like companion objects to case classes will be exported alongside a type alias to the case class
1 parent ca02d83 commit f79059f

File tree

3 files changed

+62
-2
lines changed

3 files changed

+62
-2
lines changed

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

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1062,15 +1062,26 @@ class Namer { typer: Typer =>
10621062
}
10631063
}
10641064

1065+
def addWildcardForwardersNamed(name: TermName, span: Span): Unit =
1066+
List(name, name.toTypeName)
1067+
.flatMap(path.tpe.memberBasedOnFlags(_, excluded = Private|Given).alternatives)
1068+
.foreach(addForwarder(name, _, span)) // ignore if any are not added
1069+
10651070
def addWildcardForwarders(seen: List[TermName], span: Span): Unit =
1071+
val seenBuf = mutable.HashSet(seen: _*)
10661072
for mbr <- path.tpe.membersBasedOnFlags(required = EmptyFlags, excluded = PrivateOrSynthetic) do
10671073
if !mbr.symbol.isSuperAccessor then
10681074
// Scala 2 superaccessors have neither Synthetic nor Artfact set, so we
10691075
// need to filter them out here (by contrast, Scala 3 superaccessors are Artifacts)
10701076
val alias = mbr.name.toTermName
1071-
if !seen.contains(alias)
1077+
if !seenBuf.contains(alias)
10721078
&& mbr.matchesImportBound(if mbr.symbol.is(Given) then givenBound else wildcardBound)
1073-
then addForwarder(alias, mbr, span)
1079+
then
1080+
seenBuf += alias
1081+
if mbr.symbol.is(Given) then
1082+
addForwarder(alias, mbr, span)
1083+
else
1084+
addWildcardForwardersNamed(alias, span)
10741085

10751086
def addForwarders(sels: List[untpd.ImportSelector], seen: List[TermName]): Unit = sels match
10761087
case sel :: sels1 =>

tests/neg/i10857.scala

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
object Module:
2+
3+
class Bar
4+
class Baz
5+
6+
object Givens:
7+
given GivenBar: Bar = new Bar()
8+
def GivenBar(ignored: Int): Bar = new Bar()
9+
class GivenBar
10+
11+
object Members:
12+
given Member: Baz = new Baz()
13+
private def Member(ignored1: String)(ignored2: Int): Bar = new Bar()
14+
def Member(ignored: Int): Baz = new Baz()
15+
class Member
16+
17+
enum Color:
18+
case Red, Green, Blue
19+
20+
export Color._ // will only export synthetic defs with same name as standard definition
21+
export Givens.given // should only export given values
22+
export Members._ // should only export values that are not given
23+
24+
@main def Test =
25+
26+
println(Module.Red)
27+
println(Module.valueOf("Red")) // error: value valueOf is not a member
28+
29+
println(summon[Module.Bar])
30+
println(new Module.GivenBar()) // error: type GivenBar is not a member
31+
println(Module.GivenBar(23)) // error: method GivenBar does not take parameters
32+
33+
34+
println(new Module.Member())
35+
println(Module.Member(23))
36+
println(Module.Member("?")(23)) // error: Found: ("?" : String) Required: Int
37+
println(summon[Module.Baz]) // error: no implicit argument of type Module.Baz was found

tests/run/i10857.scala

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
object Module:
2+
3+
enum Foo:
4+
case Value
5+
case Parameterised(i: Int)
6+
7+
export Foo._
8+
9+
@main def Test =
10+
import Module.given
11+
println(Module.Parameterised.apply(23)) // synthetic companion object is exported
12+
println(Module.Value)

0 commit comments

Comments
 (0)