summaryrefslogtreecommitdiff
path: root/src/compiler
diff options
context:
space:
mode:
authorLex Spoon <lex@lexspoon.org>2007-12-12 19:50:58 +0000
committerLex Spoon <lex@lexspoon.org>2007-12-12 19:50:58 +0000
commita891b5b274428c8cdb0ba3fc5e96cb7cb7cbd433 (patch)
tree405fb81461f2aaa5a2690396fc8de16acb69e5c3 /src/compiler
parentbd42999939b338728a3c96bcfa74166f51a8b341 (diff)
downloadscala-a891b5b274428c8cdb0ba3fc5e96cb7cb7cbd433.tar.gz
scala-a891b5b274428c8cdb0ba3fc5e96cb7cb7cbd433.tar.bz2
scala-a891b5b274428c8cdb0ba3fc5e96cb7cb7cbd433.zip
Added the AnnotationCheckers registry, so that
plugins can modify isSubType0 and typed().
Diffstat (limited to 'src/compiler')
-rw-r--r--src/compiler/scala/tools/nsc/symtab/AnnotationCheckers.scala60
-rw-r--r--src/compiler/scala/tools/nsc/symtab/SymbolTable.scala1
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Types.scala28
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala3
4 files changed, 83 insertions, 9 deletions
diff --git a/src/compiler/scala/tools/nsc/symtab/AnnotationCheckers.scala b/src/compiler/scala/tools/nsc/symtab/AnnotationCheckers.scala
new file mode 100644
index 0000000000..ce1669c456
--- /dev/null
+++ b/src/compiler/scala/tools/nsc/symtab/AnnotationCheckers.scala
@@ -0,0 +1,60 @@
+/* NSC -- new Scala compiler
+ * Copyright 2007-2008 LAMP/EPFL
+ * @author Martin Odersky
+ */
+// $Id: AnnotationInfos.scala 13367 2007-11-28 05:17:14Z spoon $
+
+package scala.tools.nsc.symtab
+
+/** Additions to the type checker that can be added at
+ * run time. Typically these are added by
+ * compiler plugins. */
+trait AnnotationCheckers {
+ self: SymbolTable =>
+
+
+ /** An additional checker for annotations on types.
+ * Typically these are registered by compiler plugins
+ * with the addAnnotationChecker method. */
+ abstract class AnnotationChecker {
+ /** Check the annotations on two types conform. */
+ def annotationsConform(tpe1: Type, tpe2: Type): Boolean
+
+ /** Modify the type that has thus far been inferred
+ * for a tree. All this should do is add annotations. */
+ def addAnnotations(tree: Tree, tpe: Type): Type = tpe
+ }
+
+ /** The list of annotation checkers that have been registered */
+ private var annotationCheckers: List[AnnotationChecker] = Nil
+
+ /** Register an annotation checker. Typically these
+ * are added by compiler plugins. */
+ def addAnnotationChecker(checker: AnnotationChecker) {
+ if (!(annotationCheckers contains checker))
+ annotationCheckers = checker :: annotationCheckers
+ }
+
+ /** Remove all annotation checkers */
+ def removeAllAnnotationCheckers() {
+ annotationCheckers = Nil
+ }
+
+ /** Check that the annotations on two types conform. To do
+ * so, consult all registered annotation checkers. */
+ def annotationsConform(tp1: Type, tp2: Type): Boolean = {
+ /* Finish quickly if there are no attributes */
+ if (tp1.attributes.isEmpty && tp2.attributes.isEmpty)
+ true
+ else
+ annotationCheckers.forall(
+ _.annotationsConform(tp1,tp2))
+ }
+
+ /** Let all annotations checkers add extra annotations
+ * to this tree's type. */
+ def addAnnotations(tree: Tree, tpe: Type): Type = {
+ annotationCheckers.foldLeft(tpe)((tpe, checker) =>
+ checker.addAnnotations(tree, tpe))
+ }
+}
diff --git a/src/compiler/scala/tools/nsc/symtab/SymbolTable.scala b/src/compiler/scala/tools/nsc/symtab/SymbolTable.scala
index de4fa90b7e..e02e16d0aa 100644
--- a/src/compiler/scala/tools/nsc/symtab/SymbolTable.scala
+++ b/src/compiler/scala/tools/nsc/symtab/SymbolTable.scala
@@ -18,6 +18,7 @@ abstract class SymbolTable extends Names
with InfoTransformers
with StdNames
with AnnotationInfos
+ with AnnotationCheckers
with Trees
{
def settings: Settings
diff --git a/src/compiler/scala/tools/nsc/symtab/Types.scala b/src/compiler/scala/tools/nsc/symtab/Types.scala
index 0a6aa4df52..c1c2448e31 100644
--- a/src/compiler/scala/tools/nsc/symtab/Types.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Types.scala
@@ -183,8 +183,8 @@ trait Types {
override def isComplete = underlying.isComplete
override def complete(sym: Symbol) = underlying.complete(sym)
override def load(sym: Symbol): Unit = underlying.load(sym)
- override def withAttributes(attribs: List[AnnotationInfo]) = underlying.withAttributes(attribs)
- override def withoutAttributes = underlying.withoutAttributes
+ override def withAttributes(attribs: List[AnnotationInfo]) = maybeRewrap(underlying.withAttributes(attribs))
+ override def withoutAttributes = maybeRewrap(underlying.withoutAttributes)
}
/** The base class for all types */
@@ -736,9 +736,13 @@ trait Types {
case _ => AnnotatedType(attribs, this, NoSymbol)
}
- /** Remove any attributes from this type */
+ /** Remove any annotations from this type */
def withoutAttributes = this
+ /** Remove any annotations from this type and from any
+ * types embedded in this type. */
+ def stripAnnotations = StripAnnotationsMap(this)
+
/** Set the self symbol of an annotated type, or do nothing
* otherwise. */
def withSelfsym(sym: Symbol) = this
@@ -2844,6 +2848,15 @@ A type's typeSymbol should never be inspected directly.
}
}
+ object StripAnnotationsMap extends TypeMap {
+ def apply(tp: Type): Type = tp match {
+ case AnnotatedType(_, atp, _) =>
+ mapOver(atp)
+ case tp =>
+ mapOver(tp)
+ }
+ }
+
/** A map to convert every occurrence of a wildcard type to a fresh
* type variable */
object wildcardToTypeVarMap extends TypeMap {
@@ -3422,7 +3435,8 @@ A type's typeSymbol should never be inspected directly.
/** Does type `tp1' conform to `tp2'?
*/
private def isSubType0(tp1: Type, tp2: Type): Boolean = {
- (tp1, tp2) match {
+ annotationsConform(tp1, tp2) &&
+ ((tp1.withoutAttributes, tp2.withoutAttributes) match {
case (ErrorType, _) => true
case (WildcardType, _) => true
case (_, ErrorType) => true
@@ -3491,10 +3505,6 @@ A type's typeSymbol should never be inspected directly.
case (tv1 @ TypeVar(_, constr1), _) =>
if (constr1.inst != NoType) constr1.inst <:< tp2
else isRelatable(tv1, tp2) && { constr1.hibounds = tp2 :: constr1.hibounds; true }
- case (AnnotatedType(_,atp1,_), _) =>
- atp1 <:< tp2
- case (_, AnnotatedType(_,atp2,_)) =>
- tp1 <:< atp2
case (_, _) if (tp1.isHigherKinded || tp2.isHigherKinded) =>
(tp1.typeSymbol == AllClass
||
@@ -3546,7 +3556,7 @@ A type's typeSymbol should never be inspected directly.
sym1 == AllRefClass && tp2.isInstanceOf[SingletonType] && (tp1 <:< tp2.widen))
case _ =>
false
- }
+ })
} || {
val tp1n = tp1.normalize
val tp2n = tp2.normalize
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index b1cf36c53c..61f383c240 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -3138,6 +3138,9 @@ trait Typers { self: Analyzer =>
// Console.println("typing "+tree+" at "+tree.pos);//DEBUG
var tree1 = if (tree.tpe ne null) tree else typed1(tree, mode, dropExistential(pt))
// Console.println("typed "+tree1+":"+tree1.tpe+", "+context.undetparams);//DEBUG
+
+ tree1.tpe = addAnnotations(tree1, tree1.tpe)
+
val result = if (tree1.isEmpty) tree1 else adapt(tree1, mode, pt)
// Console.println("adapted "+tree1+":"+tree1.tpe+" to "+pt+", "+context.undetparams);//DEBUG
// if ((mode & TYPEmode) != 0) println("type: "+tree1+" has type "+tree1.tpe)