when namespaces collide

129 views
Skip to first unread message

Paul Phillips

unread,
Aug 2, 2012, 4:38:13 PM8/2/12
to scala-l...@googlegroups.com
In general a source file is treated as if it had these leading imports:

  import java.lang._
  import scala._
  import Predef._

This means the imported identifiers are subject to being masked.  Now where do identifiers come from? One place you get root-scoped identifiers is from your classpath.  Every top-level package is an identifier.  Which are the top-level packages? Beyond those in jars, for every directory on your classpath, every direct subdirectory is a top-level package, at least in the mind of scalac.

This has extremely perverse consequences:

% scalac ./a.scala
% mkdir any2stringadd
% scalac ./a.scala 
./a.scala:2: error: value + is not a member of object Test
  println(this + "")
               ^
one error found

The only thing more fun than a bug like that is watching it come and go based on your current working directory, since "." is the default classpath.

This came to my attention most recently because we have source files which do things like this:

  self: tools.nsc.Global =>

This can't be compiled from the repository root without changing one's classpath because the repository has a root-level directory called "tools".  There are no classfiles in that directory, but scalac doesn't care, it's going to shadow scala.tools.

Surely we don't have to accept this quantity of non-determinism.

Josh Suereth

unread,
Aug 2, 2012, 4:46:39 PM8/2/12
to scala-l...@googlegroups.com

+1
I, just recently, ran into trouble using tuples when a sub package was named "scala".  

Paul Phillips

unread,
Aug 2, 2012, 5:27:51 PM8/2/12
to scala-l...@googlegroups.com
If you have a strong stomach, see the attached files, which are the output from attempting to compile each of (compiler, library, reflect) after doing this:

mkdir $(find /scala/trunk/src/{library,compiler,reflect}/scala -maxdepth 1 -type d |xargs basename |sort -u)

Which gives us these empty directories:

  annotation beans collection compat concurrent io math parallel   
  ref reflect runtime scala sys testing text tools util xml

Not only do all of them explode horribly, 2/3 crash (in different ways) which strongly suggests the compiler is preferring these empty directories to its own scala subpackages not only for resolving the identifiers in source code but during its operation.  Here's what we can see it admit to before the forces of crashiness overwhelm the defenses.

Remember, the only thing making all this happen is that there are some empty subdirectories of my current directory.


Global.scala:57: error: not found: type Mirror
Contexts.scala:97: error: not found: type Tree
Contexts.scala:115: error: not found: type Type
Contexts.scala:115: error: not found: type Tree
Macros.scala:44: error: not found: value definitions
ExprUtils.scala:10: error: not found: value Literal
ExprUtils.scala:12: error: not found: value Literal
ExprUtils.scala:14: error: not found: value Literal
ExprUtils.scala:16: error: not found: value Literal
ExprUtils.scala:18: error: not found: value Literal
ExprUtils.scala:20: error: not found: value Literal
ExprUtils.scala:22: error: not found: value Literal
ExprUtils.scala:24: error: not found: value Literal
ExprUtils.scala:26: error: not found: value Literal
ExprUtils.scala:28: error: not found: value Literal
ExprUtils.scala:30: error: not found: value Literal
ExprUtils.scala:32: error: not found: value Literal
ExprUtils.scala:34: error: not found: value Literal
Contexts.scala:397: error: not found: type TypeError
CompilationUnits.scala:35: error: not found: type Tree
Macros.scala:49: error: not found: value perRunCaches
Reifiers.scala:14: error: not found: value definitions
Reifiers.scala:39: error: not found: value ExprSplice
Reifiers.scala:40: error: not found: value Select
SymbolTables.scala:11: error: not found: value definitions
SymbolTables.scala:12: error: not found: value Flag
SymbolTables.scala:23: error: not found: type Tree
Extractors.scala:8: error: not found: value definitions
Extractors.scala:9: error: not found: value Flag
Extractors.scala:194: error: not found: type Tree
Extractors.scala:194: error: not found: type TermName
Extractors.scala:194: error: not found: type Tree
Extractors.scala:194: error: not found: type Tree
Reifiers.scala:65: error: not found: value binding
Reifiers.scala:66: error: not found: value showRaw
Extractors.scala:213: error: not found: type Tree
Extractors.scala:213: error: not found: type TermName
Extractors.scala:213: error: not found: type Tree
Extractors.scala:213: error: not found: type Tree
Reifiers.scala:67: error: not found: value binding
Reifiers.scala:68: error: not found: value showRaw
Extractors.scala:127: error: not found: type Tree
Extractors.scala:127: error: not found: type Tree
Extractors.scala:127: error: not found: type Tree
Extractors.scala:127: error: not found: type Type
Extractors.scala:127: error: not found: type Tree
Extractors.scala:127: error: not found: type Tree
Reifiers.scala:75: error: not found: value symtab
Extractors.scala:154: error: not found: type Tree
Extractors.scala:154: error: not found: type Tree
Extractors.scala:154: error: not found: type Type
GenericTraversableTemplate.scala:29: error: not found: type uncheckedVariance
ScalaNumberProxy.scala:23: error: not found: type ScalaNumericConversions
GenericParTemplate.scala:28: error: not found: type uncheckedVariance
TraversableOnce.scala:257: error: not found: type uV
TraversableOnce.scala:257: error: not found: type uV
TraversableOnce.scala:232: error: not found: type ClassTag
ParMap.scala:34: error: not found: type GenericParMapTemplate
ParMapLike.scala:39: error: not found: type Growable
ParMapLike.scala:40: error: not found: type Shrinkable
TrieMap.scala:641: error: not found: type ParTrieMap
TrieMap.scala:435: error: not found: type ImmutableListMap
TrieMap.scala:437: error: not found: value ImmutableListMap
TrieMap.scala:438: error: not found: value ImmutableListMap
TrieMap.scala:638: error: not found: type Hashing
TrieMap.scala:644: error: not found: value Hashing
TrieMap.scala:921: error: not found: type Hashing
ParMap.scala:71: error: not found: type ParMapFactory
ParMap.scala:76: error: not found: type CanCombineFrom
TrieMap.scala:651: error: not found: type Hashing
TrieMap.scala:658: error: not found: value Hashing
TrieMap.scala:679: error: not found: type Hashing
TrieMap.scala:783: error: not found: type ParTrieMap
Position.scala:39: error: not found: type PositionApi
Statistics.scala:193: error: not found: value mutable
Statistics.scala:193: error: not found: value mutable
BaseTypeSeqs.scala:135: error: not found: value max
Chars.scala:54: error: not found: type switch
Chars.scala:89: error: not found: type switch
ClassfileConstants.scala:341: error: not found: type switch
Definitions.scala:933: error: not found: value meta
Definitions.scala:934: error: not found: value meta
Definitions.scala:935: error: not found: value meta
Definitions.scala:936: error: not found: value meta
Definitions.scala:937: error: not found: value meta
Definitions.scala:938: error: not found: value meta
Definitions.scala:939: error: not found: value meta
Definitions.scala:940: error: not found: value meta
Definitions.scala:941: error: not found: value meta
Definitions.scala:942: error: not found: value meta
UnPickler.scala:322: error: not found: type switch
UnPickler.scala:401: error: not found: type switch
UnPickler.scala:460: error: not found: type ListBuffer
UnPickler.scala:461: error: not found: type ListBuffer
Printers.scala:517: error: not found: value EOL
Printers.scala:521: error: not found: value EOL
Trees.scala:1412: error: not found: type ListBuffer
Trees.scala:1420: error: not found: type ListBuffer
Position.scala:45: error: not found: type Attachments
Statistics.scala:238: error: not found: value mutable
Statistics.scala:121: error: not found: value mutable
TwoWayCache.scala:16: error: not found: type WeakHashMap
TwoWayCache.scala:17: error: not found: type WeakHashMap
JavaMirrors.scala:794: error: not found: type ListBuffer
SymbolLoaders.scala:106: error: not found: value mutable
TwoWayCache.scala:36: error: not found: value v

compiler.txt
library.txt
reflect.txt

Josh Suereth

unread,
Aug 3, 2012, 7:54:17 AM8/3/12
to scala-l...@googlegroups.com

Can we open a bug for that?  Is there one?  

Mine had to do with having a relative scala package destroying Tuple extractor usage, even with manual _root_ imports.    I'll try to deduplicate when I have the chance.

Paul Phillips

unread,
Aug 3, 2012, 3:14:13 PM8/3/12
to scala-l...@googlegroups.com
On Fri, Aug 3, 2012 at 4:54 AM, Josh Suereth <joshua....@gmail.com> wrote:

Mine had to do with having a relative scala package destroying Tuple extractor usage, even with manual _root_ imports.    I'll try to deduplicate when I have the chance.

I know too well why that is.  However I tried once long ago to construct all internal names with _root_ and it didn't work for reasons I couldn't figure out at the time.  But clearly the fact that we synthesize trees like Select(Ident("scala"), "Tuple2") is going to break down when scala is shadowed.

I can straightforwardly deal with the interactions I'm describing in this thread in all cases except if "scala" itself is shadowed.  The changes necessary to really deal with that, I don't see them happening.  I'd much rather disallow or at least openly discourage scala as a package name.  One has to pick one's time-consuming battles.

Reply all
Reply to author
Forward
0 new messages