Skip to content

Commit a87600c

Browse files
committed
Refactor imports and implement new given import syntax
The new given import syntax required a wholesale refactorings of imports. It's shorter, clearer, and more strictly typed now.
1 parent 749932a commit a87600c

Some content is hidden

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

42 files changed

+461
-455
lines changed

compiler/src/dotty/tools/dotc/Run.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,8 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint
5454
.setTyperState(new TyperState(ctx.typerState))
5555
.setFreshNames(new FreshNameCreator.Default)
5656
ctx.initialize()(start) // re-initialize the base context with start
57-
def addImport(ctx: Context, refFn: () => TermRef) =
58-
ctx.fresh.setImportInfo(ImportInfo.rootImport(refFn)(ctx))
57+
def addImport(ctx: Context, rootRef: ImportInfo.RootRef) =
58+
ctx.fresh.setImportInfo(ImportInfo.rootImport(rootRef)(ctx))
5959
defn.RootImportFns.foldLeft(start.setRun(this))(addImport)
6060
}
6161

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

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -476,17 +476,18 @@ object desugar {
476476
stat
477477
}
478478
// The Identifiers defined by a case
479-
def caseIds(tree: Tree) = tree match {
479+
def caseIds(tree: Tree): List[Ident] = tree match {
480480
case tree: MemberDef => Ident(tree.name.toTermName) :: Nil
481-
case PatDef(_, ids, _, _) => ids
481+
case PatDef(_, ids: List[Ident] @ unchecked, _, _) => ids
482482
}
483483
val stats = impl.body.map(expandConstructor)
484484
if (isEnum) {
485485
val (enumCases, enumStats) = stats.partition(DesugarEnums.isEnumCase)
486486
if (enumCases.isEmpty)
487487
ctx.error("Enumerations must constain at least one case", namePos)
488488
val enumCompanionRef = TermRefTree()
489-
val enumImport = Import(importGiven = false, enumCompanionRef, enumCases.flatMap(caseIds))
489+
val enumImport =
490+
Import(enumCompanionRef, enumCases.flatMap(caseIds).map(ImportSelector(_)))
490491
(enumImport :: enumStats, enumCases, enumCompanionRef)
491492
}
492493
else (stats, Nil, EmptyTree)

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -360,7 +360,7 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
360360
def statPurity(tree: Tree)(implicit ctx: Context): PurityLevel = unsplice(tree) match {
361361
case EmptyTree
362362
| TypeDef(_, _)
363-
| Import(_, _, _)
363+
| Import(_, _)
364364
| DefDef(_, _, _, _, _) =>
365365
Pure
366366
case vdef @ ValDef(_, _, _) =>

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

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -803,7 +803,7 @@ object Trees {
803803
* where a selector is either an untyped `Ident`, `name` or
804804
* an untyped thicket consisting of `name` and `rename`.
805805
*/
806-
case class Import[-T >: Untyped] private[ast] (importGiven: Boolean, expr: Tree[T], selectors: List[Tree[Untyped]])(implicit @constructorOnly src: SourceFile)
806+
case class Import[-T >: Untyped] private[ast] (expr: Tree[T], selectors: List[untpd.ImportSelector])(implicit @constructorOnly src: SourceFile)
807807
extends DenotingTree[T] {
808808
type ThisTree[-T >: Untyped] = Import[T]
809809
}
@@ -1191,9 +1191,9 @@ object Trees {
11911191
case tree: Template if (constr eq tree.constr) && (parents eq tree.parents) && (derived eq tree.derived) && (self eq tree.self) && (body eq tree.unforcedBody) => tree
11921192
case tree => finalize(tree, untpd.Template(constr, parents, derived, self, body)(sourceFile(tree)))
11931193
}
1194-
def Import(tree: Tree)(importGiven: Boolean, expr: Tree, selectors: List[untpd.Tree])(implicit ctx: Context): Import = tree match {
1195-
case tree: Import if (importGiven == tree.importGiven) && (expr eq tree.expr) && (selectors eq tree.selectors) => tree
1196-
case _ => finalize(tree, untpd.Import(importGiven, expr, selectors)(sourceFile(tree)))
1194+
def Import(tree: Tree)(expr: Tree, selectors: List[untpd.ImportSelector])(implicit ctx: Context): Import = tree match {
1195+
case tree: Import if (expr eq tree.expr) && (selectors eq tree.selectors) => tree
1196+
case _ => finalize(tree, untpd.Import(expr, selectors)(sourceFile(tree)))
11971197
}
11981198
def PackageDef(tree: Tree)(pid: RefTree, stats: List[Tree])(implicit ctx: Context): PackageDef = tree match {
11991199
case tree: PackageDef if (pid eq tree.pid) && (stats eq tree.stats) => tree
@@ -1335,8 +1335,8 @@ object Trees {
13351335
cpy.TypeDef(tree)(name, transform(rhs))
13361336
case tree @ Template(constr, parents, self, _) if tree.derived.isEmpty =>
13371337
cpy.Template(tree)(transformSub(constr), transform(tree.parents), Nil, transformSub(self), transformStats(tree.body))
1338-
case Import(importGiven, expr, selectors) =>
1339-
cpy.Import(tree)(importGiven, transform(expr), selectors)
1338+
case Import(expr, selectors) =>
1339+
cpy.Import(tree)(transform(expr), selectors)
13401340
case PackageDef(pid, stats) =>
13411341
cpy.PackageDef(tree)(transformSub(pid), transformStats(stats)(localCtx))
13421342
case Annotated(arg, annot) =>
@@ -1455,7 +1455,7 @@ object Trees {
14551455
this(x, rhs)
14561456
case tree @ Template(constr, parents, self, _) if tree.derived.isEmpty =>
14571457
this(this(this(this(x, constr), parents), self), tree.body)
1458-
case Import(_, expr, _) =>
1458+
case Import(expr, _) =>
14591459
this(x, expr)
14601460
case PackageDef(pid, stats) =>
14611461
this(this(x, pid), stats)(localCtx)

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

Lines changed: 14 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -333,8 +333,8 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
333333
Block(cdef :: Nil, New(cls.typeRef, Nil))
334334
}
335335

336-
def Import(importGiven: Boolean, expr: Tree, selectors: List[untpd.Tree])(implicit ctx: Context): Import =
337-
ta.assignType(untpd.Import(importGiven, expr, selectors), ctx.newImportSymbol(ctx.owner, expr))
336+
def Import(expr: Tree, selectors: List[untpd.ImportSelector])(implicit ctx: Context): Import =
337+
ta.assignType(untpd.Import(expr, selectors), ctx.newImportSymbol(ctx.owner, expr))
338338

339339
def PackageDef(pid: RefTree, stats: List[Tree])(implicit ctx: Context): PackageDef =
340340
ta.assignType(untpd.PackageDef(pid, stats), pid)
@@ -1292,16 +1292,11 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
12921292
* @return The symbols imported.
12931293
*/
12941294
def importedSymbols(imp: Import,
1295-
selectorPredicate: untpd.Tree => Boolean = util.common.alwaysTrue)
1295+
selectorPredicate: untpd.ImportSelector => Boolean = util.common.alwaysTrue)
12961296
(implicit ctx: Context): List[Symbol] =
1297-
imp.selectors.find(selectorPredicate) match {
1298-
case Some(id: untpd.Ident) =>
1299-
importedSymbols(imp.expr, id.name)
1300-
case Some(Thicket((id: untpd.Ident) :: (_: untpd.Ident) :: Nil)) =>
1301-
importedSymbols(imp.expr, id.name)
1302-
case _ =>
1303-
Nil
1304-
}
1297+
imp.selectors.find(selectorPredicate) match
1298+
case Some(sel) => importedSymbols(imp.expr, sel.name)
1299+
case _ => Nil
13051300

13061301
/**
13071302
* The list of select trees that resolve to the same symbols as the ones that are imported
@@ -1326,16 +1321,14 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
13261321
}
13271322
}
13281323

1329-
imp.selectors.flatMap {
1330-
case Ident(nme.WILDCARD) =>
1331-
Nil
1332-
case id: untpd.Ident =>
1333-
importedSymbols(imp.expr, id.name).flatMap { sym =>
1334-
imported(sym, id, None)
1335-
}
1336-
case Thicket((id: untpd.Ident) :: (newName: untpd.Ident) :: Nil) =>
1337-
importedSymbols(imp.expr, id.name).flatMap { sym =>
1338-
imported(sym, id, Some(newName))
1324+
imp.selectors.flatMap { sel =>
1325+
if sel.isWildcard then Nil
1326+
else
1327+
val renamedOpt = sel.renamed match
1328+
case renamed: untpd.Ident => Some(renamed)
1329+
case untpd.EmptyTree => None
1330+
importedSymbols(imp.expr, sel.name).flatMap { sym =>
1331+
imported(sym, sel.imported, renamedOpt)
13391332
}
13401333
}
13411334
}

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

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,25 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
108108
case class GenAlias(pat: Tree, expr: Tree)(implicit @constructorOnly src: SourceFile) extends Tree
109109
case class ContextBounds(bounds: TypeBoundsTree, cxBounds: List[Tree])(implicit @constructorOnly src: SourceFile) extends TypTree
110110
case class PatDef(mods: Modifiers, pats: List[Tree], tpt: Tree, rhs: Tree)(implicit @constructorOnly src: SourceFile) extends DefTree
111-
case class Export(impliedOnly: Boolean, expr: Tree, selectors: List[Tree])(implicit @constructorOnly src: SourceFile) extends Tree
111+
case class Export(expr: Tree, selectors: List[ImportSelector])(implicit @constructorOnly src: SourceFile) extends Tree
112+
113+
case class ImportSelector(imported: Ident, renamed: Tree = EmptyTree, bound: Tree = EmptyTree)(implicit @constructorOnly src: SourceFile) extends Tree {
114+
115+
/** It's a `given` selector */
116+
val isGiven: Boolean = imported.name.isEmpty
117+
118+
/** It's a `given` or `_` selector */
119+
val isWildcard: Boolean = isGiven || imported.name == nme.WILDCARD
120+
121+
/** The imported name, EmptyTermName if it's a given selector */
122+
val name: TermName = imported.name.asInstanceOf[TermName]
123+
124+
/** The renamed part (which might be `_`), if present, or `name`, if missing */
125+
val rename: TermName = renamed match
126+
case Ident(rename: TermName) => rename
127+
case _ => name
128+
}
129+
112130
case class Number(digits: String, kind: NumberKind)(implicit @constructorOnly src: SourceFile) extends TermTree
113131

114132
enum NumberKind {
@@ -344,7 +362,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
344362
def Template(constr: DefDef, parents: List[Tree], derived: List[Tree], self: ValDef, body: LazyTreeList)(implicit src: SourceFile): Template =
345363
if (derived.isEmpty) new Template(constr, parents, self, body)
346364
else new DerivingTemplate(constr, parents ++ derived, self, body, derived.length)
347-
def Import(importGiven: Boolean, expr: Tree, selectors: List[Tree])(implicit src: SourceFile): Import = new Import(importGiven, expr, selectors)
365+
def Import(expr: Tree, selectors: List[ImportSelector])(implicit src: SourceFile): Import = new Import(expr, selectors)
348366
def PackageDef(pid: RefTree, stats: List[Tree])(implicit src: SourceFile): PackageDef = new PackageDef(pid, stats)
349367
def Annotated(arg: Tree, annot: Tree)(implicit src: SourceFile): Annotated = new Annotated(arg, annot)
350368

@@ -561,9 +579,13 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
561579
case tree: PatDef if (mods eq tree.mods) && (pats eq tree.pats) && (tpt eq tree.tpt) && (rhs eq tree.rhs) => tree
562580
case _ => finalize(tree, untpd.PatDef(mods, pats, tpt, rhs)(tree.source))
563581
}
564-
def Export(tree: Tree)(impliedOnly: Boolean, expr: Tree, selectors: List[Tree])(implicit ctx: Context): Tree = tree match {
565-
case tree: Export if (impliedOnly == tree.impliedOnly) && (expr eq tree.expr) && (selectors eq tree.selectors) => tree
566-
case _ => finalize(tree, untpd.Export(impliedOnly, expr, selectors)(tree.source))
582+
def Export(tree: Tree)(expr: Tree, selectors: List[ImportSelector])(implicit ctx: Context): Tree = tree match {
583+
case tree: Export if (expr eq tree.expr) && (selectors eq tree.selectors) => tree
584+
case _ => finalize(tree, untpd.Export(expr, selectors)(tree.source))
585+
}
586+
def ImportSelector(tree: Tree)(imported: Ident, renamed: Tree, bound: Tree)(implicit ctx: Context): Tree = tree match {
587+
case tree: ImportSelector if (imported eq tree.imported) && (renamed eq tree.renamed) && (bound eq tree.bound) => tree
588+
case _ => finalize(tree, untpd.ImportSelector(imported, renamed, bound)(tree.source))
567589
}
568590
def Number(tree: Tree)(digits: String, kind: NumberKind)(implicit ctx: Context): Tree = tree match {
569591
case tree: Number if (digits == tree.digits) && (kind == tree.kind) => tree
@@ -621,8 +643,10 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
621643
cpy.ContextBounds(tree)(transformSub(bounds), transform(cxBounds))
622644
case PatDef(mods, pats, tpt, rhs) =>
623645
cpy.PatDef(tree)(mods, transform(pats), transform(tpt), transform(rhs))
624-
case Export(impliedOnly, expr, selectors) =>
625-
cpy.Export(tree)(impliedOnly, transform(expr), selectors)
646+
case Export(expr, selectors) =>
647+
cpy.Export(tree)(transform(expr), selectors)
648+
case ImportSelector(imported, renamed, bound) =>
649+
cpy.ImportSelector(tree)(transformSub(imported), transform(renamed), transform(bound))
626650
case Number(_, _) | TypedSplice(_) =>
627651
tree
628652
case _ =>
@@ -676,8 +700,10 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
676700
this(this(x, bounds), cxBounds)
677701
case PatDef(mods, pats, tpt, rhs) =>
678702
this(this(this(x, pats), tpt), rhs)
679-
case Export(_, expr, _) =>
703+
case Export(expr, _) =>
680704
this(x, expr)
705+
case ImportSelector(imported, renamed, bound) =>
706+
this(this(this(x, imported), renamed), bound)
681707
case Number(_, _) =>
682708
x
683709
case TypedSplice(splice) =>

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

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ object Contexts {
214214
implicitsCache = {
215215
val implicitRefs: List[ImplicitRef] =
216216
if (isClassDefContext)
217-
try owner.thisType.implicitMembers(GivenOrImplicit)
217+
try owner.thisType.implicitMembers
218218
catch {
219219
case ex: CyclicReference => Nil
220220
}
@@ -405,8 +405,7 @@ object Contexts {
405405
case ref: RefTree[?] => Some(ref.name.asTermName)
406406
case _ => None
407407
}
408-
ctx.fresh.setImportInfo(
409-
ImportInfo(sym, imp.selectors, impNameOpt, imp.importGiven))
408+
ctx.fresh.setImportInfo(ImportInfo(sym, imp.selectors, impNameOpt))
410409
}
411410

412411
/** Does current phase use an erased types interpretation? */

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

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import scala.collection.mutable
1010
import collection.mutable
1111
import Denotations.SingleDenotation
1212
import util.SimpleIdentityMap
13+
import typer.ImportInfo.RootRef
1314

1415
import scala.annotation.tailrec
1516

@@ -1028,23 +1029,23 @@ class Definitions {
10281029
def isPredefClass(cls: Symbol): Boolean =
10291030
(cls.owner eq ScalaPackageClass) && predefClassNames.contains(cls.name)
10301031

1031-
val StaticRootImportFns: List[() => TermRef] = List[() => TermRef](
1032-
() => JavaLangPackageVal.termRef,
1033-
() => ScalaPackageVal.termRef
1032+
val StaticRootImportFns: List[RootRef] = List[RootRef](
1033+
(() => JavaLangPackageVal.termRef, false),
1034+
(() => ScalaPackageVal.termRef, false)
10341035
)
10351036

1036-
val PredefImportFns: List[() => TermRef] = List[() => TermRef](
1037-
() => ScalaPredefModule.termRef,
1038-
() => DottyPredefModule.termRef
1037+
val PredefImportFns: List[RootRef] = List[RootRef](
1038+
(() => ScalaPredefModule.termRef, true),
1039+
(() => DottyPredefModule.termRef, false)
10391040
)
10401041

1041-
@tu lazy val RootImportFns: List[() => TermRef] =
1042-
if (ctx.settings.YnoImports.value) List.empty[() => TermRef]
1042+
@tu lazy val RootImportFns: List[RootRef] =
1043+
if (ctx.settings.YnoImports.value) Nil
10431044
else if (ctx.settings.YnoPredef.value) StaticRootImportFns
10441045
else StaticRootImportFns ++ PredefImportFns
10451046

10461047
@tu lazy val ShadowableImportNames: Set[TermName] = Set("Predef", "DottyPredef").map(_.toTermName)
1047-
@tu lazy val RootImportTypes: List[TermRef] = RootImportFns.map(_())
1048+
@tu lazy val RootImportTypes: List[TermRef] = RootImportFns.map(_._1())
10481049

10491050
/** Modules whose members are in the default namespace and their module classes */
10501051
@tu lazy val UnqualifiedOwnerTypes: Set[NamedType] =

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import printing.Printer
1919
import io.AbstractFile
2020
import config.Config
2121
import util.common._
22+
import typer.ProtoTypes.NoViewsAllowed
2223
import collection.mutable.ListBuffer
2324

2425
/** Denotations represent the meaning of symbols and named types.
@@ -766,6 +767,11 @@ object Denotations {
766767
if (matches) this else NoDenotation
767768
}
768769

770+
def matchesImportBound(bound: Type)(implicit ctx: Context): Boolean =
771+
if bound.isRef(defn.NothingClass) then false
772+
else if bound.isRef(defn.AnyClass) then true
773+
else NoViewsAllowed.normalizedCompatible(info, bound, keepConstraint = false)
774+
769775
// ------ Transformations -----------------------------------------
770776

771777
private[this] var myValidFor: Period = Nowhere

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -799,10 +799,10 @@ object Types {
799799
* @param kind A subset of {Implicit, Given} that specifies what kind of implicit should
800800
* be returned
801801
*/
802-
final def implicitMembers(kind: FlagSet)(implicit ctx: Context): List[TermRef] = {
802+
final def implicitMembers(implicit ctx: Context): List[TermRef] = {
803803
record("implicitMembers")
804804
memberDenots(implicitFilter,
805-
(name, buf) => buf ++= member(name).altsWith(_.isOneOf(GivenOrImplicitVal & kind)))
805+
(name, buf) => buf ++= member(name).altsWith(_.isOneOf(GivenOrImplicitVal)))
806806
.toList.map(d => TermRef(this, d.symbol.asTerm))
807807
}
808808

compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,13 +60,13 @@ Standard-Section: "ASTs" TopLevelStat*
6060
Stat = Term
6161
ValOrDefDef
6262
TYPEDEF Length NameRef (type_Term | Template) Modifier* -- modifiers type name (= type | bounds) | moifiers class name template
63-
IMPORT Length [GIVEN] qual_Term Selector* -- import given? qual selectors
63+
IMPORT Length qual_Term Selector* -- import qual selectors
6464
ValOrDefDef = VALDEF Length NameRef type_Term rhs_Term? Modifier* -- modifiers val name : type (= rhs)?
6565
DEFDEF Length NameRef TypeParam* Params* returnType_Term rhs_Term?
6666
Modifier* -- modifiers def name [typeparams] paramss : returnType (= rhs)?
67-
Selector = IMPORTED name_NameRef -- name
67+
Selector = IMPORTED name_NameRef -- name, "_" for normal wildcards, "" for given wildcards
6868
RENAMED to_NameRef -- => name
69-
BOUNDED type_Term? -- for type
69+
BOUNDED type_Term -- type bound
7070
7171
TypeParam = TYPEPARAM Length NameRef type_Term Modifier* -- modifiers name bounds
7272
Params = PARAMS Length Param*

compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -529,10 +529,9 @@ class TreePickler(pickler: TastyPickler) {
529529
}
530530
pickleStats(tree.constr :: rest)
531531
}
532-
case Import(importGiven, expr, selectors) =>
532+
case Import(expr, selectors) =>
533533
writeByte(IMPORT)
534534
withLength {
535-
if (importGiven) writeByte(GIVEN)
536535
pickleTree(expr)
537536
pickleSelectors(selectors)
538537
}
@@ -592,18 +591,18 @@ class TreePickler(pickler: TastyPickler) {
592591
}
593592
}
594593

595-
def pickleSelectors(selectors: List[untpd.Tree])(implicit ctx: Context): Unit =
596-
selectors foreach {
597-
case Thicket((from @ Ident(_)) :: (to @ Ident(_)) :: Nil) =>
598-
pickleSelector(IMPORTED, from)
599-
pickleSelector(RENAMED, to)
600-
case id @ Ident(_) =>
601-
pickleSelector(IMPORTED, id)
602-
case bounded @ TypeBoundsTree(untpd.EmptyTree, untpd.TypedSplice(tpt)) =>
603-
registerTreeAddr(bounded)
604-
writeByte(BOUNDED)
605-
pickleTree(tpt)
606-
}
594+
def pickleSelectors(selectors: List[untpd.ImportSelector])(implicit ctx: Context): Unit =
595+
for sel <- selectors do
596+
pickleSelector(IMPORTED, sel.imported)
597+
sel.renamed match
598+
case to @ Ident(_) => pickleSelector(RENAMED, to)
599+
case _ =>
600+
sel.bound match
601+
case bound @ untpd.TypedSplice(tpt) =>
602+
registerTreeAddr(bound)
603+
writeByte(BOUNDED)
604+
pickleTree(tpt)
605+
case _ =>
607606

608607
def pickleSelector(tag: Int, id: untpd.Ident)(implicit ctx: Context): Unit = {
609608
registerTreeAddr(id)

0 commit comments

Comments
 (0)