class Annot(obj: Any) extends Annotation with TypeConstraint
defined class Annot

-----
class A {
  val x = "hello"
  val y: Int @Annot(x) = 10
  override def toString = "an A"
} 
defined class A

-----
val a = new A
a: A = an A

-----
val y = a.y   // should rewrite "this.x" to "a.x" 
y: Int @Annot(a.x) = 10

-----
var a2 = new A
a2: A = an A

-----
val y2 = a2.y   // should drop the annotation
y2: Int = 10

-----
object Stuff {
  val x = "hello"
  val y : Int @Annot(x) = 10
}
defined module Stuff

-----
val y = Stuff.y // should rewrite the annotation
y: Int @Annot(Stuff.x) = 10

-----
class B {
  val y: Int @Annot(Stuff.x) = 10
  override def toString = "a B"
}
defined class B

-----
val b = new B
b: B = a B

-----
val y = b.y  // should keep the annotation
y: Int @Annot(Stuff.x) = 10

-----
def m(x: String): String @Annot(x) = x
m: (x: String)String @Annot(x)

-----
val three = "three"
three: java.lang.String = three

-----
val three2 = m(three:three.type)  // should change x to three
three2: String @Annot(three) = three

-----
var four = "four"
four: java.lang.String = four

-----
val four2 = m(four) // should have an existential bound
four2: java.lang.String @Annot(x) forSome { val x: java.lang.String } = four

-----
val four3 = four2   // should have the same type as four2
four3: java.lang.String @Annot(x) forSome { val x: java.lang.String } = four

-----
val stuff = m("stuff") // should not crash
stuff: String @Annot("stuff") = stuff

-----
class peer extends Annotation // should not crash
defined class peer

-----
class NPE[T <: NPE[T] @peer] // should not crash
defined class NPE

-----
def m = {
  val x = "three"
  val y : String @Annot(x) = x
  y
} // x should be existentially bound
m: java.lang.String @Annot(x) forSome { val x: java.lang.String }

-----
def n(y: String) = {
  def m(x: String) : String @Annot(x) = {
    (if (x == "")
      m("default")
    else
      x)
  }
  m("stuff".stripMargin)
} // x should be existentially bound
n: (y: String)java.lang.String @Annot(x) forSome { val x: String }

-----
class rep extends Annotation
defined class rep

-----
object A { val x = "hello" : String @ rep }
defined module A

-----
val y = a.x // should drop the annotation
y: java.lang.String = hello

-----
val x = 3 : Int @Annot(e+f+g+h) //should have a graceful error message
<console>:6: error: not found: value e
       val x = 3 : Int @Annot(e+f+g+h) //should have a graceful error message
                              ^

-----
class Where(condition: Boolean) extends Annotation
defined class Where

-----
val x : Int @Where(self > 0 && self < 100) = 3
x: Int @Where(self.>(0).&&(self.<(100))) = 3

-----
