⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 infer.scala

📁 JAVA 语言的函数式编程扩展
💻 SCALA
📖 第 1 页 / 共 4 页
字号:
        if (!(lo <:< hi)) {          if (settings.debug.value) log("inconsistent: "+tparam+" "+lo+" "+hi)        } else if (!((lo <:< tparam.info.bounds.lo) && (tparam.info.bounds.hi <:< hi))) {          context.nextEnclosing(_.tree.isInstanceOf[CaseDef]).pushTypeBounds(tparam)          tparam setInfo mkTypeBounds(lo, hi)          if (settings.debug.value) log("new bounds of " + tparam + " = " + tparam.info)        } else {          if (settings.debug.value) log("redundant: "+tparam+" "+tparam.info+"/"+lo+" "+hi)        }      }    }    def checkCheckable(pos: Position, tp: Type, kind: String) {      def patternWarning(tp: Type, prefix: String) = {        context.unit.uncheckedWarning(pos, prefix+tp+" in type"+kind+" is unchecked since it is eliminated by erasure")      }      def check(tp: Type, bound: List[Symbol]) {        def isLocalBinding(sym: Symbol) =          sym.isAbstractType &&           ((bound contains sym) ||           sym.name == nme.WILDCARD.toTypeName || {            val e = context.scope.lookupEntry(sym.name)            (e ne null) && e.sym == sym && e.owner == context.scope          })        tp match {          case SingleType(pre, _) =>             check(pre, bound)          case TypeRef(pre, sym, args) =>             if (sym.isAbstractType)               patternWarning(tp, "abstract type ")            else if (sym.isAliasType)              check(tp.normalize, bound)            else if (sym == AllClass || sym == AllRefClass)               error(pos, "this type cannot be used in a type pattern")            else              for (arg <- args) {                if (sym == ArrayClass) check(arg, bound)                else arg match {                  case TypeRef(_, sym, _) if isLocalBinding(sym) =>                    ;                  case _ =>                    patternWarning(arg, "non variable type-argument ")                }              }            check(pre, bound)          case RefinedType(parents, decls) =>            if (decls.isEmpty) for (p <- parents) check(p, bound)            else patternWarning(tp, "refinement ")          case ExistentialType(quantified, tp1) =>            check(tp1, bound ::: quantified)          case ThisType(_) =>            ;          case NoPrefix =>             ;          case _ =>             patternWarning(tp, "type ")        }      }      check(tp, List())    }    /** Type intersection of simple type <code>tp1</code> with general     *  type <code>tp2</code>. The result eliminates some redundancies.     */    def intersect(tp1: Type, tp2: Type): Type = {      if (tp1 <:< tp2) tp1      else if (tp2 <:< tp1) tp2      else {        val reduced2 = tp2 match {          case rtp @ RefinedType(parents2, decls2) =>            copyRefinedType(rtp, parents2 filter (p2 => !(tp1 <:< p2)), decls2)          case _ =>            tp2        }        intersectionType(List(tp1, reduced2))      }    }    def inferTypedPattern(pos: Position, pattp: Type, pt0: Type): Type = {      val pt = widen(pt0)      checkCheckable(pos, pattp, " pattern")      if (!(pattp <:< pt)) {        val tpparams = freeTypeParamsOfTerms.collect(pattp)        if (settings.debug.value) log("free type params (1) = " + tpparams)        var tvars = tpparams map freshVar        var tp = pattp.instantiateTypeParams(tpparams, tvars)        if (!(tp <:< pt)) {          tvars = tpparams map freshVar          tp = pattp.instantiateTypeParams(tpparams, tvars)          val ptparams = freeTypeParamsOfTerms.collect(pt)          if (settings.debug.value) log("free type params (2) = " + ptparams)          val ptvars = ptparams map freshVar          val pt1 = pt.instantiateTypeParams(ptparams, ptvars)          if (!isPopulated(tp, pt1)) {            error(pos, "pattern type is incompatible with expected type"+foundReqMsg(pattp, pt))            return pattp          }          ptvars foreach instantiateTypeVar        }        tvars foreach instantiateTypeVar      }      intersect(pt, pattp)    }    def inferModulePattern(pat: Tree, pt: Type) =      if (!(pat.tpe <:< pt)) {        val ptparams = freeTypeParamsOfTerms.collect(pt)        if (settings.debug.value) log("free type params (2) = " + ptparams)        val ptvars = ptparams map freshVar        val pt1 = pt.instantiateTypeParams(ptparams, ptvars)        if (pat.tpe <:< pt1)          ptvars foreach instantiateTypeVar        else           error(pat.pos, "pattern type is incompatible with expected type"+foundReqMsg(pat.tpe, pt))      }    object toOrigin extends TypeMap {      def apply(tp: Type): Type = tp match {        case TypeVar(origin, _) => origin        case _ => mapOver(tp)      }    }    abstract class SymCollector extends TypeTraverser {      private var result: List[Symbol] = _      protected def includeCondition(sym: Symbol): Boolean      override def traverse(tp: Type): TypeTraverser = {        tp.normalize match {          case TypeRef(_, sym, _) =>            if (includeCondition(sym) && !result.contains(sym)) result = sym :: result          case _ =>        }        mapOver(tp)        this      }      /** Collect all abstract type symbols referred to by type <code>tp</code>.       *       *  @param tp ...       *  @return   ...       */      def collect(tp: Type): List[Symbol] = {        result = List()        traverse(tp)        result      }    }    object approximateAbstracts extends TypeMap {      def apply(tp: Type): Type = tp.normalize match {        case TypeRef(pre, sym, _) if sym.isAbstractType => WildcardType        case _ => mapOver(tp)      }    }    /** A traverser to collect type parameters referred to in a type     */    object freeTypeParamsOfTerms extends SymCollector {      protected def includeCondition(sym: Symbol): Boolean =        sym.isAbstractType && sym.owner.isTerm    }    object typeRefs extends SymCollector {      protected def includeCondition(sym: Symbol): Boolean = true    }    def checkDead(tree: Tree): Tree = {      if (settings.Xwarndeadcode.value && tree.tpe.typeSymbol == AllClass)        context.warning (tree.pos, "dead code following this construct")      tree    }    /* -- Overload Resolution ---------------------------------------------- */    def checkNotShadowed(pos: Position, pre: Type, best: Symbol, eligible: List[Symbol]) =      if (!phase.erasedTypes)        for (alt <- eligible) {          if (alt.owner != best.owner && alt.owner.isSubClass(best.owner))            error(pos,                  "erroneous reference to overloaded definition,\n"+                  "most specific definition is: "+best+best.locationString+" of type "+pre.memberType(best)+                  ",\nyet alternative definition   "+alt+alt.locationString+" of type "+pre.memberType(alt)+                  "\nis defined in a subclass")        }    /** Assign <code>tree</code> the symbol and type of the alternative which     *  matches prototype <code>pt</code>, if it exists.     *  If several alternatives match `pt', take parameterless one.     *  If no alternative matches `pt', take the parameterless one anyway.     */    def inferExprAlternative(tree: Tree, pt: Type): Unit = tree.tpe match {      case OverloadedType(pre, alts) => tryTwice {        var alts1 = alts filter (alt => isWeaklyCompatible(pre.memberType(alt), pt))        var secondTry = false        if (alts1.isEmpty) {           alts1 = alts          secondTry = true        }        def improves(sym1: Symbol, sym2: Symbol): Boolean =          sym2 == NoSymbol ||           { val tp1 = pre.memberType(sym1)            val tp2 = pre.memberType(sym2)            (tp2 == ErrorType ||             !global.typer.infer.isWeaklyCompatible(tp2, pt) && global.typer.infer.isWeaklyCompatible(tp1, pt) ||             isStrictlyMoreSpecific(tp1, tp2)) }        val best = ((NoSymbol: Symbol) /: alts1) ((best, alt) =>          if (improves(alt, best)) alt else best)        val competing = alts1 dropWhile (alt => best == alt || improves(best, alt))        if (best == NoSymbol) {          if (settings.debug.value) {            tree match {              case Select(qual, _) =>                Console.println("qual: " + qual + ":" + qual.tpe +                                   " with decls " + qual.tpe.decls +                                   " with members " + qual.tpe.members +                                   " with members " + qual.tpe.member(newTermName("$minus")))              case _ =>            }          }          typeErrorTree(tree, tree.symbol.tpe, pt)        } else if (!competing.isEmpty) {          if (secondTry) {            typeErrorTree(tree, tree.symbol.tpe, pt)          } else {            if (!pt.isErroneous)              context.ambiguousError(tree.pos, pre, best, competing.head, "expected type " + pt)            setError(tree)          }        } else {          val applicable = alts1 filter (alt =>             global.typer.infer.isWeaklyCompatible(pre.memberType(alt), pt))          checkNotShadowed(tree.pos, pre, best, applicable)          tree.setSymbol(best).setType(pre.memberType(best))        }      }    }    /** Assign <code>tree</code> the type of an alternative which is applicable     *  to <code>argtpes</code>, and whose result type is compatible with `pt'.     *  If several applicable alternatives exist, take the     *  most specialized one.      *  If no applicable alternative exists, and pt != WildcardType, try again     *  with pt = WildcardType.     *  Otherwise, if there is no best alternative, error.     */    def inferMethodAlternative(tree: Tree, undetparams: List[Symbol], argtpes: List[Type], pt: Type): Unit = tree.tpe match {      case OverloadedType(pre, alts) =>        tryTwice {          if (settings.debug.value) log("infer method alt " + tree.symbol + " with alternatives " + (alts map pre.memberType) + ", argtpes = " + argtpes + ", pt = " + pt)                    val applicable = alts filter (alt => isApplicable(undetparams, followApply(pre.memberType(alt)), argtpes, pt))          def improves(sym1: Symbol, sym2: Symbol) =            sym2 == NoSymbol || sym2.isError ||            isStrictlyMoreSpecific(followApply(pre.memberType(sym1)), followApply(pre.memberType(sym2)))          val best = ((NoSymbol: Symbol) /: applicable) ((best, alt) =>            if (improves(alt, best)) alt else best)          val competing = applicable dropWhile (alt => best == alt || improves(best, alt))          if (best == NoSymbol) {            if (pt == WildcardType) {              errorTree(tree, applyErrorMsg(tree, " cannot be applied to ", argtpes, pt))            } else {              inferMethodAlternative(tree, undetparams, argtpes, WildcardType)            }                      } else if (!competing.isEmpty) {            if (!(argtpes exists (_.isErroneous)) && !pt.isErroneous)              context.ambiguousError(tree.pos, pre, best, competing.head,                                     "argument types " + argtpes.mkString("(", ",", ")") +                                      (if (pt == WildcardType) "" else " and expected result type " + pt))            setError(tree)            ()          } else {            checkNotShadowed(tree.pos, pre, best, applicable)            tree.setSymbol(best).setType(pre.memberType(best))          }        }      case _ =>    }    /** Try inference twice, once without views and once with views,     *  unless views are already disabled.     *     *  @param infer ...     */    def tryTwice(infer: => Unit) {      if (context.implicitsEnabled) {        val reportGeneralErrors = context.reportGeneralErrors        context.reportGeneralErrors = false        context.implicitsEnabled = false        try {          infer        } catch {          case ex: CyclicReference =>             throw ex          case ex: TypeError =>            context.reportGeneralErrors = reportGeneralErrors            context.implicitsEnabled = true            infer        }        context.reportGeneralErrors = reportGeneralErrors        context.implicitsEnabled = true      } else infer    }    /** Assign <code>tree</code> the type of unique polymorphic alternative     *  with <code>nparams</code> as the number of type parameters, if it exists.     *  If several or none such polymorphic alternatives exist, error.     *     *  @param tree ...     *  @param nparams ...     */    def inferPolyAlternatives(tree: Tree, argtypes: List[Type]): Unit = tree.tpe match {      case OverloadedType(pre, alts) =>        val sym0 = tree.symbol filter { alt => alt.typeParams.length == argtypes.length }        if (sym0 == NoSymbol) {          error(            tree.pos,            if (alts exists (alt => alt.typeParams.length > 0))              "wrong number of type parameters for " + treeSymTypeMsg(tree)            else treeSymTypeMsg(tree) + " does not take type parameters")          return        }        if (sym0.hasFlag(OVERLOADED)) {          val sym = sym0 filter { alt => isWithinBounds(pre, alt.owner, alt.typeParams, argtypes) }          if (sym == NoSymbol) {            if (!(argtypes exists (_.isErroneous))) {              error(                tree.pos,                "type arguments " + argtypes.mkString("[", ",", "]") +                 " conform to the bounds of none of the overloaded alternatives of\n "+sym0+                ": "+sym0.info)              return            }          }          if (sym.hasFlag(OVERLOADED)) {            val tparams = new AsSeenFromMap(pre, sym.alternatives.head.owner).mapOver(              sym.alternatives.head.typeParams)            val bounds = tparams map (_.tpe)  //@M TODO: might be affected by change to tpe in Symbol            val tpe =               PolyType(tparams,                        OverloadedType(AntiPolyType(pre, bounds), sym.alternatives))            sym.setInfo(tpe)            tree.setSymbol(sym).setType(tpe)          } else {            tree.setSymbol(sym).setType(pre.memberType(sym))          }        } else {          tree.setSymbol(sym0).setType(pre.memberType(sym0))        }    }  }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -