From a468a864dcdb89091985c194737968a979e874fb Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Fri, 21 Nov 2014 18:09:10 +0100 Subject: 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. --- src/dotty/tools/dotc/core/TypeOps.scala | 36 +++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) (limited to 'src/dotty/tools/dotc/core/TypeOps.scala') 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: * -- cgit v1.2.3