Skip to content

Commit 1a21f80

Browse files
authored
Fix imported twice error messages (#18102)
Fixes #18082
2 parents 90c59bd + eb5d07c commit 1a21f80

File tree

10 files changed

+58
-11
lines changed

10 files changed

+58
-11
lines changed

compiler/src/dotty/tools/dotc/ast/untpd.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,8 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
137137
val rename: TermName = renamed match
138138
case Ident(rename: TermName) => rename
139139
case _ => name
140+
141+
def isUnimport = rename == nme.WILDCARD
140142
}
141143

142144
case class Number(digits: String, kind: NumberKind)(implicit @constructorOnly src: SourceFile) extends TermTree

compiler/src/dotty/tools/dotc/reporting/ErrorMessageID.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ enum ErrorMessageID(val isActive: Boolean = true) extends java.lang.Enum[ErrorMe
135135
case JavaSymbolIsNotAValueID // errorNumber: 119
136136
case DoubleDefinitionID // errorNumber: 120
137137
case MatchCaseOnlyNullWarningID // errorNumber: 121
138-
case ImportRenamedTwiceID // errorNumber: 122
138+
case ImportedTwiceID // errorNumber: 122
139139
case TypeTestAlwaysDivergesID // errorNumber: 123
140140
case TermMemberNeedsNeedsResultTypeForImplicitSearchID // errorNumber: 124
141141
case ClassCannotExtendEnumID // errorNumber: 125
@@ -198,6 +198,7 @@ enum ErrorMessageID(val isActive: Boolean = true) extends java.lang.Enum[ErrorMe
198198
case NotConstantID // errorNumber: 182
199199
case ClosureCannotHaveInternalParameterDependenciesID // errorNumber: 183
200200
case MatchTypeNoCasesID // errorNumber: 184
201+
case UnimportedAndImportedID // errorNumber: 185
201202

202203
def errorNumber = ordinal - 1
203204

compiler/src/dotty/tools/dotc/reporting/messages.scala

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2234,8 +2234,15 @@ extends NamingMsg(DoubleDefinitionID) {
22342234
def explain(using Context) = ""
22352235
}
22362236

2237-
class ImportRenamedTwice(ident: untpd.Ident)(using Context) extends SyntaxMsg(ImportRenamedTwiceID) {
2238-
def msg(using Context) = s"${ident.show} is renamed twice on the same import line."
2237+
class ImportedTwice(sel: Name)(using Context) extends SyntaxMsg(ImportedTwiceID) {
2238+
def msg(using Context) = s"${sel.show} is imported twice on the same import line."
2239+
def explain(using Context) = ""
2240+
}
2241+
2242+
class UnimportedAndImported(sel: Name, isImport: Boolean)(using Context) extends SyntaxMsg(UnimportedAndImportedID) {
2243+
def msg(using Context) =
2244+
val otherStr = if isImport then "and imported" else "twice"
2245+
s"${sel.show} is unimported $otherStr on the same import line."
22392246
def explain(using Context) = ""
22402247
}
22412248

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

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1511,17 +1511,23 @@ trait Checking {
15111511
* (2) Check that no import selector is renamed more than once.
15121512
*/
15131513
def checkImportSelectors(qualType: Type, selectors: List[untpd.ImportSelector])(using Context): Unit =
1514-
val seen = mutable.Set.empty[Name]
1514+
val originals = mutable.Set.empty[Name]
1515+
val targets = mutable.Set.empty[Name]
15151516

15161517
def checkIdent(sel: untpd.ImportSelector): Unit =
15171518
if sel.name != nme.ERROR
15181519
&& !qualType.member(sel.name).exists
15191520
&& !qualType.member(sel.name.toTypeName).exists
15201521
then
15211522
report.error(NotAMember(qualType, sel.name, "value"), sel.imported.srcPos)
1522-
if seen.contains(sel.name) then
1523-
report.error(ImportRenamedTwice(sel.imported), sel.imported.srcPos)
1524-
seen += sel.name
1523+
if sel.isUnimport then
1524+
if originals.contains(sel.name) then
1525+
report.error(UnimportedAndImported(sel.name, targets.contains(sel.name)), sel.imported.srcPos)
1526+
else
1527+
if targets.contains(sel.rename) then
1528+
report.error(ImportedTwice(sel.rename), sel.renamed.orElse(sel.imported).srcPos)
1529+
targets += sel.rename
1530+
originals += sel.name
15251531

15261532
if !ctx.compilationUnit.isJava then
15271533
for sel <- selectors do

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ class ImportInfo(symf: Context ?=> Symbol,
109109
else
110110
if sel.rename != sel.name then
111111
myExcluded = myExcluded.nn + sel.name
112-
if sel.rename != nme.WILDCARD then
112+
if !sel.isUnimport then
113113
myForwardMapping = myForwardMapping.uncheckedNN.updated(sel.name, sel.rename)
114114
myReverseMapping = myReverseMapping.uncheckedNN.updated(sel.rename, sel.name)
115115

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1309,7 +1309,7 @@ class Namer { typer: Typer =>
13091309
if sel.isWildcard then
13101310
addWildcardForwarders(seen, sel.span)
13111311
else
1312-
if sel.rename != nme.WILDCARD then
1312+
if !sel.isUnimport then
13131313
addForwardersNamed(sel.name, sel.rename, sel.span)
13141314
addForwarders(sels1, sel.name :: seen)
13151315
case _ =>

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
325325
fail(em"reference to `$name` is ambiguous; it is imported twice")
326326
found
327327

328-
if selector.rename == termName && selector.rename != nme.WILDCARD then
328+
if selector.rename == termName && !selector.isUnimport then
329329
val memberName =
330330
if selector.name == termName then name
331331
else if name.isTypeName then selector.name.toTypeName

tests/neg/i18082.check

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
-- [E122] Syntax Error: tests/neg/i18082.scala:5:23 --------------------------------------------------------------------
2+
5 |import O.{a as b, b as b} // error
3+
| ^
4+
| b is imported twice on the same import line.
5+
-- [E122] Syntax Error: tests/neg/i18082.scala:6:18 --------------------------------------------------------------------
6+
6 |import O.{a as b, b} // error
7+
| ^
8+
| b is imported twice on the same import line.
9+
-- [E122] Syntax Error: tests/neg/i18082.scala:7:13 --------------------------------------------------------------------
10+
7 |import O.{a, a} // error
11+
| ^
12+
| a is imported twice on the same import line.
13+
-- [E185] Syntax Error: tests/neg/i18082.scala:10:18 -------------------------------------------------------------------
14+
10 |import O.{a as _, a as _} // error
15+
| ^
16+
| a is unimported twice on the same import line.
17+
-- [E185] Syntax Error: tests/neg/i18082.scala:11:13 -------------------------------------------------------------------
18+
11 |import O.{a, a as _} // error
19+
| ^
20+
| a is unimported and imported on the same import line.

tests/neg/i18082.scala

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
object O { val a = 1; val b = 2 }
2+
3+
import O.{a as b, a} // OK
4+
import O.{a as b, b as a} // OK
5+
import O.{a as b, b as b} // error
6+
import O.{a as b, b} // error
7+
import O.{a, a} // error
8+
9+
import O.{a as _, b as _} // ok
10+
import O.{a as _, a as _} // error
11+
import O.{a, a as _} // error
12+

tests/neg/i3745c.scala

Lines changed: 0 additions & 1 deletion
This file was deleted.

0 commit comments

Comments
 (0)