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