aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/core/TypeOps.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2014-11-21 18:09:10 +0100
committerMartin Odersky <odersky@gmail.com>2014-11-24 14:57:49 +0100
commita468a864dcdb89091985c194737968a979e874fb (patch)
tree4fc942a70e2a3a2c9a9f84acf1f57a696e587233 /src/dotty/tools/dotc/core/TypeOps.scala
parentf6ebe1ec66220db511d0080f3807c3a0512fc01c (diff)
downloaddotty-a468a864dcdb89091985c194737968a979e874fb.tar.gz
dotty-a468a864dcdb89091985c194737968a979e874fb.tar.bz2
dotty-a468a864dcdb89091985c194737968a979e874fb.zip
checkBounds refactoring
Move core logic to TypeOps, only leave error reporting in Checking. That way, we have the option of re-using the code as a simple test elsewhere.
Diffstat (limited to 'src/dotty/tools/dotc/core/TypeOps.scala')
-rw-r--r--src/dotty/tools/dotc/core/TypeOps.scala36
1 files changed, 36 insertions, 0 deletions
diff --git a/src/dotty/tools/dotc/core/TypeOps.scala b/src/dotty/tools/dotc/core/TypeOps.scala
index 687ca9ef0..7b76feb4d 100644
--- a/src/dotty/tools/dotc/core/TypeOps.scala
+++ b/src/dotty/tools/dotc/core/TypeOps.scala
@@ -7,6 +7,8 @@ import config.Printers._
import Decorators._
import StdNames._
import util.SimpleMap
+import collection.mutable
+import ast.tpd._
trait TypeOps { this: Context =>
@@ -307,6 +309,40 @@ trait TypeOps { this: Context =>
parentRefs
}
+ /** An argument bounds violation is a triple consisting of
+ * - the argument tree
+ * - a string "upper" or "lower" indicating which bound is violated
+ * - the violated bound
+ */
+ type BoundsViolation = (Tree, String, Type)
+
+ /** The list of violations where arguments are not within bounds.
+ * @param args The arguments
+ * @param boundss The list of type bounds
+ * @param instantiate A function that maps a bound type and the list of argument types to a resulting type.
+ * Needed to handle bounds that refer to other bounds.
+ */
+ def boundsViolations(args: List[Tree], boundss: List[TypeBounds], instantiate: (Type, List[Type]) => Type)(implicit ctx: Context): List[BoundsViolation] = {
+ val argTypes = args.tpes
+ val violations = new mutable.ListBuffer[BoundsViolation]
+ for ((arg, bounds) <- args zip boundss) {
+ def checkOverlapsBounds(lo: Type, hi: Type): Unit = {
+ //println(i"instantiating ${bounds.hi} with $argTypes")
+ //println(i" = ${instantiate(bounds.hi, argTypes)}")
+ val hiBound = instantiate(bounds.hi, argTypes.mapConserve(_.bounds.hi))
+ // Note that argTypes can contain a TypeBounds type for arguments that are
+ // not fully determined. In that case we need to check against the hi bound of the argument.
+ if (!(lo <:< hiBound)) violations += ((arg, "upper", hiBound))
+ if (!(bounds.lo <:< hi)) violations += ((arg, "lower", bounds.lo))
+ }
+ arg.tpe match {
+ case TypeBounds(lo, hi) => checkOverlapsBounds(lo, hi)
+ case tp => checkOverlapsBounds(tp, tp)
+ }
+ }
+ violations.toList
+ }
+
/** Is `feature` enabled in class `owner`?
* This is the case if one of the following two alternatives holds:
*