Skip to content

Commit

Permalink
Merge pull request #10325 from som-snytt/issue/12736-private-object-i…
Browse files Browse the repository at this point in the history
…mport

Complete symbol loader on import of toplevel symbol
  • Loading branch information
lrytz committed Mar 17, 2023
2 parents d0f2aab + c434ba6 commit d4e0f8b
Show file tree
Hide file tree
Showing 6 changed files with 41 additions and 15 deletions.
9 changes: 7 additions & 2 deletions src/compiler/scala/tools/nsc/typechecker/Contexts.scala
Expand Up @@ -1246,9 +1246,11 @@ trait Contexts { self: Analyzer =>

/** If the given import is permitted, fetch the symbol and filter for accessibility.
*/
private[Contexts] def importedAccessibleSymbol(imp: ImportInfo, sym: => Symbol): Symbol =
private[Contexts] def importedAccessibleSymbol(imp: ImportInfo, sym: => Symbol): Symbol = {
if (isExcludedRootImport(imp)) NoSymbol
else sym.filter(isAccessible(_, imp.qual.tpe, superAccess = false))
else sym.filter(s => s.exists && isAccessible(s, imp.qual.tpe, superAccess = false))
// `exists` above completes SymbolLoaders, which sets the symbol's access flags (scala/bug#12736)
}

private def isExcludedRootImport(imp: ImportInfo): Boolean =
imp.isRootImport && excludedRootImportsCached.get(unit).exists(_.contains(imp.qual.symbol))
Expand Down Expand Up @@ -1508,6 +1510,9 @@ trait Contexts { self: Analyzer =>
val importCursor = new ImportCursor(thisContext, name)
import importCursor.{imp1, imp2}

// The symbol resolved by the given import for `name`, paired with the selector that was used.
// If `requireExplicit`, then only "named" or "specific" selectors are considered.
// In addition, the symbol must be accessible (in the current context) and satisfy the `qualifies` predicate.
def lookupImport(imp: ImportInfo, requireExplicit: Boolean): (ImportSelector, Symbol) = {
val pair @ (sel, sym) = imp.importedSelectedSymbol(name, requireExplicit)
if (sym == NoSymbol) pair
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/scala/tools/nsc/typechecker/Infer.scala
Expand Up @@ -286,7 +286,7 @@ trait Infer extends Checkable {
ErrorUtils.issueTypeError(error)(context)
ErrorType
}
def accessible = sym filter (alt => context.isAccessible(alt, pre, site.isInstanceOf[Super])) match {
def accessible = sym.filter(context.isAccessible(_, pre, site.isInstanceOf[Super])) match {
case NoSymbol if sym.isJavaDefined && context.unit.isJava => sym // don't try to second guess Java; see #4402
case sym1 => sym1
}
Expand Down
24 changes: 12 additions & 12 deletions src/reflect/scala/reflect/internal/Symbols.scala
Expand Up @@ -1095,21 +1095,21 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
}

def exists: Boolean = !isTopLevel || {
val isSourceLoader = rawInfo match {
case sl: SymLoader => sl.fromSource
case _ => false
}
def warnIfSourceLoader(): Unit = {
def warnIfSourceLoader(): false = {
val isSourceLoader = rawInfo match {
case sl: SymLoader => sl.fromSource
case _ => false
}
// Predef is completed early due to its autoimport; we used to get here when type checking its
// parent LowPriorityImplicits. See comment in c5441dc for more elaboration.
// Since the fix for scala/bug#7335 Predef parents must be defined in Predef.scala, and we should not
// get here anymore.
if (isSourceLoader)
// Predef is completed early due to its autoimport; we used to get here when type checking its
// parent LowPriorityImplicits. See comment in c5441dc for more elaboration.
// Since the fix for scala/bug#7335 Predef parents must be defined in Predef.scala, and we should not
// get here anymore.
devWarning(s"calling Symbol#exists with sourcefile based symbol loader may give incorrect results.")
false
}

rawInfo load this
rawInfo != NoType || { warnIfSourceLoader(); false }
rawInfo.load(this)
rawInfo != NoType || warnIfSourceLoader()
}

final def isInitialized: Boolean =
Expand Down
3 changes: 3 additions & 0 deletions test/files/pos/t12736/bar_2.scala
@@ -0,0 +1,3 @@
package bar

private object Foo
15 changes: 15 additions & 0 deletions test/files/pos/t12736/baz_2.scala
@@ -0,0 +1,15 @@
package bar
package baz

import foo._

object Bar {
def test() = println(Foo)
}

/*
baz_2.scala:8: error: object Foo in package foo cannot be accessed as a member of package foo from object Bar in package baz
def test() = println(Foo)
^
1 error
*/
3 changes: 3 additions & 0 deletions test/files/pos/t12736/foo_1.scala
@@ -0,0 +1,3 @@
package foo

private object Foo

0 comments on commit d4e0f8b

Please sign in to comment.