Skip to content

Commit 3aa5f76

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 d049102 commit 3aa5f76

File tree

3 files changed

+69
-3
lines changed

3 files changed

+69
-3
lines changed

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

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1086,15 +1086,24 @@ class Namer { typer: Typer =>
10861086
}
10871087
}
10881088

1089+
def addWildcardForwardersNamed(name: TermName, span: Span): Unit =
1090+
List(name, name.toTypeName)
1091+
.flatMap(path.tpe.memberBasedOnFlags(_, excluded = Private|Given|ConstructorProxy).alternatives)
1092+
.foreach(addForwarder(name, _, span)) // ignore if any are not added
1093+
10891094
def addWildcardForwarders(seen: List[TermName], span: Span): Unit =
1095+
val nonContextual = mutable.HashSet(seen: _*)
10901096
for mbr <- path.tpe.membersBasedOnFlags(required = EmptyFlags, excluded = PrivateOrSynthetic) do
10911097
if !mbr.symbol.isSuperAccessor then
10921098
// Scala 2 superaccessors have neither Synthetic nor Artfact set, so we
10931099
// need to filter them out here (by contrast, Scala 3 superaccessors are Artifacts)
10941100
val alias = mbr.name.toTermName
1095-
if !seen.contains(alias)
1096-
&& mbr.matchesImportBound(if mbr.symbol.is(Given) then givenBound else wildcardBound)
1097-
then addForwarder(alias, mbr, span)
1101+
if mbr.symbol.is(Given) then
1102+
if !seen.contains(alias) && mbr.matchesImportBound(givenBound) then
1103+
addForwarder(alias, mbr, span)
1104+
else if !nonContextual.contains(alias) && mbr.matchesImportBound(wildcardBound) then
1105+
nonContextual += alias
1106+
addWildcardForwardersNamed(alias, span)
10981107

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

tests/neg/i10857.scala

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

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)