Skip to content

Commit ed5ecac

Browse files
authored
Merge pull request #11244 from dotty-staging/change-imports
Allow new import syntax
2 parents bea5619 + 068ad0a commit ed5ecac

File tree

1,555 files changed

+2586
-2429
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

1,555 files changed

+2586
-2429
lines changed

bench/tests/Vector.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ package immutable
1212

1313
import scala.annotation.unchecked.uncheckedVariance
1414
import scala.compat.Platform
15-
import scala.collection.generic._
15+
import scala.collection.generic.*
1616
import scala.collection.mutable.Builder
1717
import compiletime.uninitialized
1818

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
object PowerInlined {
2-
import PowerMacro._
2+
import PowerMacro.*
33

44
power(1, 5.0) // 1 quotes to unpickle
55
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
object PowerInlined {
2-
import PowerMacro._
2+
import PowerMacro.*
33

44
power(1, 5.0) // 1 quotes to unpickle
55
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ trait TreeInfo[T >: Untyped <: Type] { self: Trees.Instance[T] =>
179179
case _ => false
180180
}
181181

182-
/** Is this argument node of the form <expr> : _*, or is it a reference to
182+
/** Is this argument node of the form <expr> *, or is it a reference to
183183
* such an argument ? The latter case can happen when an argument is lifted.
184184
*/
185185
def isWildcardStarArg(tree: Tree)(using Context): Boolean = unbind(tree) match {

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1027,6 +1027,7 @@ object Trees {
10271027
type Template = Trees.Template[T]
10281028
type Import = Trees.Import[T]
10291029
type Export = Trees.Export[T]
1030+
type ImportOrExport = Trees.ImportOrExport[T]
10301031
type PackageDef = Trees.PackageDef[T]
10311032
type Annotated = Trees.Annotated[T]
10321033
type Thicket = Trees.Thicket[T]

compiler/src/dotty/tools/dotc/parsing/Parsers.scala

Lines changed: 83 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -3066,8 +3066,8 @@ object Parsers {
30663066

30673067
type ImportConstr = (Tree, List[ImportSelector]) => Tree
30683068

3069-
/** Import ::= `import' [`given'] [ImportExpr {`,' ImportExpr}
3070-
* Export ::= `export' [`given'] [ImportExpr {`,' ImportExpr}
3069+
/** Import ::= `import' ImportExpr {‘,’ ImportExpr}
3070+
* Export ::= `export' ImportExpr {‘,’ ImportExpr}
30713071
*/
30723072
def importClause(leading: Token, mkTree: ImportConstr): List[Tree] = {
30733073
val offset = accept(leading)
@@ -3097,48 +3097,62 @@ object Parsers {
30973097
ctx.compilationUnit.sourceVersion = Some(SourceVersion.valueOf(imported.toString))
30983098
Import(tree, selectors)
30993099

3100-
/** ImportExpr ::= SimpleRef {‘.’ id} ‘.’ ImportSpec
3101-
* ImportSpec ::= id
3102-
* | ‘_’
3103-
* | ‘given’
3104-
* | ‘{’ ImportSelectors) ‘}’
3105-
*/
3106-
def importExpr(mkTree: ImportConstr): () => Tree = {
3107-
3108-
/** '_' */
3109-
def wildcardSelectorId() = atSpan(in.skipToken()) { Ident(nme.WILDCARD) }
3110-
def givenSelectorId(start: Offset) = atSpan(start) { Ident(nme.EMPTY) }
3100+
/** ImportExpr ::= SimpleRef {‘.’ id} ‘.’ ImportSpec
3101+
* | SimpleRef ‘as’ id
3102+
* ImportSpec ::= NamedSelector
3103+
* | WildcardSelector
3104+
* | ‘{’ ImportSelectors ‘}’
3105+
* ImportSelectors ::= NamedSelector [‘,’ ImportSelectors]
3106+
* | WildCardSelector {‘,’ WildCardSelector}
3107+
* NamedSelector ::= id [‘as’ (id | ‘_’)]
3108+
* WildCardSelector ::= ‘*' | ‘given’ [InfixType]
3109+
*/
3110+
def importExpr(mkTree: ImportConstr): () => Tree =
3111+
3112+
/** ‘*' | ‘_' */
3113+
def wildcardSelector() =
3114+
if in.token == USCORE && sourceVersion.isAtLeast(`3.1`) then
3115+
report.errorOrMigrationWarning(
3116+
em"`_` is no longer supported for a wildcard import; use `*` instead${rewriteNotice("3.1")}",
3117+
in.sourcePos())
3118+
patch(source, Span(in.offset, in.offset + 1), "*")
3119+
ImportSelector(atSpan(in.skipToken()) { Ident(nme.WILDCARD) })
3120+
3121+
/** 'given [InfixType]' */
3122+
def givenSelector() =
3123+
ImportSelector(
3124+
atSpan(in.skipToken()) { Ident(nme.EMPTY) },
3125+
bound =
3126+
if canStartTypeTokens.contains(in.token) then rejectWildcardType(infixType())
3127+
else EmptyTree)
3128+
3129+
/** id [‘as’ (id | ‘_’) */
3130+
def namedSelector(from: Ident) =
3131+
if in.token == ARROW || isIdent(nme.as) then
3132+
if in.token == ARROW && sourceVersion.isAtLeast(`3.1`) then
3133+
report.errorOrMigrationWarning(
3134+
em"The import renaming `a => b` is no longer supported ; use `a as b` instead${rewriteNotice("3.1")}",
3135+
in.sourcePos())
3136+
patch(source, Span(in.offset, in.offset + 2),
3137+
if testChar(in.offset - 1, ' ') && testChar(in.offset + 2, ' ') then "as"
3138+
else " as ")
3139+
atSpan(startOffset(from), in.skipToken()) {
3140+
val to = if in.token == USCORE then wildcardIdent() else termIdent()
3141+
ImportSelector(from, if to.name == nme.ERROR then EmptyTree else to)
3142+
}
3143+
else ImportSelector(from)
31113144

3112-
/** ImportSelectors ::= id [‘=>’ id | ‘=>’ ‘_’] [‘,’ ImportSelectors]
3113-
* | WildCardSelector {‘,’ WildCardSelector}
3114-
* WildCardSelector ::= ‘given’ [InfixType]
3115-
* | ‘_'
3116-
*/
31173145
def importSelectors(idOK: Boolean): List[ImportSelector] =
3118-
val isWildcard = in.token == USCORE || in.token == GIVEN
3146+
val isWildcard = in.token == USCORE || in.token == GIVEN || isIdent(nme.raw.STAR)
31193147
val selector = atSpan(in.offset) {
31203148
in.token match
3121-
case USCORE =>
3122-
ImportSelector(wildcardSelectorId())
3123-
case GIVEN =>
3124-
val start = in.skipToken()
3125-
if in.token == USCORE then
3126-
deprecationWarning(em"`given _` is deprecated in imports; replace with just `given`", start)
3127-
in.nextToken()
3128-
ImportSelector(givenSelectorId(start)) // Let the selector span all of `given`; needed for -Ytest-pickler
3129-
else if canStartTypeTokens.contains(in.token) then
3130-
ImportSelector(givenSelectorId(start), bound = rejectWildcardType(infixType()))
3131-
else
3132-
ImportSelector(givenSelectorId(start))
3149+
case USCORE => wildcardSelector()
3150+
case GIVEN => givenSelector()
31333151
case _ =>
3134-
val from = termIdent()
3135-
if !idOK then syntaxError(i"named imports cannot follow wildcard imports")
3136-
if in.token == ARROW then
3137-
atSpan(startOffset(from), in.skipToken()) {
3138-
val to = if in.token == USCORE then wildcardIdent() else termIdent()
3139-
ImportSelector(from, if to.name == nme.ERROR then EmptyTree else to)
3140-
}
3141-
else ImportSelector(from)
3152+
if isIdent(nme.raw.STAR) then wildcardSelector()
3153+
else
3154+
if !idOK then syntaxError(i"named imports cannot follow wildcard imports")
3155+
namedSelector(termIdent())
31423156
}
31433157
val rest =
31443158
if in.token == COMMA then
@@ -3149,26 +3163,36 @@ object Parsers {
31493163
selector :: rest
31503164

31513165
def importSelection(qual: Tree): Tree =
3152-
accept(DOT)
3153-
in.token match
3154-
case USCORE =>
3155-
mkTree(qual, ImportSelector(wildcardSelectorId()) :: Nil)
3156-
case GIVEN =>
3157-
mkTree(qual, ImportSelector(givenSelectorId(in.skipToken())) :: Nil)
3158-
case LBRACE =>
3159-
mkTree(qual, inBraces(importSelectors(idOK = true)))
3160-
case _ =>
3161-
val start = in.offset
3162-
val name = ident()
3163-
if in.token == DOT then
3164-
importSelection(atSpan(startOffset(qual), start) { Select(qual, name) })
3165-
else
3166-
atSpan(startOffset(qual)) {
3167-
mkTree(qual, ImportSelector(atSpan(start) { Ident(name) }) :: Nil)
3168-
}
3169-
3170-
() => importSelection(simpleRef())
3171-
}
3166+
if in.isIdent(nme.as) && qual.isInstanceOf[RefTree] then
3167+
qual match
3168+
case Select(qual1, name) =>
3169+
val from = Ident(name).withSpan(Span(qual.span.point, qual.span.end, 0))
3170+
mkTree(qual1, namedSelector(from) :: Nil)
3171+
case qual: Ident =>
3172+
mkTree(EmptyTree, namedSelector(qual) :: Nil)
3173+
else
3174+
accept(DOT)
3175+
in.token match
3176+
case USCORE =>
3177+
mkTree(qual, wildcardSelector() :: Nil)
3178+
case GIVEN =>
3179+
mkTree(qual, givenSelector() :: Nil)
3180+
case LBRACE =>
3181+
mkTree(qual, inBraces(importSelectors(idOK = true)))
3182+
case _ =>
3183+
if isIdent(nme.raw.STAR) then
3184+
mkTree(qual, wildcardSelector() :: Nil)
3185+
else
3186+
val start = in.offset
3187+
val name = ident()
3188+
if in.token == DOT then
3189+
importSelection(atSpan(startOffset(qual), start) { Select(qual, name) })
3190+
else
3191+
mkTree(qual, namedSelector(atSpan(start) { Ident(name) }) :: Nil)
3192+
end importSelection
3193+
3194+
() => atSpan(in.offset) { importSelection(simpleRef()) }
3195+
end importExpr
31723196

31733197
/** Def ::= val PatDef
31743198
* | var VarDef

compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -340,9 +340,13 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
340340

341341
def selectorText(sel: untpd.ImportSelector): Text =
342342
val id: Text =
343-
if sel.isGiven then keywordText("given") else toText(sel.imported)
343+
if sel.isGiven then keywordText("given")
344+
else sel.imported.name match
345+
case nme.WILDCARD => "*"
346+
case nme.raw.STAR => "`*`"
347+
case name => toText(name)
344348
val rename: Text =
345-
if sel.renamed.isEmpty then "" else Str(" => ") ~ toText(sel.renamed)
349+
if sel.renamed.isEmpty then "" else Str(" as ") ~ toText(sel.renamed)
346350
val bound: Text =
347351
if sel.bound.isEmpty then ""
348352
else if sel.isGiven then Str(" ") ~ toText(sel.bound)

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ class FirstTransform extends MiniPhase with InfoTransformer { thisPhase =>
150150
}
151151

152152
override def transformOther(tree: Tree)(using Context): Tree = tree match {
153-
case tree: ImportOrExport[_] => EmptyTree
153+
case tree: ImportOrExport => EmptyTree
154154
case tree: NamedArg => transformAllDeep(tree.arg)
155155
case tree => if (tree.isType) toTypeTree(tree) else tree
156156
}

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

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -693,7 +693,7 @@ class Namer { typer: Typer =>
693693
// make sure testing contexts are not captured by completers
694694
assert(!ictx.reporter.isInstanceOf[ExploringReporter])
695695

696-
protected def typeSig(sym: Symbol): Type = original match {
696+
protected def typeSig(sym: Symbol): Type = original match
697697
case original: ValDef =>
698698
if (sym.is(Module)) moduleValSig(sym)
699699
else valOrDefDefSig(original, sym, Nil, identity)(using localContext(sym).setNewScope)
@@ -702,16 +702,12 @@ class Namer { typer: Typer =>
702702
nestedTyper(sym) = typer1
703703
typer1.defDefSig(original, sym)(using localContext(sym).setTyper(typer1))
704704
case imp: Import =>
705-
try {
706-
val expr1 = typedAheadExpr(imp.expr, AnySelectionProto)
705+
try
706+
val expr1 = typedImportQualifier(imp, typedAheadExpr)
707707
ImportType(expr1)
708-
}
709-
catch {
710-
case ex: CyclicReference =>
711-
typr.println(s"error while completing ${imp.expr}")
712-
throw ex
713-
}
714-
}
708+
catch case ex: CyclicReference =>
709+
typr.println(s"error while completing ${imp.expr}")
710+
throw ex
715711

716712
final override def complete(denot: SymDenotation)(using Context): Unit = {
717713
if (Config.showCompletions && ctx.typerState != creationContext.typerState) {
@@ -987,6 +983,10 @@ class Namer { typer: Typer =>
987983
def exportForwarders(exp: Export): List[tpd.MemberDef] = {
988984
val buf = new mutable.ListBuffer[tpd.MemberDef]
989985
val Export(expr, selectors) = exp
986+
if expr.isEmpty then
987+
report.error(em"Export selector must have prefix and `.`", exp.srcPos)
988+
return Nil
989+
990990
val path = typedAheadExpr(expr, AnySelectionProto)
991991
checkLegalExportPath(path, selectors)
992992
lazy val wildcardBound = importBound(selectors, isGiven = false)

0 commit comments

Comments
 (0)