Skip to content

Commit 1f813bc

Browse files
authored
Merge pull request #15477 from dotty-staging/fix-15468
Check import selectors at Typer
2 parents f58c158 + d73fc84 commit 1f813bc

13 files changed

+42
-23
lines changed

compiler/src/dotty/tools/dotc/core/TypeErrors.scala

+2-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@ class MissingType(pre: Type, name: Name) extends TypeError {
4141
}
4242
}
4343

44-
class RecursionOverflow(val op: String, details: => String, val previous: Throwable, val weight: Int) extends TypeError {
44+
class RecursionOverflow(val op: String, details: => String, val previous: Throwable, val weight: Int)
45+
extends TypeError {
4546

4647
def explanation: String = s"$op $details"
4748

compiler/src/dotty/tools/dotc/transform/PostTyper.scala

-15
Original file line numberDiff line numberDiff line change
@@ -430,21 +430,6 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisPhase
430430
case tpe => tpe
431431
}
432432
)
433-
case Import(expr, selectors) =>
434-
val exprTpe = expr.tpe
435-
val seen = mutable.Set.empty[Name]
436-
437-
def checkIdent(sel: untpd.ImportSelector): Unit =
438-
if !exprTpe.member(sel.name).exists
439-
&& !exprTpe.member(sel.name.toTypeName).exists then
440-
report.error(NotAMember(exprTpe, sel.name, "value"), sel.imported.srcPos)
441-
if seen.contains(sel.name) then
442-
report.error(ImportRenamedTwice(sel.imported), sel.imported.srcPos)
443-
seen += sel.name
444-
445-
for sel <- selectors do
446-
if !sel.isWildcard then checkIdent(sel)
447-
super.transform(tree)
448433
case Typed(Ident(nme.WILDCARD), _) =>
449434
withMode(Mode.Pattern)(super.transform(tree))
450435
// The added mode signals that bounds in a pattern need not

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

+22
Original file line numberDiff line numberDiff line change
@@ -1429,6 +1429,27 @@ trait Checking {
14291429
em"""Implementation restriction: cannot generate CanThrow capability for this kind of catch.
14301430
|CanThrow capabilities can only be generated $req.""",
14311431
pat.srcPos)
1432+
1433+
/** (1) Check that every named import selector refers to a type or value member of the
1434+
* qualifier type.
1435+
* (2) Check that no import selector is renamed more than once.
1436+
*/
1437+
def checkImportSelectors(qualType: Type, selectors: List[untpd.ImportSelector])(using Context): Unit =
1438+
val seen = mutable.Set.empty[Name]
1439+
1440+
def checkIdent(sel: untpd.ImportSelector): Unit =
1441+
if sel.name != nme.ERROR
1442+
&& !qualType.member(sel.name).exists
1443+
&& !qualType.member(sel.name.toTypeName).exists
1444+
then
1445+
report.error(NotAMember(qualType, sel.name, "value"), sel.imported.srcPos)
1446+
if seen.contains(sel.name) then
1447+
report.error(ImportRenamedTwice(sel.imported), sel.imported.srcPos)
1448+
seen += sel.name
1449+
1450+
for sel <- selectors do
1451+
if !sel.isWildcard then checkIdent(sel)
1452+
end checkImportSelectors
14321453
}
14331454

14341455
trait ReChecking extends Checking {
@@ -1466,4 +1487,5 @@ trait NoChecking extends ReChecking {
14661487
override def checkMembersOK(tp: Type, pos: SrcPos)(using Context): Type = tp
14671488
override def checkInInlineContext(what: String, pos: SrcPos)(using Context): Unit = ()
14681489
override def checkValidInfix(tree: untpd.InfixOp, meth: Symbol)(using Context): Unit = ()
1490+
override def checkImportSelectors(qualType: Type, selectors: List[untpd.ImportSelector])(using Context): Unit = ()
14691491
}

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

+1
Original file line numberDiff line numberDiff line change
@@ -2606,6 +2606,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
26062606
val expr1 = typedImportQualifier(imp, typedExpr(_, _)(using ctx.withOwner(sym)))
26072607
checkLegalImportPath(expr1)
26082608
val selectors1 = typedSelectors(imp.selectors)
2609+
checkImportSelectors(expr1.tpe, selectors1)
26092610
assignType(cpy.Import(imp)(expr1, selectors1), sym)
26102611

26112612
def typedExport(exp: untpd.Export)(using Context): Tree =

tests/neg-custom-args/jdk-9-app.check

+4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
-- [E008] Not Found Error: tests/neg-custom-args/jdk-9-app.scala:1:17 --------------------------------------------------
2+
1 |import java.lang.ProcessHandle // error: not a member
3+
| ^^^^^^^^^^^^^
4+
| value ProcessHandle is not a member of java.lang
15
-- [E006] Not Found Error: tests/neg-custom-args/jdk-9-app.scala:4:10 --------------------------------------------------
26
4 | println(ProcessHandle.current().pid()) // error: not found
37
| ^^^^^^^^^^^^^

tests/neg-custom-args/jdk-9-app.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import java.lang.ProcessHandle
1+
import java.lang.ProcessHandle // error: not a member
22

33
object Jdk9App extends App {
44
println(ProcessHandle.current().pid()) // error: not found

tests/neg/deriving.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import reflect.Generic
1+
import reflect.Generic // error: Generic is not a member of reflect
22

33
sealed trait A derives Generic // error: cannot take shape, it has anonymous or inaccessible subclasses
44

tests/neg/i15468.scala

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
object Test {
2+
val s = ""
3+
import s.{length => x, size => y} // error: size is not a member of s
4+
locally(x) // ok
5+
locally(size) // error: Not found: y
6+
}

tests/neg/i6056.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
object i0{
2-
import i0.i0 // error
2+
import i0.i0 // error // error
33
def i0={
44
import _ // error
55
import // error

tests/neg/implicitDefs.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package test
22

3-
import Predef.{any2stringadd as _, StringAdd as _, *}
3+
import Predef.{any2stringadd as _, *}
44

55
object implicitDefs {
66

tests/neg/language-import.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ object a:
33
import l.noAutoTupling // error
44
import l.experimental.genericNumberLiterals // error
55
val scala = c
6-
import scala.language.noAutoTupling // error
6+
import scala.language.noAutoTupling // error // error
77
val language = b
88
import language.experimental.genericNumberLiterals // error
99

tests/neg/parser-stability-23.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
object i0 {
2-
import Ordering.{ implicitly as } (true: Boolean) match { case _: i1 as true } // error // error
2+
import Ordering.{ implicitly as } (true: Boolean) match { case _: i1 as true } // error // error // error
33
}

tests/neg/rootImplicits.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package test
22

3-
import Predef.{any2stringadd as _, StringAdd as _, *}
3+
import Predef.{any2stringadd as _, *}
44

55
object rootImplicits {
66

0 commit comments

Comments
 (0)