Skip to content

Commit

Permalink
Merge pull request #15477 from dotty-staging/fix-15468
Browse files Browse the repository at this point in the history
Check import selectors at Typer
  • Loading branch information
odersky authored Jun 19, 2022
2 parents f58c158 + d73fc84 commit 1f813bc
Show file tree
Hide file tree
Showing 13 changed files with 42 additions and 23 deletions.
3 changes: 2 additions & 1 deletion compiler/src/dotty/tools/dotc/core/TypeErrors.scala
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ class MissingType(pre: Type, name: Name) extends TypeError {
}
}

class RecursionOverflow(val op: String, details: => String, val previous: Throwable, val weight: Int) extends TypeError {
class RecursionOverflow(val op: String, details: => String, val previous: Throwable, val weight: Int)
extends TypeError {

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

Expand Down
15 changes: 0 additions & 15 deletions compiler/src/dotty/tools/dotc/transform/PostTyper.scala
Original file line number Diff line number Diff line change
Expand Up @@ -430,21 +430,6 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisPhase
case tpe => tpe
}
)
case Import(expr, selectors) =>
val exprTpe = expr.tpe
val seen = mutable.Set.empty[Name]

def checkIdent(sel: untpd.ImportSelector): Unit =
if !exprTpe.member(sel.name).exists
&& !exprTpe.member(sel.name.toTypeName).exists then
report.error(NotAMember(exprTpe, sel.name, "value"), sel.imported.srcPos)
if seen.contains(sel.name) then
report.error(ImportRenamedTwice(sel.imported), sel.imported.srcPos)
seen += sel.name

for sel <- selectors do
if !sel.isWildcard then checkIdent(sel)
super.transform(tree)
case Typed(Ident(nme.WILDCARD), _) =>
withMode(Mode.Pattern)(super.transform(tree))
// The added mode signals that bounds in a pattern need not
Expand Down
22 changes: 22 additions & 0 deletions compiler/src/dotty/tools/dotc/typer/Checking.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1429,6 +1429,27 @@ trait Checking {
em"""Implementation restriction: cannot generate CanThrow capability for this kind of catch.
|CanThrow capabilities can only be generated $req.""",
pat.srcPos)

/** (1) Check that every named import selector refers to a type or value member of the
* qualifier type.
* (2) Check that no import selector is renamed more than once.
*/
def checkImportSelectors(qualType: Type, selectors: List[untpd.ImportSelector])(using Context): Unit =
val seen = mutable.Set.empty[Name]

def checkIdent(sel: untpd.ImportSelector): Unit =
if sel.name != nme.ERROR
&& !qualType.member(sel.name).exists
&& !qualType.member(sel.name.toTypeName).exists
then
report.error(NotAMember(qualType, sel.name, "value"), sel.imported.srcPos)
if seen.contains(sel.name) then
report.error(ImportRenamedTwice(sel.imported), sel.imported.srcPos)
seen += sel.name

for sel <- selectors do
if !sel.isWildcard then checkIdent(sel)
end checkImportSelectors
}

trait ReChecking extends Checking {
Expand Down Expand Up @@ -1466,4 +1487,5 @@ trait NoChecking extends ReChecking {
override def checkMembersOK(tp: Type, pos: SrcPos)(using Context): Type = tp
override def checkInInlineContext(what: String, pos: SrcPos)(using Context): Unit = ()
override def checkValidInfix(tree: untpd.InfixOp, meth: Symbol)(using Context): Unit = ()
override def checkImportSelectors(qualType: Type, selectors: List[untpd.ImportSelector])(using Context): Unit = ()
}
1 change: 1 addition & 0 deletions compiler/src/dotty/tools/dotc/typer/Typer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2606,6 +2606,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
val expr1 = typedImportQualifier(imp, typedExpr(_, _)(using ctx.withOwner(sym)))
checkLegalImportPath(expr1)
val selectors1 = typedSelectors(imp.selectors)
checkImportSelectors(expr1.tpe, selectors1)
assignType(cpy.Import(imp)(expr1, selectors1), sym)

def typedExport(exp: untpd.Export)(using Context): Tree =
Expand Down
4 changes: 4 additions & 0 deletions tests/neg-custom-args/jdk-9-app.check
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
-- [E008] Not Found Error: tests/neg-custom-args/jdk-9-app.scala:1:17 --------------------------------------------------
1 |import java.lang.ProcessHandle // error: not a member
| ^^^^^^^^^^^^^
| value ProcessHandle is not a member of java.lang
-- [E006] Not Found Error: tests/neg-custom-args/jdk-9-app.scala:4:10 --------------------------------------------------
4 | println(ProcessHandle.current().pid()) // error: not found
| ^^^^^^^^^^^^^
Expand Down
2 changes: 1 addition & 1 deletion tests/neg-custom-args/jdk-9-app.scala
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import java.lang.ProcessHandle
import java.lang.ProcessHandle // error: not a member

object Jdk9App extends App {
println(ProcessHandle.current().pid()) // error: not found
Expand Down
2 changes: 1 addition & 1 deletion tests/neg/deriving.scala
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import reflect.Generic
import reflect.Generic // error: Generic is not a member of reflect

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

Expand Down
6 changes: 6 additions & 0 deletions tests/neg/i15468.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
object Test {
val s = ""
import s.{length => x, size => y} // error: size is not a member of s
locally(x) // ok
locally(size) // error: Not found: y
}
2 changes: 1 addition & 1 deletion tests/neg/i6056.scala
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
object i0{
import i0.i0 // error
import i0.i0 // error // error
def i0={
import _ // error
import // error
Expand Down
2 changes: 1 addition & 1 deletion tests/neg/implicitDefs.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package test

import Predef.{any2stringadd as _, StringAdd as _, *}
import Predef.{any2stringadd as _, *}

object implicitDefs {

Expand Down
2 changes: 1 addition & 1 deletion tests/neg/language-import.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ object a:
import l.noAutoTupling // error
import l.experimental.genericNumberLiterals // error
val scala = c
import scala.language.noAutoTupling // error
import scala.language.noAutoTupling // error // error
val language = b
import language.experimental.genericNumberLiterals // error

Expand Down
2 changes: 1 addition & 1 deletion tests/neg/parser-stability-23.scala
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
object i0 {
import Ordering.{ implicitly as } (true: Boolean) match { case _: i1 as true } // error // error
import Ordering.{ implicitly as } (true: Boolean) match { case _: i1 as true } // error // error // error
}
2 changes: 1 addition & 1 deletion tests/neg/rootImplicits.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package test

import Predef.{any2stringadd as _, StringAdd as _, *}
import Predef.{any2stringadd as _, *}

object rootImplicits {

Expand Down

0 comments on commit 1f813bc

Please sign in to comment.