summaryrefslogblamecommitdiff
path: root/src/compiler/scala/tools/nsc/typechecker/Namers.scala
blob: 25b30c9c35c9931b59741d359168cc1441405ccc (plain) (tree)
1
2
3
4
5
6
7
8

                                


                          
 
                                   
 








                                                                                
                                

                      
 

                                                                            





                                                                              
                                    
                

                                                             


                                                        
                                                            
                                                  

                                                                              
               

                   

   
                                     
 
                                 
 
                                                                              
                                      
                                                                                         

         
 
                                                                              






                                                                                            

                                                                      
                                                                                   




                                                                                               





                                                                                   
                                             

                                  


                                                                             
                     
     
 
                                                                      
                        
                                                         
                                                                              
 
                                             
                                     
                                                                                    
                                                       
                                                          


                                          



                                            


         
                                                                             

                                                                               
                                         
                                                        
         
              



                                                                                         
                         


       



                                                                                    
                                                                                       
                                                
                                                                                       
                                      
              
                                                                                               
       
                                   

                                                


                                                                                                    
                               



                                                                                             
       
       

     
                                                                                        


                                                                  
                                     
              
                                                                                                         
                                  


                                                        
                       
       
                                   
                                                                

                                                          
       

     
                                                                                             
                                                
                                                                                                       
                                     
              
                                                                           
       

                                                               
       

     

                                                              
 
                                                               
                                                 







                                                                       
                                                      
                                                          




                                                                                     
                                                                  
 
                                                                                      
 
                                       
 
                                                         
                                                                                                                                      
                                                            

                                                                                
                                                                
                                                     
         
                                  
       
                                     
 
 
                                    
                                 




                                                                                   
                                   
                                                        
                                                                                         
                                                   

                                                                                            
                                                                
             


                                                                      
                                          
                                                                                         


                                                                                      

                                             
                                                                    

                                                                                                 
                                                          

                                                               
                                                   
                                   
                                                
                                                                                

                                                                 
                                                     


                                    



                                                                                 
                            
                    

                                                                        

                    
                                                                 
                                                                      


                                                               
                                                      
                                                                       


                                                     
                                              
                                                                             

                                                     

                                                      
                                                                          

                                                     
                               

                                 
                                    
                                                                                               
                                                         
                   

         
          
     


                                                                              


                                                             

                              
                                                        
                     


       





                                                                        


                                                                   
                                                    
                                                        
                     





                                                                   
                                                                   
                                                        
                     




                                                                 
                                              




                                                                    


                                              
                                                                          
                        



                                                                 



                                                              



                                                                                             

                                                                
                                                          















                                                                                   
                               











                                                                  
                           











                                                                                        




                                                                                  
                   

                                                                                 
                                                                         
                 
                                        

                                                               
                                                                                                   
                                         
       



                                                          

     








                                                                                         

                                                    




                                                                                   


                                                            
















                                                                                
                                                                                         
                                                                               
 


                                             
                                       




                                                                                     
                                         

















                                                                                                       
                      










                                                                                          




                                               

                                           


                                                    
                                                                                         
                                                                                       














                                                                                            

                                                                                             





                                                                                                  





                                                                                                    
               
                                       



                               

                                                                       


                         
     





                                                                  
                                                          










                                                                                         
                                                                                                        
                                                            
                                                                                          

                                                                                     
                                                        
                                                             
                                                                             
                                                                   
                                                                                  
                                                         
                                                                                                 
                                                


                                                                                               
                                                                    

                                                                                            
                                                                                    
                                 

         




                                         
     
   
 


                                                                            
                                                   


                                                                           
                                                    





                                                                                               
                      
                      


                                                 
                         









                                                                                          







                                                



          
                                                               






















                                                                                    

 
/* NSC -- new Scala compiler
 * Copyright 2005-2006 LAMP/EPFL
 * @author  Martin Odersky
 */
// $Id$

package scala.tools.nsc.typechecker

import scala.tools.nsc.util.Position
import symtab.Flags
import symtab.Flags._

/** This trait declares methods to create symbols and to enter them into scopes.
 *
 *  @author Martin Odersky
 *  @version 1.0
 */
trait Namers requires Analyzer {
  import global._
  import definitions._

  /** Convert to corresponding type parameters all skolems which satisfy one
   *  of the following two conditions:
   *  1. The skolem is a parameter of a class or alias type
   *  2. The skolem is a method parameter which appears in parameter `tparams'
   */
  class DeSkolemizeMap(tparams: List[Symbol]) extends TypeMap {
    def apply(tp: Type): Type = tp match {
      case TypeRef(pre, sym, args) =>
        val tparam = sym.deSkolemize
        mapOver(
          if (tparam == sym || !(tparams contains tparam)) tp
          else rawTypeRef(NoPrefix, tparam, args))
      case SingleType(pre, sym) if (sym.isThisSkolem) =>
        ThisType(sym.deSkolemize)
      case PolyType(tparams1, restpe) =>
        new DeSkolemizeMap(tparams1 ::: tparams).mapOver(tp)
      case ClassInfoType(parents, decls, clazz) =>
        val parents1 = List.mapConserve(parents)(this)
        if (parents1 eq parents) tp else ClassInfoType(parents1, decls, clazz)
      case _ =>
        mapOver(tp)
    }
  }

  class Namer(val context: Context) {

    val typer = newTyper(context)

    def setPrivateWithin(tree: Tree, sym: Symbol, mods: Modifiers): Symbol = {
      if (!mods.privateWithin.isEmpty)
        sym.privateWithin = typer.qualifyingClassContext(tree, mods.privateWithin).owner;
      sym
    }

    def updatePosFlags(sym: Symbol, pos: PositionType, flags: int): Symbol = {
      if (settings.debug.value) log("overwriting " + sym);
      val lockedFlag = sym.flags & LOCKED;
      sym.reset(NoType);
      sym setPos pos;
      sym.flags = flags | lockedFlag;
      if (sym.isModule && sym.moduleClass != NoSymbol)
        updatePosFlags(sym.moduleClass, pos, (flags & ModuleToClassFlags) | MODULE | FINAL);
      if (sym.owner.isPackageClass &&
          (sym.linkedSym.rawInfo.isInstanceOf[loaders.SymbolLoader] ||
           sym.linkedSym.rawInfo.isComplete && runId(sym.validTo) != currentRunId))
        // pre-set linked symbol to NoType, in case it is not loaded together with this symbol.
        sym.linkedSym.setInfo(NoType);
      sym
    }

    private def isTemplateContext(context: Context): boolean = context.tree match {
      case Template(_, _) => true
      case Import(_, _) => isTemplateContext(context.outer)
      case _ => false
    }

    private var innerNamerCache: Namer = null
    def innerNamer: Namer = {
      if (innerNamerCache == null)
        innerNamerCache =
          if (!isTemplateContext(context)) this
          else new Namer(context.make(context.tree, context.owner, newScope))
      innerNamerCache
    }

    private def doubleDefError(pos: PositionType, sym: Symbol): unit =
      context.error(pos,
        sym.name.toString() + " is already defined as " +
        (if (sym.hasFlag(CASE)) "case class " + sym.name else sym.toString()))

    def enterInScope(sym: Symbol): Symbol = {
      // allow for overloaded methods
      if (!(sym.isSourceMethod && sym.owner.isClass && !sym.owner.isPackageClass)) {
      	val prev = context.scope.lookupEntry(sym.name);
      	if (prev != null && prev.owner == context.scope &&
            (!prev.sym.isSourceMethod ||
             nme.isSetterName(sym.name) ||
             sym.owner.isPackageClass)) {
     	   doubleDefError(sym.pos, prev.sym)
           sym setInfo ErrorType
      	} else context.scope enter sym
      } else context.scope enter sym
      sym
    }

    private def enterPackageSymbol(pos: PositionType, name: Name): Symbol = {
      val cscope = if (context.owner == EmptyPackageClass) RootClass.info.decls
                   else context.scope;
      val p: Symbol = cscope.lookup(name)
      if (p.isPackage && cscope == p.owner.info.decls) {
        p
      } else {
        val cowner = if (context.owner == EmptyPackageClass) RootClass else context.owner
        val pkg = cowner.newPackage(pos, name)
        pkg.moduleClass.setInfo(new PackageClassInfoType(newScope, pkg.moduleClass))
        pkg.setInfo(pkg.moduleClass.tpe)
        enterInScope(pkg)
      }
    }

    private def inConstructorFlag: long =
      if (context.owner.isConstructor && !context.inConstructorSuffix) INCONSTRUCTOR
      else 0l;

    private def enterClassSymbol(pos: PositionType, flags: int, name: Name): Symbol = {
      var c: Symbol = context.scope.lookup(name)
      if (c.isType && !currentRun.compiles(c) && context.scope == c.owner.info.decls) {
        updatePosFlags(c, pos, flags);
      } else {
        c = enterInScope(context.owner.newClass(pos, name)).setFlag(flags | inConstructorFlag);
      }
      if (c.owner.isPackageClass) {
      	val file = context.unit.source.getFile()
      	val clazz = c.asInstanceOf[ClassSymbol]
      	if (settings.debug.value && clazz.sourceFile != null && !clazz.sourceFile.equals(file)) {
          System.err.println("SOURCE MISMATCH: " + clazz.sourceFile + " vs. " + file + " SYM=" + c);
        }
        clazz.sourceFile = file
      	if (clazz.sourceFile != null) {
      	  assert(!currentRun.compiles(clazz) || clazz.sourceFile == currentRun.symSource(c));
      	  currentRun.symSource(c) = clazz.sourceFile
      	}
      }
      c
    }

    private def enterModuleSymbol(pos: PositionType, flags: int, name: Name): Symbol = {
      var m: Symbol = context.scope.lookup(name)
      if (m.isModule && !m.isPackage && !currentRun.compiles(m) &&
         (context.scope == m.owner.info.decls)) {
        updatePosFlags(m, pos, flags)
      } else {
        if (m.isTerm && !m.isPackage && !currentRun.compiles(m) && (context.scope == m.owner.info.decls))
          context.scope.unlink(m);
        m = context.owner.newModule(pos, name)
        m.setFlag(flags)
        m.moduleClass.setFlag(flags | inConstructorFlag)
	enterInScope(m)
      }
      if (m.owner.isPackageClass) {
        m.moduleClass.sourceFile = context.unit.source.getFile()
        currentRun.symSource(m) = m.moduleClass.sourceFile
      }
      m
    }

    private def enterCaseFactorySymbol(pos: PositionType, flags: int, name: Name): Symbol = {
      var m: Symbol = context.scope.lookup(name)
      if (m.isTerm && !m.isPackage && !currentRun.compiles(m) && context.scope == m.owner.info.decls) {
        updatePosFlags(m, pos, flags)
      } else {
        m = enterInScope(context.owner.newMethod(pos, name)).setFlag(flags)
      }
      if (m.owner.isPackageClass)
        currentRun.symSource(m) = context.unit.source.getFile()
      m
    }

    def enterSyms(trees: List[Tree]): Namer =
      (this /: trees) ((namer, tree) => namer.enterSym(tree));

    def newTypeSkolems(tparams: List[Symbol]): List[Symbol] = {
      val tskolems = tparams map (.newTypeSkolem)
      val ltp = new LazyType {
        override def complete(sym: Symbol): unit =
          sym setInfo sym.deSkolemize.info.substSym(tparams, tskolems);
      }
      tskolems foreach (.setInfo(ltp));
      tskolems
    }

    def skolemize(tparams: List[AbsTypeDef]): unit = {
      val tskolems = newTypeSkolems(tparams map (.symbol))
      for (val Pair(tparam, tskolem) <- tparams zip tskolems) tparam.symbol = tskolem
    }

    def applicableTypeParams(owner: Symbol): List[Symbol] =
      if (owner.isTerm || owner.isPackageClass) List()
      else applicableTypeParams(owner.owner) ::: owner.typeParams;

    def deSkolemize: TypeMap = new DeSkolemizeMap(applicableTypeParams(context.owner))

    def enterSym(tree: Tree): Namer = {

      def finishWith(tparams: List[AbsTypeDef]): unit = {
        if (settings.debug.value) log("entered " + tree.symbol + " in " + context.owner + ", scope-id = " + context.scope.hashCode());
	var ltype: LazyType = innerNamer.typeCompleter(tree)
        if (!tparams.isEmpty) {
	  new Namer(context.makeNewScope(tree, tree.symbol)).enterSyms(tparams);
	  ltype = new LazyPolyType(tparams map (.symbol), ltype)
          if (tree.symbol.isTerm) skolemize(tparams);
	}
	tree.symbol.setInfo(ltype)
      }
      def finish = finishWith(List())


      if (tree.symbol == NoSymbol) {
	val owner = context.owner
	tree match {
	  case PackageDef(name, stats) =>
	    tree.symbol = enterPackageSymbol(tree.pos, name);
	    val namer = new Namer(
	      context.make(tree, tree.symbol.moduleClass, tree.symbol.info.decls));
	    namer.enterSyms(stats);
	  case ClassDef(mods, name, tparams, _, impl) =>
	    if ((mods.flags & (CASE | ABSTRACT)) == CASE) { // enter case factory method.
	      tree.symbol = enterCaseFactorySymbol(
        		tree.pos, mods.flags & AccessFlags | METHOD | CASE, name.toTermName)
        	          .setInfo(innerNamer.caseFactoryCompleter(tree));
                      setPrivateWithin(tree, tree.symbol, mods);
            }
	    tree.symbol = enterClassSymbol(tree.pos, mods.flags, name)
            setPrivateWithin(tree, tree.symbol, mods)
	    finishWith(tparams)
	  case ModuleDef(mods, name, _) =>
	    tree.symbol = enterModuleSymbol(tree.pos, mods.flags | MODULE | FINAL, name);
            setPrivateWithin(tree, tree.symbol, mods)
            setPrivateWithin(tree, tree.symbol.moduleClass, mods)
	    tree.symbol.moduleClass.setInfo(innerNamer.moduleClassTypeCompleter(tree))
	    finish
	  case ValDef(mods, name, tp, rhs) =>
            if (context.owner.isClass & (mods.flags & LOCAL) == 0) {
	      val accflags = ACCESSOR |
                (if ((mods.flags & MUTABLE) != 0) mods.flags & ~MUTABLE else mods.flags | STABLE)
	      val getter = owner.newMethod(tree.pos, name)
	        .setFlag(accflags)
                .setInfo(innerNamer.getterTypeCompleter(tree));
              setPrivateWithin(tree, getter, mods);
	      enterInScope(getter);
	      if ((mods.flags & MUTABLE) != 0) {
	        val setter = owner.newMethod(tree.pos, nme.getterToSetter(name))
		  .setFlag(accflags & ~STABLE & ~CASEACCESSOR)
                  .setInfo(innerNamer.setterTypeCompleter(tree));
                setPrivateWithin(tree, setter, mods);
	        enterInScope(setter)
	      }
	      tree.symbol =
		if ((mods.flags & DEFERRED) == 0)
		  enterInScope(owner.newValue(tree.pos, nme.getterToLocal(name)))
 	            .setFlag(mods.flags & FieldFlags | PRIVATE | LOCAL)
	            .setInfo(innerNamer.typeCompleter(tree))
		else getter;
            } else {
              tree.symbol = enterInScope(owner.newValue(tree.pos, name))
                .setFlag(mods.flags);
	      finish
            }
	  case DefDef(mods, nme.CONSTRUCTOR, tparams, _, _, _) =>
	    tree.symbol = enterInScope(owner.newConstructor(tree.pos))
	      .setFlag(mods.flags | owner.getFlag(ConstrFlags))
            setPrivateWithin(tree, tree.symbol, mods)
	    finishWith(tparams)
	  case DefDef(mods, name, tparams, _, _, _) =>
	    tree.symbol = enterInScope(owner.newMethod(tree.pos, name))
              .setFlag(mods.flags)
            setPrivateWithin(tree, tree.symbol, mods)
	    finishWith(tparams)
	  case AbsTypeDef(mods, name, _, _) =>
	    tree.symbol = enterInScope(owner.newAbstractType(tree.pos, name))
              .setFlag(mods.flags)
            setPrivateWithin(tree, tree.symbol, mods)
	    finish
	  case AliasTypeDef(mods, name, tparams, _) =>
	    tree.symbol = enterInScope(owner.newAliasType(tree.pos, name))
              .setFlag(mods.flags)
            setPrivateWithin(tree, tree.symbol, mods)
	    finishWith(tparams)
	  case DocDef(_, defn) =>
	    enterSym(defn)
	  case imp @ Import(_, _) =>
	    tree.symbol = NoSymbol.newImport(tree.pos).setInfo(innerNamer.typeCompleter(tree));
	    return new Namer(context.makeNewImport(imp));
	  case _ =>
	}
      }
      this
    }

// --- Lazy Type Assignment --------------------------------------------------

    def typeCompleter(tree: Tree) = new TypeCompleter(tree) {
      override def complete(sym: Symbol): unit = {
        if (settings.debug.value) log("defining " + sym);
        val tp = typeSig(tree)
        sym.setInfo(tp)
        if (settings.debug.value) log("defined " + sym);
        validate(sym)
      }
    }

    def moduleClassTypeCompleter(tree: Tree) = new TypeCompleter(tree) {
      override def complete(sym: Symbol): unit = {
        tree.symbol.info // sets moduleClass info as a side effect.
      }
    }

    def getterTypeCompleter(tree: Tree) = new TypeCompleter(tree) {
      override def complete(sym: Symbol): unit = {
        if (settings.debug.value) log("defining " + sym);
        sym.setInfo(PolyType(List(), typeSig(tree)))
        if (settings.debug.value) log("defined " + sym);
        validate(sym)
      }
    }

    def setterTypeCompleter(tree: Tree) = new TypeCompleter(tree) {
      override def complete(sym: Symbol): unit = {
        if (settings.debug.value) log("defining " + sym);
        sym.setInfo(MethodType(List(typeSig(tree)), UnitClass.tpe))
        if (settings.debug.value) log("defined " + sym);
        validate(sym)
      }
    }

    def selfTypeCompleter(tree: Tree) = new TypeCompleter(tree) {
      override def complete(sym: Symbol): unit = {
        sym.setInfo(typer.typedType(tree).tpe)
      }
    }

    def caseFactoryCompleter(tree: Tree) = new TypeCompleter(tree) {
      override def complete(sym: Symbol): unit = {
	val clazz = tree.symbol
	var tpe = clazz.primaryConstructor.tpe
	val tparams = clazz.typeParams
	if (!tparams.isEmpty) tpe = PolyType(tparams, tpe).cloneInfo(sym);
	sym.setInfo(tpe)
      }
    }

    private def deconstIfNotFinal(sym: Symbol, tpe: Type): Type =
      if (sym.isVariable ||
	  !(sym hasFlag FINAL) ||
	  sym.isMethod && !(sym hasFlag ACCESSOR)) tpe.deconst
      else tpe;

    def enterValueParams(owner: Symbol, vparamss: List[List[ValDef]]): List[List[Symbol]] = {
      def enterValueParam(param: ValDef): Symbol = {
	param.symbol = owner.newValueParameter(param.pos, param.name)
	  .setInfo(typeCompleter(param))
          .setFlag(param.mods.flags & (BYNAMEPARAM | IMPLICIT));
        setPrivateWithin(param, param.symbol, param.mods);
        context.scope enter param.symbol;
        param.symbol
      }
      vparamss.map(.map(enterValueParam))
    }

    /** A creator for polytypes. If tparams is empty, simply returns result type */
    private def makePolyType(tparams: List[Symbol], tpe: Type): Type =
      if (tparams.isEmpty) tpe
      else
	PolyType(tparams, tpe match {
	  case PolyType(List(), tpe1) => tpe1
	  case _ => tpe
	});

    private def templateSig(templ: Template): Type = {
      val clazz = context.owner
      def checkParent(tpt: Tree): Type = {
        val tp = tpt.tpe
        if (tp.symbol == context.owner) {
          context.error(tpt.pos, ""+tp.symbol+" inherits itself");
          AnyRefClass.tpe
        } else if (tp.isError) {
          AnyRefClass.tpe
        } else {
          tp
        }
      }
      val parents = typer.parentTypes(templ) map checkParent
      val decls = newScope;
      new Namer(context.make(templ, clazz, decls)).enterSyms(templ.body);
      ClassInfoType(parents, decls, clazz)
    }

    private def classSig(tparams: List[AbsTypeDef], tpt: Tree, impl: Template): Type = {
      val tparamSyms = typer.reenterTypeParams(tparams);
      if (!tpt.isEmpty)
        context.owner.typeOfThis = selfTypeCompleter(tpt);
      else tpt.tpe = NoType;
      makePolyType(tparamSyms, templateSig(impl))
    }

    private def methodSig(tparams: List[AbsTypeDef], vparamss: List[List[ValDef]],
                          tpt: Tree, rhs: Tree): Type = {
      val meth = context.owner
      val tparamSyms = typer.reenterTypeParams(tparams)
      val vparamSymss = enterValueParams(meth, vparamss)
      val restype =
	if (tpt.isEmpty) {
	  tpt.tpe = if (meth.name == nme.CONSTRUCTOR) context.enclClass.owner.tpe
		    else deconstIfNotFinal(meth, typer.computeType(rhs));
	  tpt.tpe
	} else typer.typedType(tpt).tpe;
      def mkMethodType(vparams: List[Symbol], restpe: Type) = {
	val formals = vparams map (.tpe);
	if (!vparams.isEmpty && vparams.head.hasFlag(IMPLICIT)) ImplicitMethodType(formals, restpe)
	else MethodType(formals, restpe);
      }
      makePolyType(
	tparamSyms,
	if (vparamSymss.isEmpty) PolyType(List(), restype)
	else (vparamSymss :\ restype)(mkMethodType))
    }

    /** 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);
	for (val 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
    }

    private def aliasTypeSig(tpsym: Symbol, tparams: List[AbsTypeDef], rhs: Tree): Type =
      makePolyType(typer.reenterTypeParams(tparams), typer.typedType(rhs).tpe);

    private def typeSig(tree: Tree): Type = {
      val result =
        try {
	  val sym: Symbol = tree.symbol
	  tree match {
	    case ClassDef(_, _, tparams, tpt, impl) =>
	      new Namer(context.makeNewScope(tree, sym)).classSig(tparams, tpt, impl)

	    case ModuleDef(_, _, impl) =>
	      val clazz = sym.moduleClass
	      clazz.setInfo(new Namer(context.make(tree, clazz)).templateSig(impl));
	      //clazz.typeOfThis = singleType(sym.owner.thisType, sym);
	      clazz.tpe;

	    case DefDef(_, _, tparams, vparamss, tpt, rhs) =>
	      val result =
	        new Namer(context.makeNewScope(tree, sym)).methodSig(tparams, vparamss, tpt, rhs);
	      checkContractive(sym, result)

	    case ValDef(_, _, tpt, rhs) =>
	      if (tpt.isEmpty) {
	        if (rhs.isEmpty) {
		  context.error(tpt.pos, "missing parameter type");
		  ErrorType
	        } else {
		  tpt.tpe = deconstIfNotFinal(sym, newTyper(context.make(tree, sym)).computeType(rhs));
		  tpt.tpe
	        }
	      } else {
                val typer1 =
                  if (sym.hasFlag(PARAM) && sym.owner.isConstructor && !phase.erasedTypes)
                    newTyper(context.makeConstructorContext)
                  else typer;
                typer1.typedType(tpt).tpe
              }

	    case AliasTypeDef(_, _, tparams, rhs) =>
	      new Namer(context.makeNewScope(tree, sym)).aliasTypeSig(sym, tparams, rhs)

	    case AbsTypeDef(_, _, lo, hi) =>
              var lt = typer.typedType(lo).tpe
              if (lt.isError) lt = AllClass.tpe
              var ht = typer.typedType(hi).tpe
              if (ht.isError) ht = AnyClass.tpe
	      TypeBounds(lt, ht)

	    case Import(expr, selectors) =>
	      val expr1 = typer.typedQualifier(expr)
	      val base = expr1.tpe
	      typer.checkStable(expr1)
              def checkNotRedundant(pos: PositionType, from: Name, to: Name): boolean = {
                if (!tree.symbol.hasFlag(SYNTHETIC) && 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 != 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[Pair[Name, Name]]): unit = selectors match {
	        case Pair(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 != 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 =>
            //System.out.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
     */
    def validate(sym: Symbol): unit = {
      def checkNoConflict(flag1: int, flag2: int): unit =
	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));
      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)
	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.symbol == 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.flags & DEFERRED) != 0) {
	if (!sym.isValueParameter && !sym.isTypeParameterOrSkolem &&
	    (!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)
    }
  }

  /* Is type `tp1' properly contained in type `tp2'? */
  def isContainedIn(tp1: Type, tp2: Type) = {
    //System.out.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.typeArgs.length > elemtp.typeArgs.length))
          result = true
        else Pair(tp, elemtp) match {
          case Pair(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(val tree: Tree) extends LazyType

  /** 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) =
    if (member hasFlag ACCESSOR) {
      if (member hasFlag DEFERRED) {
        val getter = if (member.isSetter) member.getter(member.owner) else member
        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) =
    if (underlying(sym).isVariable)
      "\n(Note that variables need to be initialized to be defined)"
    else ""
}