Skip to content

Commit 7e05e1e

Browse files
Fix #7312: choose root imports based on the source file
Instead of setting the scala root imports in the rootContext, set it later and choose the right import depending on the language (java and scala).
1 parent aa6b172 commit 7e05e1e

File tree

15 files changed

+141
-66
lines changed

15 files changed

+141
-66
lines changed

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

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ import Periods._
77
import Symbols._
88
import Types._
99
import Scopes._
10-
import typer.{ImportInfo, Typer}
10+
import typer.Typer
11+
import typer.ImportInfo._
1112
import Decorators._
1213
import io.{AbstractFile, PlainFile}
1314
import Phases.unfusedPhases
@@ -74,9 +75,7 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint
7475
.addMode(Mode.ImplicitsEnabled)
7576
.setTyperState(ctx.typerState.fresh(ctx.reporter))
7677
ctx.initialize()(using start) // re-initialize the base context with start
77-
def addImport(ctx: Context, rootRef: ImportInfo.RootRef) =
78-
ctx.fresh.setImportInfo(ImportInfo.rootImport(rootRef))
79-
defn.RootImportFns.foldLeft(start.setRun(this))(addImport)
78+
start.setRun(this)
8079
}
8180

8281
private var compiling = false
@@ -92,8 +91,8 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint
9291
private var myFiles: Set[AbstractFile] = _
9392

9493
/** The compilation units currently being compiled, this may return different
95-
* results over time.
96-
*/
94+
* results over time.
95+
*/
9796
def units: List[CompilationUnit] = myUnits
9897

9998
var suspendedUnits: mutable.ListBuffer[CompilationUnit] = mutable.ListBuffer()
@@ -205,15 +204,20 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint
205204
compiling = false
206205
}
207206

208-
/** Enter top-level definitions of classes and objects contain in Scala source file `file`.
207+
/** Enter top-level definitions of classes and objects contained in source file `file`.
209208
* The newly added symbols replace any previously entered symbols.
210209
* If `typeCheck = true`, also run typer on the compilation unit, and set
211210
* `rootTreeOrProvider`.
212211
*/
213212
def lateCompile(file: AbstractFile, typeCheck: Boolean)(using Context): Unit =
214213
if (!files.contains(file) && !lateFiles.contains(file)) {
215214
lateFiles += file
215+
216216
val unit = CompilationUnit(ctx.getSource(file.path))
217+
val unitCtx = runContext.fresh
218+
.setCompilationUnit(unit)
219+
.withRootImports
220+
217221
def process()(using Context) = {
218222
unit.untpdTree =
219223
if (unit.isJava) new JavaParser(unit.source).parse()
@@ -227,7 +231,7 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint
227231
if (typeCheck)
228232
if (compiling) finalizeActions += (() => processUnit()) else processUnit()
229233
}
230-
process()(using runContext.fresh.setCompilationUnit(unit))
234+
process()(using unitCtx)
231235
}
232236

233237
private sealed trait PrintedTree

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

Lines changed: 47 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1140,28 +1140,61 @@ class Definitions {
11401140
def isPredefClass(cls: Symbol): Boolean =
11411141
(cls.owner eq ScalaPackageClass) && predefClassNames.contains(cls.name)
11421142

1143-
val StaticRootImportFns: List[RootRef] = List[RootRef](
1144-
(() => JavaLangPackageVal.termRef, false),
1145-
(() => ScalaPackageVal.termRef, false)
1143+
private val JavaImportFns: List[RootRef] = List(
1144+
RootRef(() => JavaLangPackageVal.termRef)
11461145
)
11471146

1148-
val PredefImportFns: List[RootRef] = List[RootRef](
1149-
(() => ScalaPredefModule.termRef, true),
1150-
(() => DottyPredefModule.termRef, false)
1147+
private val ScalaImportFns: List[RootRef] =
1148+
JavaImportFns :+
1149+
RootRef(() => ScalaPackageVal.termRef)
1150+
1151+
private val PredefImportFns: List[RootRef] = List(
1152+
RootRef(() => ScalaPredefModule.termRef, isPredef=true),
1153+
RootRef(() => DottyPredefModule.termRef)
11511154
)
11521155

1153-
@tu lazy val RootImportFns: List[RootRef] =
1154-
if (ctx.settings.YnoImports.value) Nil
1155-
else if (ctx.settings.YnoPredef.value) StaticRootImportFns
1156-
else StaticRootImportFns ++ PredefImportFns
1156+
@tu private lazy val JavaRootImportFns: List[RootRef] =
1157+
if ctx.settings.YnoImports.value then Nil
1158+
else JavaImportFns
11571159

1158-
@tu lazy val ShadowableImportNames: Set[TermName] = Set("Predef", "DottyPredef").map(_.toTermName)
1159-
@tu lazy val RootImportTypes: List[TermRef] = RootImportFns.map(_._1())
1160+
@tu private lazy val ScalaRootImportFns: List[RootRef] =
1161+
if ctx.settings.YnoImports.value then Nil
1162+
else if ctx.settings.YnoPredef.value then ScalaImportFns
1163+
else ScalaImportFns ++ PredefImportFns
1164+
1165+
@tu private lazy val JavaRootImportTypes: List[TermRef] = JavaRootImportFns.map(_.refFn())
1166+
@tu private lazy val ScalaRootImportTypes: List[TermRef] = ScalaRootImportFns.map(_.refFn())
1167+
@tu private lazy val JavaUnqualifiedOwnerTypes: Set[NamedType] = unqualifiedTypes(JavaRootImportTypes)
1168+
@tu private lazy val ScalaUnqualifiedOwnerTypes: Set[NamedType] = unqualifiedTypes(ScalaRootImportTypes)
1169+
1170+
/** Are we compiling a java source file? */
1171+
private def isJavaContext(using Context): Boolean =
1172+
val unit = ctx.compilationUnit
1173+
unit != null && unit.isJava
1174+
1175+
private def unqualifiedTypes(refs: List[TermRef]) =
1176+
val types = refs.toSet[NamedType]
1177+
types ++ types.map(_.symbol.moduleClass.typeRef)
1178+
1179+
/** Lazy references to the root imports */
1180+
def rootImportFns(using Context): List[RootRef] =
1181+
if isJavaContext then JavaRootImportFns
1182+
else ScalaRootImportFns
1183+
1184+
/** Root types imported by default */
1185+
def rootImportTypes(using Context): List[TermRef] =
1186+
if isJavaContext then JavaRootImportTypes
1187+
else ScalaRootImportTypes
11601188

11611189
/** Modules whose members are in the default namespace and their module classes */
1162-
@tu lazy val UnqualifiedOwnerTypes: Set[NamedType] =
1163-
RootImportTypes.toSet[NamedType] ++ RootImportTypes.map(_.symbol.moduleClass.typeRef)
1190+
def unqualifiedOwnerTypes(using Context): Set[NamedType] =
1191+
if isJavaContext then JavaUnqualifiedOwnerTypes
1192+
else ScalaUnqualifiedOwnerTypes
1193+
1194+
/** Names of the root import symbols that can be hidden by other imports */
1195+
@tu lazy val ShadowableImportNames: Set[TermName] = Set("Predef", "DottyPredef").map(_.toTermName)
11641196

1197+
/** Class symbols for which no class exist at runtime */
11651198
@tu lazy val NotRuntimeClasses: Set[Symbol] = Set(AnyClass, AnyValClass, NullClass, NothingClass)
11661199

11671200
/** Classes that are known not to have an initializer irrespective of

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import dotty.tools.dotc.transform.MegaPhase._
1414
import dotty.tools.dotc.transform._
1515
import Periods._
1616
import typer.{FrontEnd, RefChecks}
17+
import typer.ImportInfo.withRootImports
1718
import ast.tpd
1819

1920
object Phases {
@@ -291,7 +292,7 @@ object Phases {
291292
/** @pre `isRunnable` returns true */
292293
def runOn(units: List[CompilationUnit])(using Context): List[CompilationUnit] =
293294
units.map { unit =>
294-
val unitCtx = ctx.fresh.setPhase(this.start).setCompilationUnit(unit)
295+
val unitCtx = ctx.fresh.setPhase(this.start).setCompilationUnit(unit).withRootImports
295296
run(using unitCtx)
296297
unitCtx.compilationUnit
297298
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ object JavaParsers {
101101
def javaLangObject(): Tree = javaLangDot(tpnme.Object)
102102

103103
def arrayOf(tpt: Tree): AppliedTypeTree =
104-
AppliedTypeTree(Ident(nme.Array.toTypeName), List(tpt))
104+
AppliedTypeTree(scalaDot(tpnme.Array), List(tpt))
105105

106106
def makeTemplate(parents: List[Tree], stats: List[Tree], tparams: List[TypeDef], needsDummyConstr: Boolean): Template = {
107107
def pullOutFirstConstr(stats: List[Tree]): (Tree, List[Tree]) = stats match {

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,7 @@ class PlainPrinter(_ctx: Context) extends Printer {
321321
}
322322

323323
protected def isOmittablePrefix(sym: Symbol): Boolean =
324-
defn.UnqualifiedOwnerTypes.exists(_.symbol == sym) || isEmptyPrefix(sym)
324+
defn.unqualifiedOwnerTypes.exists(_.symbol == sym) || isEmptyPrefix(sym)
325325

326326
protected def isEmptyPrefix(sym: Symbol): Boolean =
327327
sym.isEffectiveRoot || sym.isAnonymousClass || sym.name.isReplWrapperName

compiler/src/dotty/tools/dotc/transform/patmat/Space.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -664,7 +664,7 @@ class SpaceEngine(using Context) extends SpaceLogic {
664664

665665
def isOmittable(sym: Symbol) =
666666
sym.isEffectiveRoot || sym.isAnonymousClass || sym.name.isReplWrapperName ||
667-
ctx.definitions.UnqualifiedOwnerTypes.exists(_.symbol == sym) ||
667+
ctx.definitions.unqualifiedOwnerTypes.exists(_.symbol == sym) ||
668668
sym.showFullName.startsWith("scala.") ||
669669
sym == enclosingCls || sym == enclosingCls.sourceModule
670670

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

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ import Phases._
77
import Contexts._
88
import Symbols._
99
import Decorators._
10-
import dotty.tools.dotc.parsing.JavaParsers.JavaParser
10+
import ImportInfo.withRootImports
11+
import parsing.JavaParsers.JavaParser
1112
import parsing.Parsers.Parser
1213
import config.Config
1314
import config.Printers.{typr, default}
@@ -98,7 +99,7 @@ class FrontEnd extends Phase {
9899
val unitContexts =
99100
for unit <- units yield
100101
report.inform(s"compiling ${unit.source}")
101-
ctx.fresh.setCompilationUnit(unit)
102+
ctx.fresh.setCompilationUnit(unit).withRootImports
102103
unitContexts.foreach(parse(using _))
103104
record("parsedTrees", ast.Trees.ntrees)
104105
remaining = unitContexts
@@ -123,7 +124,7 @@ class FrontEnd extends Phase {
123124
| ${suspendedUnits.toList}%, %
124125
|"""
125126
val enableXprintSuspensionHint =
126-
if (ctx.settings.XprintSuspension.value) ""
127+
if ctx.settings.XprintSuspension.value then ""
127128
else "\n\nCompiling with -Xprint-suspension gives more information."
128129
report.error(em"""Cyclic macro dependencies $where
129130
|Compilation stopped since no further progress can be made.

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

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,24 +17,32 @@ import Decorators._
1717

1818
object ImportInfo {
1919

20-
type RootRef = (
21-
() => TermRef, // a lazy reference to the root module to be imported
22-
Boolean // true if this will refer to scala.Predef
23-
)
24-
25-
/** The import info for a root import from given symbol `sym` */
26-
def rootImport(rootRef: RootRef)(using Context): ImportInfo =
27-
val (refFn, isPredef) = rootRef
20+
case class RootRef(refFn: () => TermRef, isPredef: Boolean = false)
21+
22+
/** The import info for a root import */
23+
def rootImport(ref: RootRef)(using Context): ImportInfo =
2824
var selectors =
2925
untpd.ImportSelector(untpd.Ident(nme.WILDCARD)) // import all normal members...
3026
:: untpd.ImportSelector(untpd.Ident(nme.EMPTY)) // ... and also all given members
3127
:: Nil
32-
if isPredef then // do not import any2stringadd
28+
if ref.isPredef then // do not import any2stringadd
3329
selectors = untpd.ImportSelector(untpd.Ident(nme.any2stringadd), untpd.Ident(nme.WILDCARD))
3430
:: selectors
35-
def expr(using Context) = tpd.Ident(refFn())
36-
def imp(using Context) = tpd.Import(expr, selectors)
37-
ImportInfo(imp.symbol, selectors, None, isRootImport = true)
31+
32+
def sym(using Context) =
33+
val expr = tpd.Ident(ref.refFn()) // refFn must be called in the context of ImportInfo.sym
34+
tpd.Import(expr, selectors).symbol
35+
36+
ImportInfo(sym, selectors, None, isRootImport = true)
37+
38+
extension (c: Context):
39+
def withRootImports(rootRefs: List[RootRef])(using Context): Context =
40+
rootRefs.foldLeft(c)((ctx, ref) => ctx.fresh.setImportInfo(rootImport(ref)))
41+
42+
def withRootImports: Context =
43+
given Context = c
44+
c.withRootImports(defn.rootImportFns)
45+
3846
}
3947

4048
/** Info relating to an import clause
@@ -164,7 +172,7 @@ class ImportInfo(symf: Context ?=> Symbol,
164172
case Some(symName) => defn.ShadowableImportNames.contains(symName)
165173
case None => false
166174
myUnimported =
167-
if maybeShadowsRoot && defn.RootImportTypes.exists(_.symbol == sym) then sym
175+
if maybeShadowsRoot && defn.rootImportTypes.exists(_.symbol == sym) then sym
168176
else NoSymbol
169177
assert(myUnimported != null)
170178
myUnimported
@@ -193,4 +201,4 @@ class ImportInfo(symf: Context ?=> Symbol,
193201
end featureImported
194202

195203
def toText(printer: Printer): Text = printer.toText(this)
196-
}
204+
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ trait ImportSuggestions:
226226

227227
try
228228
val roots = suggestionRoots
229-
.filterNot(root => defn.RootImportTypes.exists(_.symbol == root.symbol))
229+
.filterNot(root => defn.rootImportTypes.exists(_.symbol == root.symbol))
230230
// don't suggest things that are imported by default
231231

232232
def extensionImports = pt match

compiler/src/dotty/tools/repl/ReplCompiler.scala

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import dotty.tools.dotc.core.StdNames._
1313
import dotty.tools.dotc.core.Symbols._
1414
import dotty.tools.dotc.reporting.Diagnostic
1515
import dotty.tools.dotc.transform.{PostTyper, Staging}
16-
import dotty.tools.dotc.typer.ImportInfo
16+
import dotty.tools.dotc.typer.ImportInfo._
1717
import dotty.tools.dotc.util.Spans._
1818
import dotty.tools.dotc.util.{ParsedComment, SourceFile}
1919
import dotty.tools.dotc.{CompilationUnit, Compiler, Run}
@@ -48,21 +48,19 @@ class ReplCompiler extends Compiler {
4848
def importPreviousRun(id: Int)(using Context) = {
4949
// we first import the wrapper object id
5050
val path = nme.EMPTY_PACKAGE ++ "." ++ objectNames(id)
51-
def importWrapper(c: Context, importGiven: Boolean) = {
52-
val importInfo = ImportInfo.rootImport(() =>
53-
requiredModuleRef(path), importGiven)(using c)
54-
c.fresh.setNewScope.setImportInfo(importInfo)
55-
}
56-
val ctx0 = importWrapper(importWrapper(ctx, false), true)
51+
val ctx0 = ctx.fresh
52+
.setNewScope
53+
.withRootImports(RootRef(() => requiredModuleRef(path)) :: Nil)
5754

5855
// then its user defined imports
5956
val imports = state.imports.getOrElse(id, Nil)
60-
if (imports.isEmpty) ctx0
57+
if imports.isEmpty then ctx0
6158
else imports.foldLeft(ctx0.fresh.setNewScope)((ctx, imp) =>
6259
importContext(imp)(using ctx))
6360
}
6461

65-
(1 to state.objectIndex).foldLeft(super.rootContext)((ctx, id) =>
62+
val rootCtx = super.rootContext.withRootImports
63+
(1 to state.objectIndex).foldLeft(rootCtx)((ctx, id) =>
6664
importPreviousRun(id)(using ctx))
6765
}
6866
}

compiler/src/dotty/tools/repl/ReplFrontEnd.scala

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ package repl
44
import dotc.typer.FrontEnd
55
import dotc.CompilationUnit
66
import dotc.core.Contexts._
7+
import dotc.typer.ImportInfo.withRootImports
78

89
/** A customized `FrontEnd` for the REPL
910
*
@@ -17,10 +18,10 @@ private[repl] class REPLFrontEnd extends FrontEnd {
1718

1819
override def runOn(units: List[CompilationUnit])(using Context): List[CompilationUnit] = {
1920
assert(units.size == 1) // REPl runs one compilation unit at a time
20-
21-
val unitContext = ctx.fresh.setCompilationUnit(units.head)
21+
val unit = units.head
22+
val unitContext = ctx.fresh.setCompilationUnit(unit).withRootImports
2223
enterSyms(using unitContext)
2324
typeCheck(using unitContext)
24-
List(unitContext.compilationUnit)
25+
List(unit)
2526
}
2627
}

doc-tool/src/dotty/tools/dottydoc/DocCompiler.scala

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,9 @@ import dotty.tools.dotc.transform.CookComments
2727
class DocCompiler extends Compiler {
2828

2929
override def newRun(using Context): Run = {
30-
if (ctx.settings.fromTasty.value) {
30+
if ctx.settings.fromTasty.value then
3131
reset()
3232
new TASTYRun(this, ctx.addMode(Mode.ReadPositions).addMode(Mode.ReadComments))
33-
}
3433
else
3534
super.newRun
3635
}

doc-tool/test/dotty/tools/dottydoc/DottyDocTest.scala

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,18 @@ package dottydoc
33

44
import vulpix.TestConfiguration
55

6-
import dotc.Compiler
6+
import dotc.{Compiler, Run}
77
import dotc.core.Contexts.{ Context, ContextBase, FreshContext }
88
import dotc.core.Comments.{ ContextDoc, ContextDocstrings }
99
import dotc.util.SourceFile
1010
import dotc.core.Phases.Phase
11-
import dotty.tools.io.AbstractFile
1211
import dotc.typer.FrontEnd
13-
import dottydoc.core.{ DocASTPhase, ContextDottydoc }
14-
import model.Package
15-
import dotty.tools.dottydoc.util.syntax._
16-
import dotty.tools.io.AbstractFile
17-
import dotc.reporting.{ StoreReporter, MessageRendering }
1812
import dotc.interfaces.Diagnostic.ERROR
19-
import io.Directory
13+
import dotc.reporting.{ StoreReporter, MessageRendering }
14+
import util.syntax._
15+
import io.{AbstractFile, Directory}
16+
import core.{ DocASTPhase, ContextDottydoc }
17+
import model.Package
2018
import org.junit.Assert.fail
2119

2220
import java.io.{ BufferedWriter, OutputStreamWriter }
@@ -115,6 +113,7 @@ trait DottyDocTest extends MessageRendering {
115113
ctx.setSetting(ctx.settings.outputDir, AbstractFile.getDirectory(out))
116114
}
117115
val dotc = new Compiler
116+
118117
val run = dotc.newRun(using dotcCtx)
119118
run.compileSources(sources)
120119
assert(!dotcCtx.reporter.hasErrors)

0 commit comments

Comments
 (0)