@@ -5,7 +5,7 @@ import dotty.tools.dotc.ast.untpd
5
5
import dotty .tools .dotc .core .Contexts ._
6
6
import dotty .tools .dotc .core .Names .Name
7
7
import dotty .tools .dotc .core .Phases .Phase
8
- import dotty .tools .dotc .core .StdNames .ScalaTermNames
8
+ import dotty .tools .dotc .core .StdNames .nme
9
9
10
10
11
11
/** This phase collects and transforms top-level Import trees to handle definition shadowing.
@@ -15,7 +15,7 @@ import dotty.tools.dotc.core.StdNames.ScalaTermNames
15
15
*
16
16
* Import transformation is necessary for excluding its members when they are shadowed in the same run.
17
17
* This is done by finding all members defined after the Import clause calculating
18
- * their intersection with available members from selectors
18
+ * their intersection with available members from selectors including renaming.
19
19
*
20
20
* This step is necessary for proper new run initialization since we need to import the previous run
21
21
* into Context. It is accomplished in the following order:
@@ -40,23 +40,39 @@ class CollectTopLevelImports extends Phase {
40
40
/** Transforms top-level imports to exclude intersecting members declared after the Import clause.
41
41
* To properly handle imports such as: `import A.f; def f = 3` consequently making sure that original selectors are
42
42
* filtered to eliminate potential duplications that would result in compilation error.
43
+ *
44
+ * Transformed imports of which selectors were all shadowed will be ignored in the future runs.
43
45
*/
44
46
private def transformTopLevelImports (trees : List [Tree ])(using Context ): List [Import ] =
45
47
val definitions = collectTopLevelMemberDefs(trees)
46
48
47
49
trees.collect {
48
50
case tree @ Import (expr, selectors) =>
49
51
val definitionsAfterImport = definitions.filter(_._2 > tree.endPos.end).map(_._1)
50
- val membersIntersection = expr.tpe.allMembers.map(_.name).intersect(definitionsAfterImport)
51
52
52
- val transformedSelectors = membersIntersection.map(collidingMember => {
53
- untpd.ImportSelector (untpd.Ident (collidingMember), untpd.Ident (CollectTopLevelImports .nme.WILDCARD ))
54
- }).toList
55
-
56
- val filteredSelectors = selectors.filterNot(importSelector => membersIntersection.contains(importSelector.imported.name))
57
-
58
- Import (expr, transformedSelectors.toList ::: filteredSelectors)
59
- }
53
+ val importedNames : List [Name ] = (if selectors.exists(_.isWildcard) then
54
+ val allImportTypeMembers = expr.tpe.allMembers.map(_.name)
55
+ val nonWildcardSelectors = selectors.filter(_.isWildcard)
56
+ val renamedMembers = nonWildcardSelectors.map(_.imported.name)
57
+ nonWildcardSelectors.map(_.rename) ++ allImportTypeMembers.filterNot(renamedMembers.contains)
58
+ else
59
+ selectors.map(_.rename)
60
+ )
61
+
62
+ val shadowedMembers = importedNames.intersect(definitionsAfterImport)
63
+ val adjustedSelectors = shadowedMembers.map(collidingMember => {
64
+ untpd.ImportSelector (untpd.Ident (collidingMember), untpd.Ident (nme.WILDCARD ))
65
+ })
66
+
67
+ val remainingSelectors = selectors.filterNot(importSelector => {
68
+ shadowedMembers.contains(importSelector.rename)
69
+ })
70
+
71
+ if remainingSelectors.isEmpty then
72
+ None
73
+ else
74
+ Some (Import (expr, adjustedSelectors ++ remainingSelectors))
75
+ }.flatten
60
76
61
77
private def collectTopLevelMemberDefs (trees : List [Tree ])(using Context ): List [(Name , Int )] =
62
78
trees.collect {
@@ -67,7 +83,3 @@ class CollectTopLevelImports extends Phase {
67
83
68
84
}
69
85
70
- object CollectTopLevelImports {
71
- private lazy val nme : ScalaTermNames = new ScalaTermNames
72
- }
73
-
0 commit comments