typers.scala

来自「JAVA 语言的函数式编程扩展」· SCALA 代码 · 共 1,553 行 · 第 1/5 页

SCALA
1,553
字号
        }        //Console.println("parents("+clazz") = "+supertpt :: mixins);//DEBUG        List.mapConserve(supertpt :: mixins)(tpt => checkNoEscaping.privates(clazz, tpt))      } catch {        case ex: TypeError =>          templ.tpe = null          reportTypeError(templ.pos, ex)          List(TypeTree(AnyRefClass.tpe))      }    /** <p>Check that</p>     *  <ul>     *    <li>all parents are class types,</li>     *    <li>first parent class is not a mixin; following classes are mixins,</li>     *    <li>final classes are not inherited,</li>     *    <li>     *      sealed classes are only inherited by classes which are     *      nested within definition of base class, or that occur within same     *      statement sequence,     *    </li>     *    <li>self-type of current class is a subtype of self-type of each parent class.</li>     *    <li>no two parents define same symbol.</li>     *  </ul>     */    def validateParentClasses(parents: List[Tree], selfType: Type) {      def validateParentClass(parent: Tree, superclazz: Symbol) {        if (!parent.tpe.isError) {          val psym = parent.tpe.typeSymbol.initialize          checkClassType(parent, false)          if (psym != superclazz) {            if (psym.isTrait) {              val ps = psym.info.parents              if (!ps.isEmpty && !superclazz.isSubClass(ps.head.typeSymbol))                error(parent.pos, "illegal inheritance; super"+superclazz+                      "\n is not a subclass of the super"+ps.head.typeSymbol+                      "\n of the mixin " + psym);            } else {              error(parent.pos, psym+" needs to be a trait be mixed in")            }          }           if (psym hasFlag FINAL) {            error(parent.pos, "illegal inheritance from final "+psym)          }           if (psym.isSealed && !phase.erasedTypes) {            if (context.unit.source.file != psym.sourceFile)              error(parent.pos, "illegal inheritance from sealed "+psym)            else              psym addChild context.owner          }          if (!(selfType <:< parent.tpe.typeOfThis) && !phase.erasedTypes) { //@M .typeOfThis seems necessary            //Console.println(context.owner);//DEBUG            //Console.println(context.owner.unsafeTypeParams);//DEBUG            //Console.println(List.fromArray(context.owner.info.closure));//DEBUG            // disable in IDE, don't know how else to avoid it on refresh            if (!inIDE) error(parent.pos, "illegal inheritance;\n self-type "+                  selfType+" does not conform to "+parent +                  "'s selftype "+parent.tpe.typeOfThis)            if (settings.explaintypes.value) explainTypes(selfType, parent.tpe.typeOfThis)          }          if (parents exists (p => p != parent && p.tpe.typeSymbol == psym && !psym.isError))            error(parent.pos, psym+" is inherited twice")        }      }      if (!parents.isEmpty && !parents.head.tpe.isError)        for (p <- parents) validateParentClass(p, parents.head.tpe.typeSymbol)    }    def checkFinitary(classinfo: ClassInfoType) {      val clazz = classinfo.typeSymbol      for (tparam <- clazz.typeParams) {        if (classinfo.expansiveRefs(tparam) contains tparam) {          error(tparam.pos, "class graph is not finitary because type parameter "+tparam.name+" is expansively recursive")          val newinfo = ClassInfoType(            classinfo.parents map (_.instantiateTypeParams(List(tparam), List(AnyRefClass.tpe))),             classinfo.decls,             clazz)          clazz.setInfo {            clazz.info match {              case PolyType(tparams, _) => PolyType(tparams, newinfo)              case _ => newinfo            }          }        }      }    }    /**     *  @param cdef ...     *  @return     ...     */    def typedClassDef(cdef: ClassDef): Tree = {//      attributes(cdef)      val typedMods = typedModifiers(cdef.mods)      val clazz = cdef.symbol;       if (inIDE && clazz == NoSymbol) {        assert(true)        throw new TypeError("type signature typing failed")      }      assert(clazz != NoSymbol)      reenterTypeParams(cdef.tparams)      val tparams1 = List.mapConserve(cdef.tparams)(typedTypeDef)      val impl1 = newTyper(context.make(cdef.impl, clazz, scopeFor(cdef.impl, TypedDefScopeKind)))        .typedTemplate(cdef.impl, parentTypes(cdef.impl))      val impl2 = addSyntheticMethods(impl1, clazz, context)      if ((clazz != ClassfileAnnotationClass) &&	  (clazz isNonBottomSubClass ClassfileAnnotationClass))	unit.warning (cdef.pos,          "implementation restriction: subclassing Classfile does not\n"+          "make your annotation visible at runtime.  If that is what\n"+ 	  "you want, you must write the annotation class in Java.")      copy.ClassDef(cdef, typedMods, cdef.name, tparams1, impl2)        .setType(NoType)    }     /**     *  @param mdef ...     *  @return     ...     */    def typedModuleDef(mdef: ModuleDef): Tree = {      //Console.println("sourcefile of " + mdef.symbol + "=" + mdef.symbol.sourceFile)//      attributes(mdef)      val typedMods = typedModifiers(mdef.mods)      val clazz = mdef.symbol.moduleClass      if (inIDE && clazz == NoSymbol) throw new TypeError("bad signature")      assert(clazz != NoSymbol)      val impl1 = newTyper(context.make(mdef.impl, clazz, scopeFor(mdef.impl, TypedDefScopeKind)))        .typedTemplate(mdef.impl, parentTypes(mdef.impl))      val impl2 = addSyntheticMethods(impl1, clazz, context)      copy.ModuleDef(mdef, typedMods, mdef.name, impl2) setType NoType    }    /**     *  @param stat ...     *  @return     ...     */    def addGetterSetter(stat: Tree): List[Tree] = stat match {      case ValDef(mods, name, tpt, rhs)         if (mods.flags & (PRIVATE | LOCAL)) != (PRIVATE | LOCAL)          && !stat.symbol.isModuleVar          && !stat.symbol.hasFlag(LAZY) =>        val vdef = copy.ValDef(stat, mods | PRIVATE | LOCAL, nme.getterToLocal(name), tpt, rhs)        val value = vdef.symbol        val getter = if ((mods hasFlag DEFERRED)) value else value.getter(value.owner)        // XXX:        if (inIDE && getter == NoSymbol)           return Nil        assert(getter != NoSymbol, stat)        if (getter hasFlag OVERLOADED)          error(getter.pos, getter+" is defined twice")        val getterDef: DefDef = {          getter.attributes = value.initialize.attributes          val result = DefDef(getter, vparamss =>              if (mods hasFlag DEFERRED) EmptyTree               else typed(                atPos(vdef.pos) { gen.mkCheckInit(Select(This(value.owner), value)) },                 EXPRmode, value.tpe))          result.tpt.asInstanceOf[TypeTree] setOriginal tpt /* setPos tpt.pos */          checkNoEscaping.privates(getter, result.tpt)          copy.DefDef(result, result.mods withAnnotations mods.annotations, result.name,                      result.tparams, result.vparamss, result.tpt, result.rhs)          //todo: withAnnotations is probably unnecessary        }        def setterDef: DefDef = {          val setr = getter.setter(value.owner)          setr.attributes = value.attributes          val result = atPos(vdef.pos)(            DefDef(setr, vparamss =>              if ((mods hasFlag DEFERRED) || (setr hasFlag OVERLOADED))                 EmptyTree              else                 typed(Assign(Select(This(value.owner), value),                             Ident(vparamss.head.head)))))          copy.DefDef(result, result.mods withAnnotations mods.annotations, result.name,                      result.tparams, result.vparamss, result.tpt, result.rhs)        }        val gs = if (mods hasFlag MUTABLE) List(getterDef, setterDef)                 else List(getterDef)        if (mods hasFlag DEFERRED) gs else vdef :: gs      case DocDef(comment, defn) =>        addGetterSetter(defn) map (stat => DocDef(comment, stat))      case Annotated(annot, defn) =>        addGetterSetter(defn) map (stat => Annotated(annot, stat))      case _ =>        List(stat)    }    protected def enterSyms(txt: Context, trees: List[Tree]) = {      var txt0 = txt      for (tree <- trees) txt0 = enterSym(txt0, tree)    }    protected def enterSym(txt: Context, tree: Tree): Context =      if (txt eq context) namer.enterSym(tree)      else newNamer(txt).enterSym(tree)    /**     *  @param templ    ...     *  @param parents1 ...     *  @return         ...     */    def typedTemplate(templ: Template, parents1: List[Tree]): Template = {      val clazz = context.owner      if (templ.symbol == NoSymbol)        templ setSymbol newLocalDummy(clazz, templ.pos)      val self1 = templ.self match {        case vd @ ValDef(mods, name, tpt, EmptyTree) =>          val tpt1 = checkNoEscaping.privates(clazz.thisSym, typedType(tpt))          copy.ValDef(vd, mods, name, tpt1, EmptyTree) setType NoType      }      if (self1.name != nme.WILDCARD) context.scope enter self1.symbol      val selfType =        if (clazz.isAnonymousClass && !phase.erasedTypes)           intersectionType(clazz.info.parents, clazz.owner)        else clazz.typeOfThis      // the following is necessary for templates generated later      assert(clazz.info.decls != EmptyScope)      enterSyms(context.outer.make(templ, clazz, clazz.info.decls), templ.body)      validateParentClasses(parents1, selfType)      if (!phase.erasedTypes && !clazz.info.resultType.isError) // @S: prevent crash for duplicated type members        checkFinitary(clazz.info.resultType.asInstanceOf[ClassInfoType])      val body =         if (phase.id <= currentRun.typerPhase.id && !reporter.hasErrors)           templ.body flatMap addGetterSetter        else templ.body       val body1 = typedStats(body, templ.symbol)      copy.Template(templ, parents1, self1, body1) setType clazz.tpe    }    /** Type check the annotations within a set of modifiers.  */    def typedModifiers(mods: Modifiers): Modifiers = {      val Modifiers(flags, privateWithin, annotations) = mods      val typedAnnots = annotations.map(typed(_).asInstanceOf[Annotation])      Modifiers(flags, privateWithin, typedAnnots)    }    /**     *  @param vdef ...     *  @return     ...     */    def typedValDef(vdef: ValDef): ValDef = {//      attributes(vdef)      val sym = vdef.symbol      val typer1 = constrTyperIf(sym.hasFlag(PARAM) && sym.owner.isConstructor)      val typedMods = typedModifiers(vdef.mods)      var tpt1 = checkNoEscaping.privates(sym, typer1.typedType({        if (inIDE) vdef.tpt.duplicate // avoids wrong context sticking        else vdef.tpt      }))      checkNonCyclic(vdef, tpt1)      val rhs1 =        if (vdef.rhs.isEmpty) {          if (sym.isVariable && sym.owner.isTerm && phase.id <= currentRun.typerPhase.id)            error(vdef.pos, "local variables must be initialized")          vdef.rhs        } else {          //assert(vdef.rhs.tpe == null)          val rhs = if (inIDE && vdef.rhs.tpe != null) vdef.rhs.duplicate else vdef.rhs          newTyper(typer1.context.make(vdef, sym)).transformedOrTyped(rhs, tpt1.tpe)        }      copy.ValDef(vdef, typedMods, vdef.name, tpt1, checkDead(rhs1)) setType NoType    }    /** Enter all aliases of local parameter accessors.     *     *  @param clazz    ...     *  @param vparamss ...     *  @param rhs      ...     */    def computeParamAliases(clazz: Symbol, vparamss: List[List[ValDef]], rhs: Tree) {      if (settings.debug.value) log("computing param aliases for "+clazz+":"+clazz.primaryConstructor.tpe+":"+rhs);//debug      def decompose(call: Tree): (Tree, List[Tree]) = call match {        case Apply(fn, args) =>          val (superConstr, args1) = decompose(fn)          val formals = (if (fn.tpe == null && inIDE) ErrorType else fn.tpe).paramTypes          val args2 = if (formals.isEmpty || formals.last.typeSymbol != RepeatedParamClass) args                      else args.take(formals.length - 1) ::: List(EmptyTree)          if (args2.length != formals.length) {            if (!inIDE)                        assert(false, "mismatch " + clazz + " " + formals + " " + args2);//debug            else error(call.pos, "XXX: mismatch " + clazz + " " + formals + " " + args2)          }           (superConstr, args1 ::: args2)        case Block(stats, expr) if !stats.isEmpty =>          decompose(stats.last)        case _ =>          (call, List())      }      val (superConstr, superArgs) = decompose(rhs)      assert(superConstr.symbol ne null)//debug      if (superConstr.symbol.isPrimaryConstructor) {        val superClazz = superConstr.symbol.owner        if (!superClazz.hasFlag(JAVA)) {          val superParamAccessors = superClazz.constrParamAccessors          if (superParamAccessors.length == superArgs.length) {            List.map2(superParamAccessors, superArgs) { (superAcc, superArg) =>              superArg match {                case Ident(name) =>                  if (vparamss.exists(_.exists(_.symbol == superArg.symbol))) {                    var alias = superAcc.initialize.alias                    if (alias == NoSymbol)                      alias = superAcc.getter(superAcc.owner)                    if (alias != NoSymbol &&                        superClazz.info.nonPrivateMember(alias.name) != alias)

⌨️ 快捷键说明

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