diff options
author | Adriaan Moors <adriaan.moors@typesafe.com> | 2012-12-10 14:19:37 -0800 |
---|---|---|
committer | Adriaan Moors <adriaan.moors@typesafe.com> | 2012-12-10 14:19:37 -0800 |
commit | 7fe7d2537963dd24ea1cca7b0c4b96f96b773c4a (patch) | |
tree | 337f28aea9381b89bac3c9ed1e80443f636ec62a | |
parent | 38b92224536b5d6619364c8266232569b12f6a26 (diff) | |
parent | 0b1ae9cef4391775f0137332cc0cbd6136fe71b0 (diff) | |
download | scala-7fe7d2537963dd24ea1cca7b0c4b96f96b773c4a.tar.gz scala-7fe7d2537963dd24ea1cca7b0c4b96f96b773c4a.tar.bz2 scala-7fe7d2537963dd24ea1cca7b0c4b96f96b773c4a.zip |
Merge pull request #1701 from retronym/ticket/5877
SI-5877 Support implicit classes in package objects
-rw-r--r-- | src/compiler/scala/tools/nsc/CompilationUnits.scala | 20 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Typers.scala | 6 | ||||
-rw-r--r-- | test/files/pos/t5877.scala | 14 | ||||
-rw-r--r-- | test/files/pos/t5877b.scala | 13 |
4 files changed, 50 insertions, 3 deletions
diff --git a/src/compiler/scala/tools/nsc/CompilationUnits.scala b/src/compiler/scala/tools/nsc/CompilationUnits.scala index 4e7ba60d5e..355a1fd262 100644 --- a/src/compiler/scala/tools/nsc/CompilationUnits.scala +++ b/src/compiler/scala/tools/nsc/CompilationUnits.scala @@ -23,7 +23,7 @@ trait CompilationUnits { self: Global => /** One unit of compilation that has been submitted to the compiler. * It typically corresponds to a single file of source code. It includes * error-reporting hooks. */ - class CompilationUnit(val source: SourceFile) extends CompilationUnitContextApi { + class CompilationUnit(val source: SourceFile) extends CompilationUnitContextApi { self => /** the fresh name creator */ var fresh: FreshNameCreator = new FreshNameCreator.Default @@ -57,7 +57,23 @@ trait CompilationUnits { self: Global => /** Synthetic definitions generated by namer, eliminated by typer. */ - val synthetics = mutable.HashMap[Symbol, Tree]() + object synthetics { + private val map = mutable.HashMap[Symbol, Tree]() + def update(sym: Symbol, tree: Tree) { + debuglog(s"adding synthetic ($sym, $tree) to $self") + map.update(sym, tree) + } + def -=(sym: Symbol) { + debuglog(s"removing synthetic $sym from $self") + map -= sym + } + def get(sym: Symbol): Option[Tree] = logResultIf[Option[Tree]](s"found synthetic for $sym in $self", _.isDefined) { + map get sym + } + def keys: Iterable[Symbol] = map.keys + def clear(): Unit = map.clear() + override def toString = map.toString + } /** things to check at end of compilation unit */ val toCheck = new ListBuffer[() => Unit] diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 0d6d051475..83ded04c39 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -2956,7 +2956,11 @@ trait Typers extends Modes with Adaptations with Tags { var moreToAdd = true while (moreToAdd) { val initElems = scope.elems - for (sym <- scope) + // SI-5877 The decls of a package include decls of the package object. But we don't want to add + // the corresponding synthetics to the package class, only to the package object class. + def shouldAdd(sym: Symbol) = + inBlock || !isInPackageObject(sym, context.owner) + for (sym <- scope if shouldAdd(sym)) for (tree <- context.unit.synthetics get sym) { newStats += typedStat(tree) // might add even more synthetics to the scope context.unit.synthetics -= sym diff --git a/test/files/pos/t5877.scala b/test/files/pos/t5877.scala new file mode 100644 index 0000000000..c7827df99f --- /dev/null +++ b/test/files/pos/t5877.scala @@ -0,0 +1,14 @@ +package foo { + class Foo + + object Test { + new Foo().huzzah + } +} + +package object foo { + // Crasher: No synthetics for method PimpedFoo2: synthetics contains + implicit class PimpedFoo2(value: Foo) { + def huzzah = "" + } +} diff --git a/test/files/pos/t5877b.scala b/test/files/pos/t5877b.scala new file mode 100644 index 0000000000..6b8cbd473e --- /dev/null +++ b/test/files/pos/t5877b.scala @@ -0,0 +1,13 @@ +package foo + +class Foo + +object Test { + new Foo().huzzah +} + +object `package` { + implicit class PimpedFoo2(value: Foo) { + def huzzah = "" + } +} |