namers.scala
来自「JAVA 语言的函数式编程扩展」· SCALA 代码 · 共 1,028 行 · 第 1/3 页
SCALA
1,028 行
} thisMethodType( if (tpt.isEmpty) { val pt = resultPt.substSym(tparamSyms, tparams map (_.symbol)) tpt.tpe = widenIfNotFinal(meth, typer.computeType(rhs, pt), pt) tpt.tpe } else typer.typedType(tpt).tpe) } /** If `sym' is an implicit value, check that its type signature `tp' is contractive. * This means: The type of every implicit parameter is properly contained * in the type that is obtained by removing all implicit parameters and converting * the rest to a function type. * If the check succeeds return `tp' itself, otherwise `ErrorType'. */ private def checkContractive(sym: Symbol, tp: Type): Type = { /* The type signature without implicit parameters converted to function type */ def provided(tp: Type): Type = tp match { case PolyType(_, restpe) => provided(restpe) case mt: ImplicitMethodType => mt.resultType case MethodType(formals, restpe) => functionType(formals, provided(restpe)) case _ => tp } /* The types of all implicit parameters */ def required(tp: Type): List[Type] = tp match { case PolyType(_, restpe) => required(restpe) case mt: ImplicitMethodType => mt.paramTypes case MethodType(formals, restpe) => required(restpe) case _ => List() } var result = tp; if (sym hasFlag IMPLICIT) { val p = provided(tp); //Console.println("check contractive: "+sym+" "+p+"/"+required(tp)) for (r <- required(tp)) { if (!isContainedIn(r, p) || (r =:= p)) { context.error(sym.pos, "implicit " + sym + " is not contractive," + "\n because the implicit parameter type " + r + "\n is not strictly contained in the signature " + p); result = ErrorType; } } } result } //@M! an abstract type definition (abstract type member/type parameter) may take type parameters, which are in scope in its bounds private def typeDefSig(tpsym: Symbol, tparams: List[TypeDef], rhs: Tree) = { val tparamSyms = typer.reenterTypeParams(tparams) //@M make tparams available in scope (just for this abstypedef) val tp = typer.typedType(rhs).tpe match { case TypeBounds(lt, rt) if (lt.isError || rt.isError) => TypeBounds(AllClass.tpe, AnyClass.tpe) case tp => tp } def verifyOverriding(other: Symbol): Boolean = { if(other.unsafeTypeParams.length != tparamSyms.length) { context.error(tpsym.pos, "The kind of "+tpsym.keyString+" "+tpsym.varianceString + tpsym.nameString+ " does not conform to the expected kind of " + other.defString + other.locationString + ".") false } else true } // @M: make sure overriding in refinements respects rudimentary kinding // have to do this early, as otherwise we might get crashes: (see neg/bug1275.scala) // suppose some parameterized type member is overridden by a type member w/o params, // then appliedType will be called on a type that does not expect type args --> crash if (tpsym.owner.isRefinementClass && // only needed in refinements !tpsym.allOverriddenSymbols.forall{verifyOverriding(_)}) ErrorType else polyType(tparamSyms, tp) } /** Given a case class * * case class C[Ts] (ps: Us) * * Add the following methods to toScope: * * 1. if case class is not abstract, add * * <synthetic> <case> def apply[Ts](ps: Us): C[Ts] = new C[Ts](ps) * * 2. add a method * * <synthetic> <case> def unapply[Ts](x: C[Ts]) = <ret-val> * * where <ret-val> is the caseClassUnapplyReturnValue of class C (see UnApplies.scala) */ def addApplyUnapply(cdef: ClassDef, namer: Namer) { if (!(cdef.symbol hasFlag ABSTRACT)) namer.enterSyntheticSym(caseModuleApplyMeth(cdef)) namer.enterSyntheticSym(caseModuleUnapplyMeth(cdef)) } def typeSig(tree: Tree): Type = { val sym: Symbol = tree.symbol tree match { case defn: MemberDef => val ainfos = for { annot <- defn.mods.annotations val ainfo = typer.typedAnnotation(annot) if !ainfo.atp.isError && annot != null } yield ainfo if (!ainfos.isEmpty) { val annotated = if (sym.isModule) sym.moduleClass else sym annotated.attributes = ainfos } case _ => } implicit val scopeKind = TypeSigScopeKind val result = try { tree match { case ClassDef(_, _, tparams, impl) => newNamer(context.makeNewScope(tree, sym)).classSig(tparams, impl) case ModuleDef(_, _, impl) => val clazz = sym.moduleClass clazz.setInfo(newNamer(context.makeNewScope(tree, clazz)).templateSig(impl)) //clazz.typeOfThis = singleType(sym.owner.thisType, sym); clazz.tpe case DefDef(_, _, tparams, vparamss, tpt, rhs) => //val result = newNamer(context.makeNewScope(tree, sym)).methodSig(tparams, vparamss, tpt, rhs) //checkContractive(sym, result) case vdef @ ValDef(mods, _, tpt, rhs) => val typer1 = typer.constrTyperIf(sym.hasFlag(PARAM | PRESUPER) && sym.owner.isConstructor) if (tpt.isEmpty) { if (rhs.isEmpty) { context.error(tpt.pos, "missing parameter type"); ErrorType } else { tpt.tpe = widenIfNotFinal( sym, newTyper(typer1.context.make(vdef, sym)).computeType(rhs, WildcardType), WildcardType) tpt.tpe } } else typer1.typedType(tpt).tpe case TypeDef(_, _, tparams, rhs) => newNamer(context.makeNewScope(tree, sym)).typeDefSig(sym, tparams, rhs) //@M! case Import(expr, selectors) => val expr1 = typer.typedQualifier(expr) val base = expr1.tpe typer.checkStable(expr1) if (expr1.symbol.isRootPackage) context.error(tree.pos, "_root_ cannot be imported") def checkNotRedundant(pos: Position, from: Name, to: Name): Boolean = { if (!tree.symbol.hasFlag(SYNTHETIC) && !((expr1.symbol ne null) && expr1.symbol.isInterpreterWrapper) && base.member(from) != NoSymbol) { val e = context.scope.lookupEntry(to) def warnRedundant(sym: Symbol) = context.unit.warning(pos, "imported `"+to+ "' is permanently hidden by definition of "+sym+ sym.locationString) if ((e ne null) && e.owner == context.scope) { warnRedundant(e.sym); return false } else if (context eq context.enclClass) { val defSym = context.prefix.member(to) filter ( sym => sym.exists && context.isAccessible(sym, context.prefix, false)) if (defSym != NoSymbol) { warnRedundant(defSym); return false } } } true } def checkSelectors(selectors: List[(Name, Name)]): Unit = selectors match { case (from, to) :: rest => if (from != nme.WILDCARD && base != ErrorType) { if (base.member(from) == NoSymbol && base.member(from.toTypeName) == NoSymbol) context.error(tree.pos, from.decode + " is not a member of " + expr); if (checkNotRedundant(tree.pos, from, to)) checkNotRedundant(tree.pos, from.toTypeName, to.toTypeName) } if (from != nme.WILDCARD && (rest.exists (sel => sel._1 == from))) context.error(tree.pos, from.decode + " is renamed twice"); if ((to ne null) && to != nme.WILDCARD && (rest exists (sel => sel._2 == to))) context.error(tree.pos, to.decode + " appears twice as a target of a renaming"); checkSelectors(rest) case Nil => } checkSelectors(selectors) ImportType(expr1) } } catch { case ex: TypeError => //Console.println("caught " + ex + " in typeSig")//DEBUG typer.reportTypeError(tree.pos, ex) ErrorType } deSkolemize(result) } /** Check that symbol's definition is well-formed. This means: * - no conflicting modifiers * - `abstract' modifier only for classes * - `override' modifier never for classes * - `def' modifier never for parameters of case classes * - declarations only in mixins or abstract classes (when not @native) */ def validate(sym: Symbol) { def checkNoConflict(flag1: Int, flag2: Int) { if (sym.hasFlag(flag1) && sym.hasFlag(flag2)) context.error(sym.pos, if (flag1 == DEFERRED) "abstract member may not have " + Flags.flagsToString(flag2) + " modifier"; else "illegal combination of modifiers: " + Flags.flagsToString(flag1) + " and " + Flags.flagsToString(flag2) + " for: " + sym + Flags.flagsToString(sym.rawflags)); } if (sym.hasFlag(IMPLICIT) && !sym.isTerm) context.error(sym.pos, "`implicit' modifier can be used only for values, variables and methods") if (sym.hasFlag(IMPLICIT) && sym.owner.isPackageClass && !inIDE) context.error(sym.pos, "`implicit' modifier cannot be used for top-level objects") if (sym.hasFlag(ABSTRACT) && !sym.isClass) context.error(sym.pos, "`abstract' modifier can be used only for classes; " + "\nit should be omitted for abstract members") if (sym.hasFlag(OVERRIDE | ABSOVERRIDE) && sym.isClass) context.error(sym.pos, "`override' modifier not allowed for classes") if (sym.hasFlag(OVERRIDE | ABSOVERRIDE) && sym.isConstructor) context.error(sym.pos, "`override' modifier not allowed for constructors") if (sym.hasFlag(ABSOVERRIDE) && !sym.owner.isTrait) context.error(sym.pos, "`abstract override' modifier only allowed for members of traits") if (sym.info.typeSymbol == FunctionClass(0) && sym.isValueParameter && sym.owner.isClass && sym.owner.hasFlag(CASE)) context.error(sym.pos, "pass-by-name arguments not allowed for case class parameters"); if (sym hasFlag DEFERRED) { // virtual classes count, too if (sym.hasAttribute(definitions.NativeAttr)) sym.resetFlag(DEFERRED) else if (!sym.isValueParameter && !sym.isTypeParameterOrSkolem && !context.tree.isInstanceOf[ExistentialTypeTree] && (!sym.owner.isClass || sym.owner.isModuleClass || sym.owner.isAnonymousClass)) { context.error(sym.pos, "only classes can have declared but undefined members" + varNotice(sym)) sym.resetFlag(DEFERRED) } } checkNoConflict(DEFERRED, PRIVATE) checkNoConflict(FINAL, SEALED) checkNoConflict(PRIVATE, PROTECTED) checkNoConflict(PRIVATE, OVERRIDE) checkNoConflict(DEFERRED, FINAL) checkNoConflict(DEFERRED, CASE) // case classes cannot be virtual } } /* Is type `tp1' properly contained in type `tp2'? */ def isContainedIn(tp1: Type, tp2: Type) = { //Console.println("is " + tp1 + " contained in " + tp2 + "?");//DEBUG new ContainsTraverser(tp1).traverse(tp2).result } /* Type `elemtp' is contained in type `tp' is one of the following holds: * - elemtp is the same as some proper part of tp * - tp is a function type and elemtp is not * - tp and elemtp are function types, and arity of tp is greater than arity of elemtp * - tp and elemtp are both parameterized types with same type constructor and prefix, * and each type argument of elemtp is contained in the corresponding type argument of tp. */ private class ContainsTraverser(elemtp: Type) extends TypeTraverser { var nested = false var result = false def traverse(tp: Type): ContainsTraverser = { if (!result) { if (elemtp =:= tp) result = nested else if (isFunctionType(tp) && (!isFunctionType(elemtp) || tp.normalize.typeArgs.length > elemtp.normalize.typeArgs.length)) result = true else (tp, elemtp) match { case (TypeRef(pre, sym, args), TypeRef(elempre, elemsym, elemargs)) => if ((sym == elemsym) && (pre =:= elempre) && (args.length == elemargs.length)) result = List.forall2(elemargs, args) (isContainedIn) case _ => } } if (!result) { tp match { case SingleType(_, _) => nested = true case TypeRef(_, _, _) => nested = true case _ => } mapOver(tp) } this } } abstract class TypeCompleter extends LazyType { val tree: Tree } def mkTypeCompleter(t: Tree)(c: Symbol => Unit) = new TypeCompleter { val tree = t override def complete(sym: Symbol) = c(sym) } /** A class representing a lazy type with known type parameters. */ class PolyTypeCompleter(tparams: List[Tree], restp: TypeCompleter, owner: Tree, ownerSym: Symbol, ctx: Context) extends TypeCompleter { override val typeParams: List[Symbol]= tparams map (_.symbol) //@M override val tree = restp.tree override def complete(sym: Symbol) { if(ownerSym.isAbstractType) //@M an abstract type's type parameters are entered -- TODO: change to isTypeMember ? newNamer(ctx.makeNewScope(owner, ownerSym)(PolyTypeCompleterScopeKind)).enterSyms(tparams) //@M restp.complete(sym) } } /** The symbol that which this accessor represents (possibly in part). * This is used for error messages, where we want to speak in terms * of the actual declaration or definition, not in terms of the generated setters * and getters */ def underlying(member: Symbol): Symbol = if (member hasFlag ACCESSOR) { if (member.isDeferred) { val getter = if (member.isSetter) member.getter(member.owner) else member if (inIDE && getter == NoSymbol) return NoSymbol; val result = getter.owner.newValue(getter.pos, getter.name) .setInfo(getter.tpe.resultType) .setFlag(DEFERRED) if (getter.setter(member.owner) != NoSymbol) result.setFlag(MUTABLE) result } else member.accessed } else member /** An explanatory note to be added to error messages * when there's a problem with abstract var defs */ def varNotice(sym: Symbol): String = if (underlying(sym).isVariable) "\n(Note that variables need to be initialized to be defined)" else ""}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?