summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdriaan Moors <adriaan.moors@epfl.ch>2010-08-09 11:51:37 +0000
committerAdriaan Moors <adriaan.moors@epfl.ch>2010-08-09 11:51:37 +0000
commit3ac03c3d3f0e21f279ba8c405351e445af623ceb (patch)
treeea405a577a99904525cc9b3042d7c5ac207ae20c
parent40aafbdf1a9a52c1236f07e06d48fb24b5fa2169 (diff)
downloadscala-3ac03c3d3f0e21f279ba8c405351e445af623ceb.tar.gz
scala-3ac03c3d3f0e21f279ba8c405351e445af623ceb.tar.bz2
scala-3ac03c3d3f0e21f279ba8c405351e445af623ceb.zip
closes #3582: typedTypeDef needs to run in a ne...
closes #3582: typedTypeDef needs to run in a new typer for TypeDefs with type parameters this was honored when typedTypeDef was called by typed1, but other callers did not this would cause higher-order type parameters to be re-entered in the scope of a method or a class (by the way, should we recycle scopes for higher-order type params? now new scopes are created, symbols entered, and tree's symbols updated) changed some spurious vars to vals review by odersky
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Types.scala2
-rw-r--r--src/compiler/scala/tools/nsc/transform/TypingTransformers.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Namers.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala16
-rw-r--r--test/files/pos/t3582.scala12
-rw-r--r--test/files/pos/t3582b.scala5
6 files changed, 33 insertions, 6 deletions
diff --git a/src/compiler/scala/tools/nsc/symtab/Types.scala b/src/compiler/scala/tools/nsc/symtab/Types.scala
index 9e10d3a408..acf4f6d43d 100644
--- a/src/compiler/scala/tools/nsc/symtab/Types.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Types.scala
@@ -137,7 +137,7 @@ trait Types extends reflect.generic.Types { self: SymbolTable =>
* It makes use of the fact that these two operations depend only on the parents,
* not on the refinement.
*/
- var intersectionWitness = new WeakHashMap[List[Type], Type]
+ val intersectionWitness = new WeakHashMap[List[Type], Type]
private object gen extends {
val global : Types.this.type = Types.this
diff --git a/src/compiler/scala/tools/nsc/transform/TypingTransformers.scala b/src/compiler/scala/tools/nsc/transform/TypingTransformers.scala
index 6656b79d26..de5355de61 100644
--- a/src/compiler/scala/tools/nsc/transform/TypingTransformers.scala
+++ b/src/compiler/scala/tools/nsc/transform/TypingTransformers.scala
@@ -26,7 +26,7 @@ trait TypingTransformers {
protected def typedPos(pos: Position)(tree: Tree) = localTyper typed { atPos(pos)(tree) }
/** a typer for each enclosing class */
- var typers: Map[Symbol, analyzer.Typer] = new HashMap
+ val typers: Map[Symbol, analyzer.Typer] = new HashMap
override def atOwner[A](owner: Symbol)(trans: => A): A = atOwner(curTree, owner)(trans)
diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
index 5687917e46..22a1bee9b2 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
@@ -297,7 +297,7 @@ trait Namers { self: Analyzer =>
val sym = tree.symbol
if (settings.debug.value) log("entered " + sym + " in " + context.owner + ", scope-id = " + context.scope.## )
var ltype = namerOf(sym).typeCompleter(tree)
- if (!tparams.isEmpty) {
+ if (tparams nonEmpty) {
//@M! TypeDef's type params are handled differently
//@M e.g., in [A[x <: B], B], A and B are entered first as both are in scope in the definition of x
//@M x is only in scope in `A[x <: B]'
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index cbdbadc4bf..381b1ceed3 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -1788,8 +1788,18 @@ trait Typers { self: Analyzer =>
}
def typedTypeDef(tdef: TypeDef): TypeDef = {
- reenterTypeParams(tdef.tparams) // @M!
- val tparams1 = tdef.tparams mapConserve (typedTypeDef) // @M!
+ def typeDefTyper = {
+ if(tdef.tparams isEmpty) Typer.this
+ else newTyper(context.makeNewScope(tdef, tdef.symbol))
+ }
+ typeDefTyper.typedTypeDef0(tdef)
+ }
+
+ // call typedTypeDef instead
+ // a TypeDef with type parameters must always be type checked in a new scope
+ private def typedTypeDef0(tdef: TypeDef): TypeDef = {
+ reenterTypeParams(tdef.tparams)
+ val tparams1 = tdef.tparams mapConserve {typedTypeDef(_)}
val typedMods = removeAnnotations(tdef.mods)
// complete lazy annotations
val annots = tdef.symbol.annotations
@@ -3803,7 +3813,7 @@ trait Typers { self: Analyzer =>
newTyper(context.makeNewScope(tree, sym)).typedDefDef(ddef)
case tdef @ TypeDef(_, _, _, _) =>
- newTyper(context.makeNewScope(tree, sym)).typedTypeDef(tdef)
+ typedTypeDef(tdef)
case ldef @ LabelDef(_, _, _) =>
labelTyper(ldef).typedLabelDef(ldef)
diff --git a/test/files/pos/t3582.scala b/test/files/pos/t3582.scala
new file mode 100644
index 0000000000..0ac112efbf
--- /dev/null
+++ b/test/files/pos/t3582.scala
@@ -0,0 +1,12 @@
+trait C[A]
+object Test {
+ def ImplicitParamCA[CC[A], A](implicit ev: C[A]) {implicitly[C[A]]} // must use this exact syntax...
+ // error: could not find implicit value for parameter e: C[A]
+}
+// [[syntax trees at end of typer]]
+// abstract trait C#5[A#9116 >: Nothing#5832 <: Any#52] extends scala#33.AnyRef#2780;
+// final object Test#15 extends java.lang.Object#2485 with ScalaObject#1913 {
+// def ImplicitParamCA#9123[CC#9124[A#10858 >: Nothing#5832 <: Any#52] >: [A#10858]Nothing#5832 <: [A#10858]Any#52,
+// A#9125 >: Nothing#5832 <: Any#52](implicit ev#10856: C#5[A#9127]): Unit#3818
+// = scala#34.this.Predef#1683.implicitly#8816[C#5[A#10858]]()
+// }
diff --git a/test/files/pos/t3582b.scala b/test/files/pos/t3582b.scala
new file mode 100644
index 0000000000..8f0bfb9b2a
--- /dev/null
+++ b/test/files/pos/t3582b.scala
@@ -0,0 +1,5 @@
+object ParamScoping {
+ // scoping worked fine in the result type, but was wrong in body
+ // reason: typedTypeDef needs new context, which was set up by typed1 but not by typedDefDef and typedClassDef
+ def noOverlapFOwithHO[T, G[T]]: G[T] = null.asInstanceOf[G[T]]
+} \ No newline at end of file