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 + -
显示快捷键?