-
Notifications
You must be signed in to change notification settings - Fork 3.1k
SI-6623 -Yrepl-use-magic-imports avoids nesting $iw wrappers #8576
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
Changes from all commits
dca6f5a
317775b
9e146e8
7613d84
1659fec
ff991f5
f4cb764
cba5394
50c74cd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -32,11 +32,10 @@ trait Contexts { self: Analyzer => | |
| object NoContext | ||
| extends Context(EmptyTree, NoSymbol, EmptyScope, NoCompilationUnit, | ||
| // We can't pass the uninitialized `this`. Instead, we treat null specially in `Context#outer` | ||
| null) { | ||
| null, 0) { | ||
| enclClass = this | ||
| enclMethod = this | ||
|
|
||
| override val depth = 0 | ||
| override def nextEnclosing(p: Context => Boolean): Context = this | ||
| override def enclosingContextChain: List[Context] = Nil | ||
| override def implicitss: List[List[ImplicitInfo]] = Nil | ||
|
|
@@ -191,7 +190,7 @@ trait Contexts { self: Analyzer => | |
| * @param _outer The next outer context. | ||
| */ | ||
| class Context private[typechecker](val tree: Tree, val owner: Symbol, val scope: Scope, | ||
| val unit: CompilationUnit, _outer: Context, | ||
| val unit: CompilationUnit, _outer: Context, val depth: Int, | ||
| private[this] var _reporter: ContextReporter = new ThrowingReporter) { | ||
| private def outerIsNoContext = _outer eq null | ||
| final def outer: Context = if (outerIsNoContext) NoContext else _outer | ||
|
|
@@ -237,16 +236,12 @@ trait Contexts { self: Analyzer => | |
|
|
||
| protected def outerDepth = if (outerIsNoContext) 0 else outer.depth | ||
|
|
||
| val depth: Int = { | ||
| val increasesDepth = isRootImport || outerIsNoContext || (outer.scope != scope) | ||
| ( if (increasesDepth) 1 else 0 ) + outerDepth | ||
| } | ||
|
|
||
| /** The currently visible imports */ | ||
| /** The currently visible imports, from innermost to outermost. */ | ||
| def imports: List[ImportInfo] = outer.imports | ||
| /** Equivalent to `imports.headOption`, but more efficient */ | ||
| def firstImport: Option[ImportInfo] = outer.firstImport | ||
| protected[Contexts] def importOrNull: ImportInfo = null | ||
| /** A root import is never unused and always bumps context depth. (e.g scala._ / Predef._ and magic REPL imports) */ | ||
| def isRootImport: Boolean = false | ||
|
|
||
| /** Types for which implicit arguments are currently searched */ | ||
|
|
@@ -488,11 +483,17 @@ trait Contexts { self: Analyzer => | |
| else if (!sameOwner && owner.isTerm) NoPrefix | ||
| else prefix | ||
|
|
||
| def innerDepth(isRootImport: Boolean) = { | ||
| val increasesDepth = isRootImport || (this == NoContext) || (this.scope != scope) | ||
| depth + (if (increasesDepth) 1 else 0) | ||
| } | ||
|
|
||
| // The blank canvas | ||
| val c = if (isImport) | ||
| new Context(tree, owner, scope, unit, this, reporter) with ImportContext | ||
| else | ||
| new Context(tree, owner, scope, unit, this, reporter) | ||
| val c = if (isImport) { | ||
| val isRootImport = !tree.pos.isDefined || isReplImportWrapperImport(tree) | ||
| new ImportContext(tree, owner, scope, unit, this, isRootImport, innerDepth(isRootImport), reporter) | ||
| } else | ||
| new Context(tree, owner, scope, unit, this, innerDepth(isRootImport = false), reporter) | ||
|
|
||
| // Fields that are directly propagated | ||
| c.variance = variance | ||
|
|
@@ -1100,6 +1101,16 @@ trait Contexts { self: Analyzer => | |
| } | ||
| } | ||
|
|
||
|
|
||
| private def isReplImportWrapperImport(tree: Tree): Boolean = { | ||
| tree match { | ||
| case Import(expr, selector :: Nil) => | ||
| // Just a syntactic check to avoid forcing typechecking of imports | ||
| selector.name.string_==(nme.INTERPRETER_IMPORT_LEVEL_UP) && owner.enclosingTopLevelClass.isInterpreterWrapper | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My other use case was to submit a directory of source files as a single compilation unit, with files wrapped in Maybe also call it
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What's the user-level use case for that? Something to do with
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, on that thread they were complaining that their files get too big when they cram everything in. That also covers companionship. Sometimes I feel like I'm crammed in with my companion. |
||
| case _ => false | ||
| } | ||
| } | ||
|
|
||
| } //class Context | ||
|
|
||
| /** Find the symbol of a simple name starting from this context. | ||
|
|
@@ -1307,8 +1318,11 @@ trait Contexts { self: Analyzer => | |
| } | ||
|
|
||
| /** A `Context` focussed on an `Import` tree */ | ||
| trait ImportContext extends Context { | ||
| private val impInfo: ImportInfo = { | ||
| final class ImportContext(tree: Tree, owner: Symbol, scope: Scope, | ||
| unit: CompilationUnit, outer: Context, | ||
| override val isRootImport: Boolean, depth: Int, | ||
| reporter: ContextReporter) extends Context(tree, owner, scope, unit, outer, depth, reporter) { | ||
| private[this] val impInfo: ImportInfo = { | ||
| val info = new ImportInfo(tree.asInstanceOf[Import], outerDepth) | ||
| if (settings.warnUnusedImport && openMacros.isEmpty && !isRootImport) // excludes java.lang/scala/Predef imports | ||
| allImportInfos(unit) ::= info | ||
|
|
@@ -1317,7 +1331,7 @@ trait Contexts { self: Analyzer => | |
| override final def imports = impInfo :: super.imports | ||
| override final def firstImport = Some(impInfo) | ||
| override final def importOrNull = impInfo | ||
| override final def isRootImport = !tree.pos.isDefined | ||
|
|
||
| override final def toString = s"${super.toString} with ImportContext { $impInfo; outer.owner = ${outer.owner} }" | ||
| } | ||
|
|
||
|
|
@@ -1467,7 +1481,6 @@ trait Contexts { self: Analyzer => | |
| protected def handleError(pos: Position, msg: String): Unit = reporter.error(pos, msg) | ||
| } | ||
|
|
||
|
|
||
| private[typechecker] class BufferingReporter(_errorBuffer: mutable.LinkedHashSet[AbsTypeError] = null, _warningBuffer: mutable.LinkedHashSet[(Position, String)] = null) extends ContextReporter(_errorBuffer, _warningBuffer) { | ||
| override def isBuffering = true | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -536,8 +536,10 @@ trait Namers extends MethodSynthesis { | |
| val Import(expr, selectors) = tree | ||
| val base = expr.tpe | ||
|
|
||
| def checkNotRedundant(pos: Position, from: Name, to0: Name) { | ||
| def check(to: Name) = { | ||
| // warn proactively if specific import loses to definition in scope, | ||
| // since it may result in desired implicit not imported into scope. | ||
| def checkNotRedundant(pos: Position, from: Name, to0: Name): Unit = { | ||
| def check(to: Name): Unit = { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Um. I guess since we're talking import magic. I know the check used to be wrong, false positive. Now I'm not sure what the user story is. Oh, this is covered by unused import. So is this check only guarding against old bugs in name binding? Including implicit shadowing?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, I see bug 2866 is due to Jason: "I have five unanswered questions"... after grepping for permanently hidden again in the check files...
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, I dropped your changes to this code from #5220 as I didn't understand the original code or the change. 🤷♂
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure it's very meaningful, even if it had a bug-compatible meaning once. |
||
| val e = context.scope.lookupEntry(to) | ||
|
|
||
| if (e != null && e.owner == context.scope && e.sym.exists) | ||
|
|
@@ -1820,7 +1822,6 @@ trait Namers extends MethodSynthesis { | |
| } | ||
| } | ||
|
|
||
|
|
||
| /** Given a case class | ||
| * case class C[Ts] (ps: Us) | ||
| * Add the following methods to toScope: | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sorry to snipe at
snippes, which I guess is the French.In the code that wraps REPL snippets, use magic imports rather