summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2007-11-01 17:35:15 +0000
committerMartin Odersky <odersky@gmail.com>2007-11-01 17:35:15 +0000
commit3a4750825e3b3992adcddd4666f264d508e21f7a (patch)
tree1ed1eae169a180c46ceb23a3ab93a00d0e5deed0
parentb14c210baba254900b2b999b4c648526a5a7846e (diff)
downloadscala-3a4750825e3b3992adcddd4666f264d508e21f7a.tar.gz
scala-3a4750825e3b3992adcddd4666f264d508e21f7a.tar.bz2
scala-3a4750825e3b3992adcddd4666f264d508e21f7a.zip
fixed ticket 91
-rw-r--r--src/compiler/scala/tools/nsc/ast/TreeGen.scala21
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Symbols.scala12
-rw-r--r--src/compiler/scala/tools/nsc/transform/Mixin.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala21
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala15
-rw-r--r--test/files/pos/typerep-stephane.scala48
-rw-r--r--test/files/pos/typerep.scala21
-rw-r--r--test/files/run/t091.check1
-rw-r--r--test/files/run/t091.scala13
9 files changed, 130 insertions, 24 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/TreeGen.scala b/src/compiler/scala/tools/nsc/ast/TreeGen.scala
index c90ea60b12..6bc136e976 100644
--- a/src/compiler/scala/tools/nsc/ast/TreeGen.scala
+++ b/src/compiler/scala/tools/nsc/ast/TreeGen.scala
@@ -208,13 +208,20 @@ abstract class TreeGen {
ValDef(mvar, if (mvar.owner.isClass) EmptyTree else Literal(Constant(null)))
}
- // def m: T = { if (m$ eq null) m$ = new m$class; m$ }
- def mkModuleAccessDef(accessor: Symbol, mvar: Symbol) =
- DefDef(accessor, vparamss =>
- mkCached(mvar,
- New(TypeTree(mvar.tpe),
- List(for (pt <- mvar.tpe.typeSymbol.primaryConstructor.info.paramTypes)
- yield This(accessor.owner.enclClass)))))
+ // def m: T = { if (m$ eq null) m$ = new m$class(...) m$ }
+ // where (...) are eventual outer accessors
+ def mkCachedModuleAccessDef(accessor: Symbol, mvar: Symbol) =
+ DefDef(accessor, vparamss => mkCached(mvar, newModule(accessor, mvar.tpe)))
+
+ // def m: T = new tpe(...)
+ // where (...) are eventual outer accessors
+ def mkModuleAccessDef(accessor: Symbol, tpe: Type) =
+ DefDef(accessor, vparamss => newModule(accessor, tpe))
+
+ private def newModule(accessor: Symbol, tpe: Type) =
+ New(TypeTree(tpe),
+ List(for (pt <- tpe.typeSymbol.primaryConstructor.info.paramTypes)
+ yield This(accessor.owner.enclClass)))
// def m: T;
def mkModuleAccessDcl(accessor: Symbol) =
diff --git a/src/compiler/scala/tools/nsc/symtab/Symbols.scala b/src/compiler/scala/tools/nsc/symtab/Symbols.scala
index 0b801fca89..c735c953bf 100644
--- a/src/compiler/scala/tools/nsc/symtab/Symbols.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Symbols.scala
@@ -611,6 +611,18 @@ trait Symbols {
def getAttributes(clazz: Symbol): List[AnnotationInfo] =
attributes.filter(_.atp.typeSymbol.isNonBottomSubClass(clazz))
+ /** The least proper supertype of a class; includes all parent types
+ * and refinement where needed */
+ def classBound: Type = {
+ val tp = refinedType(info.parents, owner)
+ val thistp = tp.typeSymbol.thisType
+ for (sym <- info.decls.toList) {
+ if (sym.isPublic && !sym.isClass && !sym.isConstructor)
+ addMember(thistp, tp, sym.cloneSymbol(tp.typeSymbol).setInfo(sym.info))
+ }
+ tp
+ }
+
/** Reset symbol to initial state
*/
def reset(completer: Type) {
diff --git a/src/compiler/scala/tools/nsc/transform/Mixin.scala b/src/compiler/scala/tools/nsc/transform/Mixin.scala
index 7289468406..9803294ae9 100644
--- a/src/compiler/scala/tools/nsc/transform/Mixin.scala
+++ b/src/compiler/scala/tools/nsc/transform/Mixin.scala
@@ -630,7 +630,7 @@ abstract class Mixin extends InfoTransform {
// add modules
val vdef = gen.mkModuleVarDef(sym)
addDef(position(sym), vdef)
- addDef(position(sym), gen.mkModuleAccessDef(sym, vdef.symbol))
+ addDef(position(sym), gen.mkCachedModuleAccessDef(sym, vdef.symbol))
} else if (!sym.isMethod) {
// add fields
addDef(position(sym), ValDef(sym))
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
index fb10d2b1b2..ffecaf5a39 100644
--- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
@@ -598,8 +598,23 @@ abstract class RefChecks extends InfoTransform {
.setPos(tree.pos)
.setSymbol(sym.moduleClass)
.setType(NoType);
- if (sym.isStatic) List(transform(cdef))
- else {
+ if (sym.isStatic) {
+ if (!sym.allOverriddenSymbols.isEmpty) {
+ val factory = sym.owner.newMethod(sym.pos, sym.name)
+ .setFlag(sym.flags | STABLE).resetFlag(MODULE)
+ .setInfo(PolyType(List(), sym.moduleClass.tpe))
+ sym.owner.info.decls.enter(factory)
+ val ddef =
+ atPhase(phase.next) {
+ localTyper.typed {
+ gen.mkModuleAccessDef(factory, sym.tpe)
+ }
+ }
+ transformTrees(List(cdef, ddef))
+ } else {
+ List(transform(cdef))
+ }
+ } else {
val vdef =
localTyper.typed {
atPos(tree.pos) {
@@ -611,7 +626,7 @@ abstract class RefChecks extends InfoTransform {
atPhase(phase.next) {
localTyper.typed {
if (sym.owner.isTrait) gen.mkModuleAccessDcl(sym)
- else gen.mkModuleAccessDef(sym, vdef.symbol)
+ else gen.mkCachedModuleAccessDef(sym, vdef.symbol)
}
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index ab07c52a07..ef56d827c4 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -358,7 +358,7 @@ trait Typers { self: Analyzer =>
else if (hiddenSymbols exists (_.isErroneous)) setError(tree)
else if (isFullyDefined(pt)) tree setType pt //todo: eliminate
else if (tp1.typeSymbol.isAnonymousClass) // todo: eliminate
- check(owner, scope, pt, tree setType classBound(tp1.typeSymbol))
+ check(owner, scope, pt, tree setType tp1.typeSymbol.classBound)
else if (owner == NoSymbol)
tree setType packSymbols(hiddenSymbols.reverse, tp1)
else { // privates
@@ -1331,16 +1331,6 @@ trait Typers { self: Analyzer =>
copy.LabelDef(ldef, ldef.name, ldef.params, rhs1) setType restpe
}
- def classBound(clazz: Symbol): Type = {
- val tp = refinedType(clazz.info.parents, clazz.owner)
- val thistp = tp.typeSymbol.thisType
- for (sym <- clazz.info.decls.toList) {
- if (sym.isPublic && !sym.isClass && !sym.isConstructor)
- addMember(thistp, tp, sym.cloneSymbol(tp.typeSymbol).setInfo(sym.info))
- }
- tp
- }
-
protected def typedFunctionIDE(fun : Function, txt : Context) = {}
/**
@@ -1857,8 +1847,7 @@ trait Typers { self: Analyzer =>
protected def existentialBound(sym: Symbol): Type =
if (sym.isClass)
- parameterizedType(
- sym.typeParams, mkTypeBounds(AllClass.tpe, classBound(sym)))
+ parameterizedType(sym.typeParams, mkTypeBounds(AllClass.tpe, sym.classBound))
else if (sym.isAbstractType)
sym.info
else if (sym.isTerm)
diff --git a/test/files/pos/typerep-stephane.scala b/test/files/pos/typerep-stephane.scala
new file mode 100644
index 0000000000..1061212369
--- /dev/null
+++ b/test/files/pos/typerep-stephane.scala
@@ -0,0 +1,48 @@
+object typerep {
+
+ class TypeRep[T] {
+ def getType: TypeRep[T] = this
+ }
+
+ object BooleanRep extends TypeRep[Boolean] {
+ override def toString = "Boolean"
+ }
+ object CharRep extends TypeRep[Char] {
+ override def toString = "Char"
+ }
+ object IntRep extends TypeRep[Int] {
+ override def toString = "Int"
+ }
+ object LongRep extends TypeRep[Long] {
+ override def toString = "Long"
+ }
+ object FloatRep extends TypeRep[Float] {
+ override def toString = "Float"
+ }
+ object DoubleRep extends TypeRep[Double] {
+ override def toString = "Double"
+ }
+ class ListRep[U, T <: List[U]](val elemRep: TypeRep[U]) extends TypeRep[T] {
+ override def toString = "List[" + elemRep + "]"
+ }
+
+ implicit def typeRep(x: Boolean): TypeRep[Boolean] = BooleanRep
+ implicit def typeRep(x: Char ): TypeRep[Char ] = CharRep
+ implicit def typeRep(x: Long ): TypeRep[Long ] = LongRep
+ implicit def typeRep(x: Float ): TypeRep[Float ] = FloatRep
+ implicit def typeRep(x: Double ): TypeRep[Double ] = DoubleRep
+ implicit def typeRep(x: Int ): TypeRep[Int ] = IntRep
+/*
+ implicit def typeRep[T](xs: List[T])(implicit rep: T => TypeRep[T]): TypeRep[List[T]] =
+ new ListRep(rep(xs.head))
+*/
+ implicit def typeRep[T <% TypeRep[T]](xs: List[T]): TypeRep[List[T]] =
+ new ListRep(xs.head)
+
+}
+
+object test extends Application {
+ import typerep._
+ println(3.getType)
+ println(List(3).getType)
+}
diff --git a/test/files/pos/typerep.scala b/test/files/pos/typerep.scala
new file mode 100644
index 0000000000..7faa8a1928
--- /dev/null
+++ b/test/files/pos/typerep.scala
@@ -0,0 +1,21 @@
+object typerep extends Application {
+ class TypeRep[T] {}
+ case object IntRep extends TypeRep[Int] {
+ override def toString = "Int"
+ }
+ case object BooleanRep extends TypeRep[Boolean] {
+ override def toString = "Boolean"
+ }
+ case class ListRep[T](elemrep: TypeRep[T]) extends TypeRep[List[T]] {
+ override def toString = "List"
+ }
+
+ implicit def intRep: TypeRep[Int] = IntRep
+ implicit def booleanRep: TypeRep[Boolean] = BooleanRep
+ implicit def listRep[T](implicit elemrep: TypeRep[T]): TypeRep[List[T]] = ListRep(elemrep)
+
+ def getType[T](x: T)(implicit rep: TypeRep[T]): TypeRep[T] = rep
+
+ println(getType(1))
+ println(getType(List(1)))
+}
diff --git a/test/files/run/t091.check b/test/files/run/t091.check
new file mode 100644
index 0000000000..7ed6ff82de
--- /dev/null
+++ b/test/files/run/t091.check
@@ -0,0 +1 @@
+5
diff --git a/test/files/run/t091.scala b/test/files/run/t091.scala
new file mode 100644
index 0000000000..eaddde0dbf
--- /dev/null
+++ b/test/files/run/t091.scala
@@ -0,0 +1,13 @@
+trait A { def x : Int }
+trait B { val m : A }
+object C extends B {
+ object m extends A { def x = 5 }
+}
+object Test {
+ // The type annotation here is necessary, otherwise
+ // the compiler would reference C$m$ directly.
+ def o : B = C
+ def main(argv : Array[String]) : Unit = {
+ println(o.m.x)
+ }
+}