Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support Scala 3 wildcard and renaming imports under -Xsource:3 #9582

Merged
merged 1 commit into from Apr 20, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
45 changes: 28 additions & 17 deletions src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
Expand Up @@ -2564,19 +2564,27 @@ self =>
def loop(expr: Tree): Tree = {
expr setPos expr.pos.makeTransparent
val selectors: List[ImportSelector] = in.token match {
case USCORE => List(wildImportSelector()) // import foo.bar._;
case LBRACE => importSelectors() // import foo.bar.{ x, y, z }
case _ =>
val nameOffset = in.offset
val name = ident()
if (in.token == DOT) {
// import foo.bar.ident.<unknown> and so create a select node and recurse.
val t = atPos(start, if (name == nme.ERROR) in.offset else nameOffset)(Select(expr, name))
in.nextToken()
return loop(t)
case USCORE =>
List(wildImportSelector()) // import foo.bar._
case IDENTIFIER if currentRun.isScala3 && in.name == raw.STAR =>
List(wildImportSelector()) // import foo.bar.*
case LBRACE =>
importSelectors() // import foo.bar.{ x, y, z }
case _ =>
if (settings.isScala3 && lookingAhead { isRawIdent && in.name == nme.as })
List(importSelector()) // import foo.bar as baz
else {
val nameOffset = in.offset
val name = ident()
if (in.token == DOT) {
// import foo.bar.ident.<unknown> and so create a select node and recurse.
val t = atPos(start, if (name == nme.ERROR) in.offset else nameOffset)(Select(expr, name))
in.nextToken()
return loop(t)
}
// import foo.bar.Baz;
else List(makeImportSelector(name, nameOffset))
}
// import foo.bar.Baz;
else List(makeImportSelector(name, nameOffset))
}
// reaching here means we're done walking.
atPos(start)(Import(expr, selectors))
Expand Down Expand Up @@ -2619,17 +2627,20 @@ self =>
val bbq = in.token == BACKQUOTED_IDENT
val name = wildcardOrIdent()
var renameOffset = -1
val rename = in.token match {
case ARROW =>

val rename =
if (in.token == ARROW || (settings.isScala3 && isRawIdent && in.name == nme.as)) {
in.nextToken()
renameOffset = in.offset
if (name == nme.WILDCARD && !bbq) syntaxError(renameOffset, "Wildcard import cannot be renamed")
wildcardOrIdent()
case _ if name == nme.WILDCARD && !bbq => null
case _ =>
}
else if (name == nme.WILDCARD && !bbq) null
else {
renameOffset = start
name
}
}

ImportSelector(name, start, rename, renameOffset)
}

Expand Down
3 changes: 3 additions & 0 deletions src/reflect/scala/reflect/internal/StdNames.scala
Expand Up @@ -658,6 +658,9 @@ trait StdNames {
val long2Long: NameType = nameType("long2Long")
val boolean2Boolean: NameType = nameType("boolean2Boolean")

// Scala 3 import syntax
val as: NameType = nameType("as")

// Compiler utilized names

val AnnotatedType: NameType = nameType("AnnotatedType")
Expand Down
4 changes: 4 additions & 0 deletions test/files/neg/import-future.check
@@ -0,0 +1,4 @@
import-future.scala:15: error: not found: value unrelated
unrelated(1) // error
^
1 error
27 changes: 27 additions & 0 deletions test/files/neg/import-future.scala
@@ -0,0 +1,27 @@
// scalac: -Xsource:3
//

class D {
def *(y: Int): Int = y
def unrelated(y: Int): Int = y
}

object Test {
val d = new D

def one: Int = {
import d.`*`

unrelated(1) // error

*(1)
}

def two: Int = {
import d.*

unrelated(1)

*(1)
}
}
25 changes: 25 additions & 0 deletions test/files/pos/import-future.scala
@@ -0,0 +1,25 @@
// scalac: -Xsource:3
//

import java.io as jio
import scala.{collection as c}

import c.mutable as mut
import mut.ArrayBuffer as Buf

object O {
val x: jio.IOException = ???
val y = Buf(1, 2, 3)

type OString = String
def foo22(x: Int) = x
}

class C {
import O.{ foo22 as foo, OString as OS }
println(foo(22))
val s: OS = ""

import mut.*
val ab = ArrayBuffer(1)
}