Skip to content

Commit

Permalink
Allow import x.{*, given} under -Xsource:3
Browse files Browse the repository at this point in the history
Imagine a Scala 3 library containing:
```
object A {
  val a: Int = 1
  given b: Int = 2
}
```
To import all members of `A` from Scala 2, we write `import A.*`,
but to do the same from Scala 3, we need to write `import A.{*, given}`
instead. This complicates cross-compilation for projects which depend on
Scala 3 libraries (unless these libraries exclusively use `implicit`
which is not something we want to encourage).

This commit remedies this by allowing `import x.{*, given}` (and `import
x.{given, *}`), this is easy to do since we can just pretend the user
wrote `import x.*` which will give us both regular and given members in
Scala 2 code and therefore match the semantics of Scala 3.
  • Loading branch information
smarter committed Aug 10, 2021
1 parent 64ea1d1 commit db5ff02
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 1 deletion.
29 changes: 29 additions & 0 deletions src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
Expand Up @@ -2693,6 +2693,30 @@ self =>
})
}

/** Treat an import of `*, given` or `given, *` as if it was an import of `*`
* since the former in Scala 3 has the same semantics as the latter in Scala 2.
*/
def scala3FullSelector(): ImportSelector /* | Null */ = {
if (in.token != IDENTIFIER)
return null
val other =
if (in.name == raw.STAR)
nme.`given`
else if (in.name == nme.`given`)
raw.STAR
else
return null

if (lookingAhead(in.token == COMMA && {
in.nextToken(); in.token == IDENTIFIER && in.name == other })) {
val start = in.offset
in.nextToken() // `*` or `given`
in.nextToken() // `,`
in.nextToken() // `given` or `*`
ImportSelector(nme.WILDCARD, start, null, -1)
} else null
}

/** {{{
* ImportSelectors ::= `{` {ImportSelector `,`} (ImportSelector | `_`) `}`
* }}}
Expand All @@ -2712,6 +2736,11 @@ self =>
* }}}
*/
def importSelector(): ImportSelector = {
if (settings.isScala3) {
val fullSelector = scala3FullSelector()
if (fullSelector != null) return fullSelector
}

val start = in.offset
val bbq = in.token == BACKQUOTED_IDENT
val name = wildcardOrIdent()
Expand Down
2 changes: 1 addition & 1 deletion test/files/pos/import-future.scala
Expand Up @@ -26,7 +26,7 @@ class C {

object starring {

import scala.concurrent.*, duration.{Duration as D, *}, ExecutionContext.Implicits.*
import scala.concurrent.{*, given}, duration.{Duration as D, given, *}, ExecutionContext.Implicits.*

val f = Future(42)
val r = Await.result(f, D.Inf)
Expand Down

0 comments on commit db5ff02

Please sign in to comment.