summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2009-08-16 16:29:36 +0000
committerMartin Odersky <odersky@gmail.com>2009-08-16 16:29:36 +0000
commit110b737f99c4e4850f9a0f861db6b9f831ae056e (patch)
tree35db6883632ffdef4c49f0699cf330f9526ce6c9
parentfe72ad6351aa3e06c894972e959fa768ed60a515 (diff)
downloadscala-110b737f99c4e4850f9a0f861db6b9f831ae056e.tar.gz
scala-110b737f99c4e4850f9a0f861db6b9f831ae056e.tar.bz2
scala-110b737f99c4e4850f9a0f861db6b9f831ae056e.zip
1.
2. Relaxed bounds checking rules for existential types.
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/BracePair.scala10
-rwxr-xr-xsrc/compiler/scala/tools/nsc/ast/parser/Parsers.scala5
-rwxr-xr-xsrc/compiler/scala/tools/nsc/ast/parser/Scanners.scala86
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala30
-rwxr-xr-xtest/files/pos/t1560.scala13
5 files changed, 104 insertions, 40 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/parser/BracePair.scala b/src/compiler/scala/tools/nsc/ast/parser/BracePair.scala
index ea64eee7ba..11d6c997c1 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/BracePair.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/BracePair.scala
@@ -6,8 +6,12 @@ package scala.tools.nsc
package ast.parser
/** A descriptor for a matching pair of braces.
- * @param loff The offset of the opening brace (-1 means missing)
- * @param roff The offset of the closing brace (-1 means missing)
+ * @param loff The offset of the opening brace (-1 means missing)
+ * @param lindent The indentation depth of the line of the opening brace (-1 means missing)
+ * @param roff The offset of the closing brace (-1 means missing)
+ * @param rindent The indentation depth of the line of the closing brace (-1 means missing)
* @param nested The brace pairs nested in this one
*/
-case class BracePair(loff: Int, off: Int, nested: List[BracePair])
+case class BracePair(loff: Int, lindent: Int, roff: Int, rindent: Int, nested: List[BracePair])
+
+
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
index 787e96d1d8..da233feab3 100755
--- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
@@ -75,7 +75,8 @@ self =>
def warning(offset: Int, msg: String) { unit.warning(o2p(offset), msg) }
- def deprecationWarning(offset: Int, msg: String) {
+ def deprecationWarning(offset: Int,
+ msg: String) {
unit.deprecationWarning(o2p(offset), msg)
}
@@ -429,7 +430,7 @@ self =>
global.atPos(r2p(offset, offset, in.lastOffset max offset))(t)
def atPos[T <: Tree](start: Int, point: Int)(t: T): T =
global.atPos(r2p(start, point, in.lastOffset max start))(t)
- def atPos[T <: Tree](start: Int, point: Int, end: Int)(t: T): T = // !!! put an { brace here and observe
+ def atPos[T <: Tree](start: Int, point: Int, end: Int)(t: T): T =
global.atPos(r2p(start, point, end))(t)
def atPos[T <: Tree](pos: Position)(t: T): T =
global.atPos(pos)(t)
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala b/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala
index 814017d6dc..518cca0c9d 100755
--- a/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala
@@ -1042,16 +1042,31 @@ trait Scanners {
var lineCount = 1
var lastOffset = 0
+ var indent = 0
+ val oldBalance = collection.mutable.Map[Int, Int]()
+ def markBalance() = for ((k, v) <- balance) oldBalance(k) = v
+ markBalance()
- def scan(bpbuf: ListBuffer[BracePair]): Int = {
+ def scan(bpbuf: ListBuffer[BracePair]): (Int, Int) = {
if (token != NEWLINE && token != NEWLINES) {
while (lastOffset < offset) {
if (buf(lastOffset) == LF) lineCount += 1
lastOffset += 1
}
- while (lineCount > lineStart.length)
+ while (lineCount > lineStart.length) {
lineStart += offset
+ // reset indentation unless there are new opening brackets or
+ // braces since last ident line and at the same time there
+ // are no new braces.
+ if (balance(RPAREN) >= oldBalance(RPAREN) &&
+ balance(RBRACKET) >= oldBalance(RBRACKET) ||
+ balance(RBRACE) != oldBalance(RBRACE)) {
+ indent = column(offset)
+ markBalance()
+ }
+ }
}
+
token match {
case LPAREN =>
balance(RPAREN) -= 1; nextToken(); scan(bpbuf)
@@ -1065,17 +1080,18 @@ trait Scanners {
balance(RBRACE) -= 1
val lc = lineCount
val loff = offset
+ val lindent = indent
val bpbuf1 = new ListBuffer[BracePair]
nextToken()
- val roff = scan(bpbuf1)
+ val (roff, rindent) = scan(bpbuf1)
if (lc != lineCount)
- bpbuf += BracePair(loff, roff, bpbuf1.toList)
+ bpbuf += BracePair(loff, lindent, roff, rindent, bpbuf1.toList)
scan(bpbuf)
case RBRACE =>
balance(RBRACE) += 1
- val off = offset; nextToken(); off
+ val off = offset; nextToken(); (off, indent)
case EOF =>
- -1
+ (-1, -1)
case _ =>
nextToken(); scan(bpbuf)
}
@@ -1083,15 +1099,24 @@ trait Scanners {
val bpbuf = new ListBuffer[BracePair]
while (token != EOF) {
- val roff = scan(bpbuf)
+ val (roff, rindent) = scan(bpbuf)
if (roff != -1) {
- val current = BracePair(-1, roff, bpbuf.toList)
+ val current = BracePair(-1, -1, roff, rindent, bpbuf.toList)
bpbuf.clear()
bpbuf += current
}
}
+
+ def printBP(bp: BracePair, indent: Int) {
+ println(" "*indent+line(bp.loff)+":"+bp.lindent+" to "+line(bp.roff)+":"+bp.rindent)
+ if (bp.nested.nonEmpty)
+ for (bp1 <- bp.nested) {
+ printBP(bp1, indent + 2)
+ }
+ }
// println("lineStart = "+lineStart)//DEBUG
-// println("bracepairs = "+bpbuf.toList)//DEBUG
+// println("bracepairs = ")
+// for (bp <- bpbuf.toList) printBP(bp, 0)
bpbuf.toList
}
@@ -1104,7 +1129,8 @@ trait Scanners {
else if (mid + 1 < lineStart.length && offset >= lineStart(mid + 1)) findLine(mid + 1, hi)
else mid
}
- findLine(0, lineStart.length - 1)
+ if (offset <= 0) 0
+ else findLine(0, lineStart.length - 1)
}
def column(offset: Int): Int = {
@@ -1139,22 +1165,24 @@ trait Scanners {
def insertRBrace(): List[BracePatch] = {
def insert(bps: List[BracePair]): List[BracePatch] = bps match {
case List() => patches
- case (bp @ BracePair(loff, roff, nested)) :: bps1 =>
- val lcol = leftColumn(loff)
- val rcol = rightColumn(roff, lcol)
- if (lcol <= rcol) insert(bps1)
+ case (bp @ BracePair(loff, lindent, roff, rindent, nested)) :: bps1 =>
+ if (lindent <= rindent) insert(bps1)
else {
-// println("patch inside "+bp+"/"+line(loff)+"/"+lineStart(line(loff))+"/"+lcol+"/"+rcol)//DEBUG
+// println("patch inside "+bp+"/"+line(loff)+"/"+lineStart(line(loff))+"/"+lindent"/"+rindent)//DEBUG
val patches1 = insert(nested)
if (patches1 ne patches) patches1
else {
-// println("patch for "+bp)//DEBUG
var lin = line(loff) + 1
- while (lin < lineStart.length && column(lineStart(lin)) > lcol)
+ while (lin < lineStart.length && column(lineStart(lin)) > lindent)
lin += 1
- if (lin < lineStart.length)
- insertPatch(patches, BracePatch(lineStart(lin), true))
- else patches
+ if (lin < lineStart.length) {
+ val patches1 = insertPatch(patches, BracePatch(lineStart(lin), true))
+ //println("patch for "+bp+"/"+imbalanceMeasure+"/"+new ParensAnalyzer(unit, patches1).imbalanceMeasure)
+ /*if (improves(patches1))*/
+ patches1
+ /*else insert(bps1)*/
+ // (this test did not seem to work very well in practice)
+ } else patches
}
}
}
@@ -1164,10 +1192,8 @@ trait Scanners {
def deleteRBrace(): List[BracePatch] = {
def delete(bps: List[BracePair]): List[BracePatch] = bps match {
case List() => patches
- case BracePair(loff, roff, nested) :: bps1 =>
- val lcol = leftColumn(loff)
- val rcol = rightColumn(roff, lcol)
- if (lcol >= rcol) delete(bps1)
+ case BracePair(loff, lindent, roff, rindent, nested) :: bps1 =>
+ if (lindent >= rindent) delete(bps1)
else {
val patches1 = delete(nested)
if (patches1 ne patches) patches1
@@ -1176,6 +1202,18 @@ trait Scanners {
}
delete(bracePairs)
}
+
+ def imbalanceMeasure: Int = {
+ def measureList(bps: List[BracePair]): Int =
+ (bps map measure).sum
+ def measure(bp: BracePair): Int =
+ (if (bp.lindent != bp.rindent) 1 else 0) + measureList(bp.nested)
+ measureList(bracePairs)
+ }
+
+ def improves(patches1: List[BracePatch]): Boolean =
+ imbalanceMeasure > new ParensAnalyzer(unit, patches1).imbalanceMeasure
+
override def error(offset: Int, msg: String) {}
}
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
index b716f6ac16..326ce6f748 100644
--- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
@@ -843,15 +843,15 @@ abstract class RefChecks extends InfoTransform {
def isCaseApply(sym : Symbol) = sym.isSourceMethod && sym.hasFlag(CASE) && sym.name == nme.apply
- def checkTypeRef(tp: TypeRef, pos: Position) {
- val TypeRef(pre, sym, args) = tp
- checkDeprecated(sym, pos)
- if (!tp.isHigherKinded)
- checkBoundsWithPos(pre, sym.owner, sym.typeParams, args, pos)
+ def checkTypeRef(tp: Type, pos: Position) = tp match {
+ case TypeRef(pre, sym, args) =>
+ checkDeprecated(sym, pos)
+ if (!tp.isHigherKinded)
+ checkBoundsWithPos(pre, sym.owner, sym.typeParams, args, pos)
+ case _ =>
}
def checkAnnotations(tpes: List[(Type, Position)]) {
- for ((tp @ TypeRef(_,_,_), pos) <- tpes)
- checkTypeRef(tp, pos)
+ for ((tp, pos) <- tpes) checkTypeRef(tp, pos)
}
val savedLocalTyper = localTyper
@@ -897,10 +897,18 @@ abstract class RefChecks extends InfoTransform {
validateBaseTypes(currentOwner)
checkAllOverrides(currentOwner)
- case TypeTree() => doTypeTraversal {
- case t: TypeRef => checkTypeRef(t, tree.pos)
- case _ =>
- }
+ case TypeTree() =>
+ val existentialParams = new ListBuffer[Symbol]
+ doTypeTraversal { // check all bounds, except those that are
+ // existential type parameters
+ case ExistentialType(tparams, tpe) =>
+ existentialParams ++= tparams
+ case t: TypeRef =>
+ val exparams = existentialParams.toList
+ val wildcards = exparams map (_ => WildcardType)
+ checkTypeRef(t.subst(exparams, wildcards), tree.pos)
+ case _ =>
+ }
case TypeApply(fn, args) =>
checkBounds(NoPrefix, NoSymbol, fn.tpe.typeParams, args map (_.tpe))
diff --git a/test/files/pos/t1560.scala b/test/files/pos/t1560.scala
new file mode 100755
index 0000000000..49cdaaed6a
--- /dev/null
+++ b/test/files/pos/t1560.scala
@@ -0,0 +1,13 @@
+object Test extends Application {
+
+ trait C[T] {
+ def t: T
+ }
+
+ def b: Option[C[x] forSome { type x }] = null
+
+ def c = b match {
+ case Some(b) => b.t
+ }
+
+}