summaryrefslogblamecommitdiff
path: root/src/compiler/scala/tools/nsc/typechecker/Infer.scala
blob: 52672ed0147954cd56acca8e86a58b85ef438f63 (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.collection.mutable.ListBuffer
import symtab.Flags._

/** This trait ...
 *
 *  @author Martin Odersky
 *  @version 1.0
 */
trait Infer requires Analyzer {
  import global._
  import definitions._
  import posAssigner.atPos

  // statistics
  var normM = 0
  var normP = 0
  var normO = 0

/* -- Type parameter inference utility functions --------------------------- */

  def assertNonCyclic(tvar: TypeVar) =
    assert(tvar.constr.inst != tvar, tvar.origin)

  def isVarArgs(formals: List[Type]) =
    !formals.isEmpty && (formals.last.symbol == RepeatedParamClass)

  /** The formal parameter types corresponding to <code>formals</code>.
   *  If <code>formals</code> has a repeated last parameter, a list of
   *  (nargs - params.length + 1) copies of its type is returned.
   *
   *  @param formals ...
   *  @param nargs ...
   */
  def formalTypes(formals: List[Type], nargs: int): List[Type] = {
    val formals1 = formals map {
      case TypeRef(_, sym, List(arg)) if (sym == ByNameParamClass) => arg
      case formal => formal
    }
    if (isVarArgs(formals1)) {
      val ft = formals1.last.typeArgs.head
      formals1.init ::: (for (val i <- List.range(formals1.length - 1, nargs)) yield ft)
    } else formals1
  }

  def actualTypes(actuals: List[Type], nformals: int): List[Type] =
    if (nformals == 1 && actuals.length != 1)
      List(if (actuals.length == 0) UnitClass.tpe else tupleType(actuals))
    else actuals

  def actualArgs(pos: PositionType, actuals: List[Tree], nformals: int): List[Tree] =
    if (nformals == 1 && actuals.length != 1) List(atPos(pos)(gen.mkTuple(actuals))) else actuals

  /** A fresh type varable with given type parameter as origin.
   *
   *  @param tparam ...
   *  @return       ...
   */
  def freshVar(tparam: Symbol): TypeVar =
    new TypeVar(tparam.tpe, new TypeConstraint)

  //todo: remove comments around following privates; right now they cause an IllegalAccess
  // error when built with scalac

  /*private*/ class NoInstance(msg: String) extends RuntimeException(msg)

  /*private*/ class DeferredNoInstance(getmsg: () => String) extends NoInstance("") {
    override def getMessage(): String = getmsg()
  }

  /*private*/ object instantiateMap extends TypeMap {
    def apply(t: Type): Type = instantiate(t)
  }

  /** map every TypeVar to its constraint.inst field.
   *  throw a NoInstance exception if a NoType or WildcardType is encountered.
   *
   *  @param  tp ...
   *  @return    ...
   *  @throws    NoInstance
   */
  def instantiate(tp: Type): Type = tp match {
    case WildcardType | NoType =>
      throw new NoInstance("undetermined type")
    case TypeVar(origin, constr) =>
      if (constr.inst != NoType) instantiate(constr.inst)
      else throw new DeferredNoInstance(() =>
        "no unique instantiation of type variable " + origin + " could be found")
    case _ =>
      instantiateMap.mapOver(tp)
  }

  /** Is type fully defined, i.e. no embedded anytypes or wildcards in it?
   *
   *  @param tp ...
   *  @return   ...
   */
  def isFullyDefined(tp: Type): boolean = try {
    instantiate(tp); true
  } catch {
    case ex: NoInstance => false
  }

  /** Do type arguments <code>targs</code> conform to formal parameters
   *  <code>tparams</code>?
   *
   *  @param tparams ...
   *  @param targs   ...
   *  @return        ...
   */
  private def isWithinBounds(pre: Type, owner: Symbol, tparams: List[Symbol], targs: List[Type]): boolean = {
    val bounds = tparams map { tparam =>
      tparam.info.asSeenFrom(pre, owner).subst(tparams, targs).bounds
    }
    !(List.map2(bounds, targs)((bound, targ) => bound containsType targ) contains false)
  }

  /** Solve constraint collected in types <code>tvars</code>.
   *
   *  @param tvars      All type variables to be instantiated.
   *  @param tparams    The type parameters corresponding to <code>tvars</code>
   *  @param variances  The variances of type parameters; need to reverse
   *                    solution direction for all contravariant variables.
   *  @param upper      When <code>true</code> search for max solution else min.
   *  @throws NoInstance
   */
  private def solve(tvars: List[TypeVar], tparams: List[Symbol],
                    variances: List[int], upper: boolean): List[Type] = {
    val config = tvars zip (tparams zip variances)

    def solveOne(tvar: TypeVar, tparam: Symbol, variance: int): unit = {
      if (tvar.constr.inst == NoType) {
        val up = if (variance != CONTRAVARIANT) upper else !upper
        tvar.constr.inst = null
        val bound: Type = if (up) tparam.info.bounds.hi else tparam.info.bounds.lo
        //Console.println("solveOne0 "+tvar+" "+config+" "+bound);//DEBUG
        var cyclic = false
        for (val Pair(tvar2, Pair(tparam2, variance2)) <- config) {
          if (tparam2 != tparam &&
              ((bound contains tparam2) ||
               up && (tparam2.info.bounds.lo =:= tparam.tpe) ||
               !up && (tparam2.info.bounds.hi =:= tparam.tpe))) {
            if (tvar2.constr.inst eq null) cyclic = true
            solveOne(tvar2, tparam2, variance2)
          }
        }
        if (!cyclic) {
          if (up) {
            if (bound.symbol != AnyClass) {
              tvar.constr.hibounds =
                bound.subst(tparams, tvars) :: tvar.constr.hibounds
            }
            for (val tparam2 <- tparams)
              if (tparam2.info.bounds.lo =:= tparam.tpe)
                tvar.constr.hibounds =
                  tparam2.tpe.subst(tparams, tvars) :: tvar.constr.hibounds
          } else {
            if (bound.symbol != AllClass && bound.symbol != tparam) {
              tvar.constr.lobounds =
                bound.subst(tparams, tvars) :: tvar.constr.lobounds
            }
            for (val tparam2 <- tparams)
              if (tparam2.info.bounds.hi =:= tparam.tpe)
                tvar.constr.lobounds =
                  tparam2.tpe.subst(tparams, tvars) :: tvar.constr.lobounds
          }
        }
        tvar.constr.inst = NoType // necessary because hibounds/lobounds may contain tvar
        //Console.println("solving "+tvar+" "+up+" "+(if (up) (tvar.constr.hibounds) else tvar.constr.lobounds))//DEBUG
        tvar.constr.inst = if (up) glb(tvar.constr.hibounds) else lub(tvar.constr.lobounds)
        assertNonCyclic(tvar)//debug
      }
    }
    for (val Pair(tvar, Pair(tparam, variance)) <- config)
      solveOne(tvar, tparam, variance)
    tvars map instantiate
  }

  def skipImplicit(tp: Type) =
    if (tp.isInstanceOf[ImplicitMethodType]) tp.resultType else tp

  /** Automatically perform the following conversions on expression types:
   *  A method type becomes the corresponding function type.
   *  A nullary method type becomes its result type.
   *  Implicit parameters are skipped.
   *
   *  @param tp ...
   *  @return   ...
   */
  def normalize(tp: Type): Type = skipImplicit(tp) match {
    case MethodType(formals, restpe) =>
      if (util.Statistics.enabled) normM = normM + 1
      functionType(formals, normalize(restpe))
    case PolyType(List(), restpe) =>
      if (util.Statistics.enabled) normP = normP + 1
      normalize(restpe)
    case tp1 =>
      if (util.Statistics.enabled) normO = normO + 1
      tp1
  }

  private val stdErrorClass = RootClass.newErrorClass(nme.ERROR.toTypeName)
  private val stdErrorValue = stdErrorClass.newErrorValue(nme.ERROR)

  /** The context-dependent inferencer part */
  class Inferencer(context: Context) {

    /* -- Error Messages --------------------------------------------------- */

    def setError[T <: Tree](tree: T): T = {
      if (tree.hasSymbol)
        if (context.reportGeneralErrors) {
          val name = newTermName("<error: " + tree.symbol + ">")
          tree.setSymbol(
            if (tree.isType) context.owner.newErrorClass(name.toTypeName)
            else context.owner.newErrorValue(name))
        } else {
          tree.setSymbol(if (tree.isType) stdErrorClass else stdErrorValue)
        }
      tree.setType(ErrorType)
    }

    def decode(name: Name): String =
      (if (name.isTypeName) "type " else "value ") + name.decode

    def treeSymTypeMsg(tree: Tree): String =
      if (tree.symbol eq null)
        "expression of type " + tree.tpe
      else if (tree.symbol.hasFlag(OVERLOADED))
        "overloaded method " + tree.symbol + " with alternatives " + tree.tpe
      else
        tree.symbol.toString() +
        (if (tree.tpe.paramSectionCount > 0) ": " else " of type ") +
        tree.tpe +
        (if (tree.symbol.name == nme.apply) tree.symbol.locationString else "")

    def applyErrorMsg(tree: Tree, msg: String, argtpes: List[Type], pt: Type) = (
      treeSymTypeMsg(tree) + msg + argtpes.mkString("(", ",", ")") +
       (if (pt == WildcardType) "" else " with expected result type " + pt)
    )

    def foundReqMsg(found: Type, req: Type): String =
      withDisambiguation(found, req) {
        ";\n found   : " + found.toLongString + "\n required: " + req
      }

    def typeErrorMsg(found: Type, req: Type) =
      "type mismatch" + foundReqMsg(found, req) +
      (if (!(found.resultType eq found) && isWeaklyCompatible(found.resultType, req))
        "\n possible cause: missing arguments for method or constructor"
       else "")

    def error(pos: PositionType, msg: String): unit =
      context.error(pos, msg)

    def errorTree(tree: Tree, msg: String): Tree = {
      if (!tree.isErroneous) error(tree.pos, msg)
      setError(tree)
    }

    def typeError(pos: PositionType, found: Type, req: Type) {
      if (!found.isErroneous && !req.isErroneous) {
        error(pos, typeErrorMsg(found, req))
        if (settings.explaintypes.value) explainTypes(found, req)
      }
    }

    def typeErrorTree(tree: Tree, found: Type, req: Type): Tree = {
      typeError(tree.pos, found, req)
      setError(tree)
    }

    def explainTypes(tp1: Type, tp2: Type) =
      withDisambiguation(tp1, tp2) { global.explainTypes(tp1, tp2) }

    /** If types `tp1' `tp2' contain different type variables with same name
     *  differentiate the names by including owner information
     */
    private def withDisambiguation[T](tp1: Type, tp2: Type)(op: => T): T = {

      def explainName(sym: Symbol) = {
        if (!sym.name.toString.endsWith(")")) {
          sym.name = newTypeName(sym.name.toString+"(in "+sym.owner+")")
        }
      }

      val patches = {
        val syms1 = typeRefs.collect(tp1)
        val syms2 = typeRefs.collect(tp2)
        for {
          val sym1 <- syms1
          val sym2 <- syms2
          sym1 != sym2 && sym1.toString == sym2.toString
        } yield {
          val name = sym1.name
          explainName(sym1)
          explainName(sym2)
          if (sym1.owner == sym2.owner) sym2.name = newTypeName("(some other)"+sym2.name)
          Triple(sym1, sym2, name)
        }
      }

      val result = op

      for (val Triple(sym1, sym2, name) <- patches) {
        sym1.name = name
        sym2.name = name
      }

      result
    }

    /* -- Tests & Checks---------------------------------------------------- */

    /** Check that <code>sym</code> is defined and accessible as a member of
     *  tree <code>site</code> with type <code>pre</code> in current context.
     *
     *  @param tree ...
     *  @param sym  ...
     *  @param pre  ...
     *  @param site ...
     *  @return     ...
     */
    def checkAccessible(tree: Tree, sym: Symbol, pre: Type, site: Tree): Tree =
      if (sym.isError) {
        tree setSymbol sym setType ErrorType
      } else {
        def accessError(explanation: String): Tree =
          errorTree(tree, underlying(sym).toString() + " cannot be accessed in " +
                    (if (sym.isClassConstructor) context.enclClass.owner else pre.widen) +
                    explanation)
        if (context.unit != null) sym.toplevelClass match {
          case clazz : ClassSymbol =>
            // System.err.println("TOP: " + clazz + " " + clazz.sourceFile)
            if (clazz.sourceFile != null) {
                context.unit.depends += clazz.sourceFile
              //Console.println("DEPEND " + global.currentRun.currentUnit + " ON " + clazz.sourceFile + " XXX " + context.unit)
            }

          case _ =>
        }
        val sym1 = sym filter (alt => context.isAccessible(alt, pre, site.isInstanceOf[Super]))
        if (sym1 == NoSymbol) {
          if (settings.debug.value) {
            Console.println(context)
            Console.println(tree)
            Console.println("" + pre + " " + sym.owner + " " + context.owner + " " + context.outer.enclClass.owner + " " + sym.owner.thisType + (pre =:= sym.owner.thisType))
          }
          accessError("")
        } else {
          //Console.println("check acc " + sym1 + ":" + sym1.tpe + " from " + pre);//DEBUG
          var owntype = try{
            pre.memberType(sym1)
          } catch {
            case ex: MalformedType =>
              val sym2 = underlying(sym1)
              val itype = withoutMalformedChecks(pre.memberType(sym2))
              accessError("\n because its instance type "+itype+
                          (if ("malformed type: "+itype.toString==ex.msg) " is malformed"
                           else " contains a "+ex.msg))
              ErrorType
          }
          if (pre.isInstanceOf[SuperType])
            owntype = owntype.substSuper(pre, site.symbol.thisType)
          tree setSymbol sym1 setType owntype
        }
      }

    def isCompatible(tp: Type, pt: Type): boolean = {
      val tp1 = normalize(tp)
      (tp1 <:< pt) || isCoercible(tp, pt)
    }

    def isWeaklyCompatible(tp: Type, pt: Type): boolean =
      pt.symbol == UnitClass || isCompatible(tp, pt)

    def isCoercible(tp: Type, pt: Type): boolean = false

    def isCompatible(tps: List[Type], pts: List[Type]): boolean =
      List.map2(tps, pts)((tp, pt) => isCompatible(tp, pt)) forall (x => x)

    /* -- Type instantiation------------------------------------------------ */

    /** Return inferred type arguments of polymorphic expression, given
     *  its type parameters and result type and a prototype <code>pt</code>.
     *  If no minimal type variables exist that make the
     *  instantiated type a subtype of <code>pt</code>, return null.
     *
     *  @param tparams ...
     *  @param restpe  ...
     *  @param pt      ...
     *  @return        ...
     */
    private def exprTypeArgs(tparams: List[Symbol], restpe: Type, pt: Type): List[Type] = {
      val tvars = tparams map freshVar
      if (isCompatible(restpe.subst(tparams, tvars), pt)) {
        try {
          solve(tvars, tparams, tparams map varianceInType(restpe), false)
        } catch {
          case ex: NoInstance => null
        }
      } else null
    }

    /** Return inferred proto-type arguments of function, given
    *  its type and value parameters and result type, and a
    *  prototype <code>pt</code> for the function result.
    *  Type arguments need to be either determined precisely by
    *  the prototype, or they are maximized, if they occur only covariantly
    *  in the value parameter list.
    *  If instantiation of a type parameter fails,
    *  take WildcardType for the proto-type argument.
    *
    *  @param tparams ...
    *  @param formals ...
    *  @param restype ...
    *  @param pt      ...
    *  @return        ...
    */
    def protoTypeArgs(tparams: List[Symbol], formals: List[Type], restpe: Type,
                      pt: Type): List[Type] = {
      /** Map type variable to its instance, or, if `variance' is covariant/contravariant,
       *  to its upper/lower bound */
      def instantiateToBound(tvar: TypeVar, variance: int): Type = try {
        //Console.println("instantiate "+tvar+tvar.constr+" variance = "+variance);//DEBUG
        if (tvar.constr.inst != NoType) {
          instantiate(tvar.constr.inst)
        } else if ((variance & COVARIANT) != 0 && !tvar.constr.hibounds.isEmpty) {
          tvar.constr.inst = glb(tvar.constr.hibounds)
          assertNonCyclic(tvar)//debug
          instantiate(tvar.constr.inst)
        } else if ((variance & CONTRAVARIANT) != 0 && !tvar.constr.lobounds.isEmpty) {
          tvar.constr.inst = lub(tvar.constr.lobounds)
          assertNonCyclic(tvar)//debug
          instantiate(tvar.constr.inst)
        } else if (!tvar.constr.hibounds.isEmpty && !tvar.constr.lobounds.isEmpty &&
                   glb(tvar.constr.hibounds) <:< lub(tvar.constr.lobounds)) {
          tvar.constr.inst = glb(tvar.constr.hibounds)
          assertNonCyclic(tvar)//debug
          instantiate(tvar.constr.inst)
        } else {
          WildcardType
        }
      } catch {
        case ex: NoInstance => WildcardType
      }
      val tvars = tparams map freshVar
      if (isCompatible(restpe.subst(tparams, tvars), pt))
        List.map2(tparams, tvars) ((tparam, tvar) =>
          instantiateToBound(tvar, varianceInTypes(formals)(tparam)))
      else
        tvars map (tvar => WildcardType)
    }

    /** Return inferred type arguments, given type parameters, formal parameters,
    *  argument types, result type and expected result type.
    *  If this is not possible, throw a <code>NoInstance</code> exception.
    *  Undetermined type arguments are represented by `definitions.AllClass.tpe'.
    *  No check that inferred parameters conform to their bounds is made here.
    *
    *  @param   tparams         the type parameters of the method
    *  @param   formals         the value parameter types of the method
    *  @param   restp           the result type of the method
    *  @param   argtpes         the argument types of the application
    *  @param   pt              the expected return type of the application
    *  @param   uninstantiated  a listbuffer receiving all uninstantiated type parameters
    *                           (type parameters mapped by the constraint solver to `scala.All'
    *                           and not covariant in <code>restpe</code> are taken to be
    *                           uninstantiated. Maps all those type arguments to their
    *                           corresponding type parameters).
    *  @return                  ...
    *  @throws                  NoInstance
    */
    // bq: was private, but need it for unapply checking
    def methTypeArgs(tparams: List[Symbol], formals: List[Type], restpe: Type,
                             argtpes: List[Type], pt: Type,
                             uninstantiated: ListBuffer[Symbol]): List[Type] = {
      val tvars = tparams map freshVar
      if (formals.length != argtpes.length) {
        throw new NoInstance("parameter lists differ in length")
      }
      // check first whether type variables can be fully defined from
      // expected result type.
      if (!isCompatible(restpe.subst(tparams, tvars), pt)) {
        throw new DeferredNoInstance(() =>
          "result type " + normalize(restpe) + " is incompatible with expected type " + pt)
      }
      for (val tvar <- tvars)
        if (!isFullyDefined(tvar)) tvar.constr.inst = NoType

      // Then define remaining type variables from argument types.
      List.map2(argtpes, formals) {(argtpe, formal) =>
        if (!isCompatible(argtpe.deconst.subst(tparams, tvars),
                          formal.subst(tparams, tvars))) {
          if (settings.explaintypes.value)
            explainTypes(argtpe.deconst.subst(tparams, tvars), formal.subst(tparams, tvars))
          throw new DeferredNoInstance(() =>
            "argument expression's type is not compatible with formal parameter type" +
            foundReqMsg(argtpe.deconst.subst(tparams, tvars), formal.subst(tparams, tvars)))
        }
        ()
      }
      val targs = solve(tvars, tparams, tparams map varianceInTypes(formals), false)
      List.map2(tparams, targs) {(tparam, targ) =>
        if (targ.symbol == AllClass && (varianceInType(restpe)(tparam) & COVARIANT) == 0) {
          uninstantiated += tparam
          tparam.tpe
        } else targ}
    }


    /** Is there an instantiation of free type variables <code>undetparams</code>
     *  such that function type <code>ftpe</code> is applicable to
     *  <code>argtpes</code> and its result conform to <code>pt</code>?
     *
     *  @param undetparams ...
     *  @param ftpe        ...
     *  @param argtpes     ...
     *  @param pt          ...
     *  @return            ...
     */
    def isApplicable(undetparams: List[Symbol], ftpe: Type,
                     argtpes0: List[Type], pt: Type): boolean =
      ftpe match {
        case MethodType(formals0, restpe) =>
          val formals = formalTypes(formals0, argtpes0.length)
          val argtpes = actualTypes(argtpes0, formals.length)
          if (undetparams.isEmpty) {
            (formals.length == argtpes.length &&
             isCompatible(argtpes, formals) &&
             isWeaklyCompatible(restpe, pt))
          } else {
            try {
              val uninstantiated = new ListBuffer[Symbol]
              val targs = methTypeArgs(undetparams, formals, restpe, argtpes, pt, uninstantiated)
              (exprTypeArgs(uninstantiated.toList, restpe.subst(undetparams, targs), pt) ne null) &&
              isWithinBounds(NoPrefix, NoSymbol, undetparams, targs)
            } catch {
              case ex: NoInstance => false
            }
          }
        case PolyType(tparams, restpe) =>
          val tparams1 = cloneSymbols(tparams)
          isApplicable(tparams1 ::: undetparams, restpe.substSym(tparams, tparams1), argtpes0, pt)
        case ErrorType =>
          true
        case _ =>
          false
      }

    /** Does type <code>ftpe1</code> specialize type <code>ftpe2</code>
     *  when both are alternatives in an overloaded function?
     *
     *  @param ftpe1 ...
     *  @param ftpe2 ...
     *  @return      ...
     */
    def specializes(ftpe1: Type, ftpe2: Type): boolean = ftpe1 match {
      case MethodType(formals, _) =>
        isApplicable(List(), ftpe2, formals, WildcardType)
      case PolyType(tparams, MethodType(formals, _)) =>
        isApplicable(List(), ftpe2, formals, WildcardType)
      case ErrorType =>
        true
      case _ =>
        false
    }

    /** Is type `tpe1' a strictly better alternative than type `ftpe2'?
     *
     *  @param tpe1 ...
     *  @param tpe2 ...
     *  @return     ...
     */
    def isStrictlyBetter(tpe1: Type, tpe2: Type) = {
      def isNullary(tpe: Type) = tpe.paramSectionCount == 0 || tpe.paramTypes.isEmpty
      isNullary(tpe1) && !isNullary(tpe2) ||
      specializes(tpe1, tpe2) && !specializes(tpe2, tpe1)
    }

    /** error if arguments not within bounds. */
    def checkBounds(pos: PositionType, pre: Type, owner: Symbol,
                    tparams: List[Symbol], targs: List[Type], prefix: String) {
      if (!isWithinBounds(pre, owner, tparams, targs)) {
        if (!(targs exists (.isErroneous)) && !(tparams exists (.isErroneous))) {
          error(pos,
                prefix + "type arguments " + targs.mkString("[", ",", "]") +
                " do not conform to " + tparams.head.owner + "'s type parameter bounds " +
                (tparams map (.defString)).mkString("[", ",", "]"))
        }
        if (settings.explaintypes.value) {
          val bounds = tparams map (.info.subst(tparams, targs).bounds)
          List.map2(targs, bounds)((targ, bound) => explainTypes(bound.lo, targ))
          List.map2(targs, bounds)((targ, bound) => explainTypes(targ, bound.hi))
          ()
        }
      }
    }

    /** Substitite free type variables `undetparams' of polymorphic argument
     *  expression `tree', given two prototypes `strictPt', and `lenientPt'.
     *  `strictPt' is the first attempt prototype where type parameters
     *  are left unchanged. `lenientPt' is the fall-back prototype where type
     *  parameters are replaced by `WildcardType's. We try to instantiate
     *  first to `strictPt' and then, if this fails, to `lenientPt'. If both
     *  attempts fail, an error is produced.
     */
    def inferArgumentInstance(tree: Tree, undetparams: List[Symbol],
                              strictPt: Type, lenientPt: Type): unit = {
      var targs = exprTypeArgs(undetparams, tree.tpe, strictPt)
      if (targs eq null) targs = exprTypeArgs(undetparams, tree.tpe, lenientPt)
      substExpr(tree, undetparams, targs, lenientPt)
    }

    /** Substitite free type variables `undetparams; of polymorphic expression
     *  <code>tree</code>, given prototype <code>pt</code>.
     *
     *  @param tree ...
     *  @param undetparams ...
     *  @param pt ...
     */
    def inferExprInstance(tree: Tree, undetparams: List[Symbol], pt: Type): unit =
      substExpr(tree, undetparams, exprTypeArgs(undetparams, tree.tpe, pt), pt)

    /** Substitite free type variables `undetparams' of polymorphic argument
     *  expression <code>tree</code> to `targs', Error if `targs' is null
     *
     *  @param tree ...
     *  @param undetparams ...
     *  @param targs ...
     *  @param pt ...
     */
    private def substExpr(tree: Tree, undetparams: List[Symbol],
                          targs: List[Type], pt: Type) {
      if (targs eq null) {
        if (!tree.tpe.isErroneous && !pt.isErroneous)
          error(tree.pos, "polymorphic expression cannot be instantiated to expected type" +
                foundReqMsg(PolyType(undetparams, skipImplicit(tree.tpe)), pt))
      } else {
        new TreeTypeSubstituter(undetparams, targs).traverse(tree)
      }
    }

    /** Substitite free type variables <code>undetparams</code> of application
     *  <code>fn(args)</code>, given prototype <code>pt</code>.
     *
     *  @param fn          ...
     *  @param undetparams ...
     *  @param args        ...
     *  @param pt          ...
     *  @return            Return the list of type parameters that remain uninstantiated.
     */
    def inferMethodInstance(fn: Tree, undetparams: List[Symbol],
                            args: List[Tree], pt: Type): List[Symbol] = fn.tpe match {
      case MethodType(formals0, restpe) =>
        try {
          val formals = formalTypes(formals0, args.length)
          val argtpes = actualTypes(args map (.tpe.deconst), formals.length)
          val uninstantiated = new ListBuffer[Symbol]
          val targs = methTypeArgs(undetparams, formals, restpe, argtpes, pt, uninstantiated)
          checkBounds(fn.pos, NoPrefix, NoSymbol, undetparams, targs, "inferred ")
          //Console.println("UNAPPLY subst type "+undetparams+" to "+targs+" in "+fn+" ( "+args+ ")")
          val treeSubst = new TreeTypeSubstituter(undetparams, targs)
          treeSubst.traverse(fn)
          treeSubst.traverseTrees(args)
          //Console.println("UNAPPLY gives "+fn+" ( "+args+ "), argtpes = "+argtpes+", pt = "+pt)
          uninstantiated.toList
        } catch {
          case ex: NoInstance =>
            errorTree(fn,
              "no type parameters for " +
              applyErrorMsg(
                fn, " exist so that it can be applied to arguments ",
                args map (.tpe.widen), WildcardType) +
              "\n --- because ---\n" + ex.getMessage())
            List()
        }
    }

    /** Is intersection of given types populated? That is,
     *  for all types tp1, tp2 in intersection
     *    for all common base classes bc of tp1 and tp2
     *      let bt1, bt2 be the base types of tp1, tp2 relative to class bc
     *      Then:
     *        bt1 and bt2 have the same prefix, and
     *        any correspondiong non-variant type arguments of bt1 and bt2 are the same
     */
    def isPopulated(tp1: Type, tp2: Type): boolean = {
      def isConsistent(tp1: Type, tp2: Type): boolean = Pair(tp1, tp2) match {
        case Pair(TypeRef(pre1, sym1, args1), TypeRef(pre2, sym2, args2)) =>
          assert(sym1 == sym2)
          pre1 =:= pre2 &&
          !(List.map3(args1, args2, sym1.typeParams) {
            (arg1, arg2, tparam) =>
              //if (tparam.variance == 0 && !(arg1 =:= arg2)) Console.println("inconsistent: "+arg1+"!="+arg2)//DEBUG
            tparam.variance != 0 || arg1 =:= arg2
          } contains false)
      }
      if (tp1.symbol.isClass && tp1.symbol.hasFlag(FINAL)) tp1 <:< tp2
      else tp1.baseClasses forall (bc =>
        tp2.closurePos(bc) < 0 || isConsistent(tp1.baseType(bc), tp2.baseType(bc)))
    }

    /** Type with all top-level occurrences of abstract types replaced by their bounds */
    def widen(tp: Type): Type = tp match {
      case TypeRef(pre, sym, _) if sym.isAbstractType =>
        widen(tp.bounds.hi)
      case rtp @ RefinedType(parents, decls) =>
        copyRefinedType(rtp, List.mapConserve(parents)(widen), decls)
      case _ =>
        tp
    }

    /** Substitite free type variables <code>undetparams</code> of type constructor
     *  <code>tree</code> in pattern, given prototype <code>pt</code>.
     *
     *  @param tree        ...
     *  @param undetparams ...
     *  @param pt          ...
     */
    def inferConstructorInstance(tree: Tree, undetparams: List[Symbol], pt: Type): unit = {
      var restpe = tree.tpe.finalResultType
      var tvars = undetparams map freshVar

      /** Compute type arguments for undetermined params and substitute them in given tree.
       */
      def computeArgs =
        try {
          val targs = solve(tvars, undetparams, undetparams map varianceInType(restpe), true)
          checkBounds(tree.pos, NoPrefix, NoSymbol, undetparams, targs, "inferred ")
          new TreeTypeSubstituter(undetparams, targs).traverse(tree)
        } catch {
          case ex: NoInstance =>
            errorTree(tree, "constructor of type " + restpe +
                      " can be instantiated in more than one way to expected type " + pt +
                      "\n --- because ---\n" + ex.getMessage())
        }
      def instError = {
        if (settings.debug.value) Console.println("ici " + tree + " " + undetparams + " " + pt)
        if (settings.explaintypes.value) explainTypes(restpe.subst(undetparams, tvars), pt)
        errorTree(tree, "constructor cannot be instantiated to expected type" +
                  foundReqMsg(restpe, pt))
      }
      if (restpe.subst(undetparams, tvars) <:< pt) {
        computeArgs
      } else if (isFullyDefined(pt)) {
        if (settings.debug.value) log("infer constr " + tree + ":" + restpe + ", pt = " + pt)
        var ptparams = freeTypeParamsOfTerms.collect(pt)
        if (settings.debug.value) log("free type params = " + ptparams)
        val ptWithWildcards = pt.subst(ptparams, ptparams map (ptparam => WildcardType))
        tvars = undetparams map freshVar
        if (restpe.subst(undetparams, tvars) <:< ptWithWildcards) {
          computeArgs
          restpe = skipImplicit(tree.tpe.resultType)
          if (settings.debug.value) log("new tree = " + tree + ":" + restpe)
          val ptvars = ptparams map freshVar
          val pt1 = pt.subst(ptparams, ptvars)
          if (isPopulated(restpe, pt1)) {
            ptvars foreach instantiateTypeVar
          } else { if (settings.debug.value) Console.println("no instance: "); instError }
        } else { if (settings.debug.value) Console.println("not a subtype " + restpe.subst(undetparams, tvars) + " of " + ptWithWildcards); instError }
      } else { if (settings.debug.value) Console.println("not fuly defined: " + pt); instError }
    }

    def instantiateTypeVar(tvar: TypeVar) = {
      val tparam = tvar.origin.symbol
      if (false &&
          tvar.constr.inst != NoType &&
          isFullyDefined(tvar.constr.inst) &&
          (tparam.info.bounds containsType tvar.constr.inst)) {
        context.nextEnclosing(.tree.isInstanceOf[CaseDef]).pushTypeBounds(tparam)
        tparam setInfo tvar.constr.inst
        tparam resetFlag DEFERRED
        if (settings.debug.value) log("new alias of " + tparam + " = " + tparam.info)
      } else {
        val instType = toOrigin(tvar.constr.inst)
        val Pair(loBounds, hiBounds) =
          if (instType != NoType && isFullyDefined(instType)) Pair(List(instType), List(instType))
          else Pair(tvar.constr.lobounds, tvar.constr.hibounds)
        val lo = lub(tparam.info.bounds.lo :: loBounds map toOrigin)
        val hi = glb(tparam.info.bounds.hi :: hiBounds map toOrigin)
        if (!(lo <:< hi)) {
          if (settings.debug.value) log("inconsistent: "+tparam+" "+lo+" "+hi)
        } else if (!((lo <:< tparam.info.bounds.lo) && (tparam.info.bounds.hi <:< hi))) {
          context.nextEnclosing(.tree.isInstanceOf[CaseDef]).pushTypeBounds(tparam)
          tparam setInfo mkTypeBounds(lo, hi)
          if (settings.debug.value) log("new bounds of " + tparam + " = " + tparam.info)
        } else {
          if (settings.debug.value) log("redundant: "+tparam+" "+tparam.info+"/"+lo+" "+hi)
        }
      }
    }

    def checkCheckable(pos: PositionType, tp: Type): unit = {
      def patternWarning(tp: Type, prefix: String) =
        context.unit.uncheckedWarning(pos, prefix+tp+" in type pattern is unchecked since it is eliminated by erasure")
      def isLocalBinding(sym: Symbol) =
        sym.isAbstractType &&
        (sym.name == nme.WILDCARD.toTypeName || {
          val e = context.scope.lookupEntry(sym.name)
          (e ne null) && e.sym == sym && e.owner == context.scope
        })
      tp match {
        case SingleType(pre, _) =>
          checkCheckable(pos, pre)
        case TypeRef(pre, sym, args) =>
          if (sym.isAbstractType) patternWarning(tp, "abstract type ")
          else for (val arg <- args) {
            if (sym == ArrayClass) checkCheckable(pos, arg)
            else arg match {
              case TypeRef(_, sym, _) if isLocalBinding(sym) =>
                ;
              case _ =>
                patternWarning(arg, "non variable type-argument ")
            }
          }
          checkCheckable(pos, pre)
        case RefinedType(parents, decls) =>
          if (decls.isEmpty) for (val p <- parents) checkCheckable(pos, p)
          else patternWarning(tp, "refinement ")
        case ThisType(_) =>
          ;
        case NoPrefix =>
          ;
        case _ =>
          patternWarning(tp, "type ")
      }
    }

    /** Type intersection of simple type `tp1' with general type `tp2'
     *  The result eliminates some redundancies
     */
    def intersect(tp1: Type, tp2: Type): Type = {
      if (tp1 <:< tp2) tp1
      else if (tp2 <:< tp1) tp2
      else {
        val reduced2 = tp2 match {
          case rtp @ RefinedType(parents2, decls2) =>
            copyRefinedType(rtp, parents2 filter (p2 => !(tp1 <:< p2)), decls2)
          case _ =>
            tp2
        }
        intersectionType(List(tp1, reduced2))
      }
    }

    def inferTypedPattern(pos: PositionType, pattp: Type, pt: Type): Type = {
      checkCheckable(pos, pattp)
      if (!(pattp <:< pt)) {
        val tpparams = freeTypeParamsOfTerms.collect(pattp)
        if (settings.debug.value) log("free type params (1) = " + tpparams)
        var tvars = tpparams map freshVar
        var tp = pattp.subst(tpparams, tvars)
        if (!(tp <:< pt)) {
          tvars = tpparams map freshVar
          tp = pattp.subst(tpparams, tvars)
          val ptparams = freeTypeParamsOfTerms.collect(pt)
          if (settings.debug.value) log("free type params (2) = " + ptparams)
          val ptvars = ptparams map freshVar
          val pt1 = pt.subst(ptparams, ptvars)
          if (!isPopulated(tp, pt1)) {
            error(pos, "pattern type is incompatibe with expected type"+foundReqMsg(pattp, pt))
            return pattp
          }
          ptvars foreach instantiateTypeVar
        }
        tvars foreach instantiateTypeVar
      }
      intersect(pt, pattp)
    }

    def inferModulePattern(pat: Tree, pt: Type) =
      if (!(pat.tpe <:< pt)) {
        val ptparams = freeTypeParamsOfTerms.collect(pt)
        if (settings.debug.value) log("free type params (2) = " + ptparams)
        val ptvars = ptparams map freshVar
        val pt1 = pt.subst(ptparams, ptvars)
        if (pat.tpe <:< pt1)
          ptvars foreach instantiateTypeVar
        else
          error(pat.pos, "pattern type is incompatibe with expected type"+foundReqMsg(pat.tpe, pt))
      }

    object toOrigin extends TypeMap {
      def apply(tp: Type): Type = tp match {
        case TypeVar(origin, _) => origin
        case _ => mapOver(tp)
      }
    }

    abstract class SymCollector extends TypeTraverser {
      private var result: List[Symbol] = _
      protected def includeCondition(sym: Symbol): boolean

      override def traverse(tp: Type): TypeTraverser = {
        tp match {
          case TypeRef(_, sym, _) =>
            if (includeCondition(sym) && !result.contains(sym)) result = sym :: result
          case _ =>
        }
        mapOver(tp)
        this
      }

      /** Collect all abstract type symbols referred to by type <code>tp</code>.
       *
       *  @param tp ...
       *  @return   ...
       */
      def collect(tp: Type): List[Symbol] = {
        result = List()
        traverse(tp)
        result
      }
    }

    object approximateAbstracts extends TypeMap {
      def apply(tp: Type): Type = tp match {
        case TypeRef(pre, sym, _) if sym.isAbstractType => WildcardType
        case _ => mapOver(tp)
      }
    }

    /** A traverser to collect type parameters referred to in a type
     */
    object freeTypeParamsOfTerms extends SymCollector {
      protected def includeCondition(sym: Symbol): boolean = sym.isAbstractType && sym.owner.isTerm
    }

    object typeRefs extends SymCollector {
      protected def includeCondition(sym: Symbol): boolean = true
    }

    /* -- Overload Resolution ---------------------------------------------- */

    def checkNotShadowed(pos: PositionType, pre: Type, best: Symbol, eligible: List[Symbol]) =
      if (!phase.erasedTypes)
        for (val alt <- eligible) {
          if (alt.owner != best.owner && alt.owner.isSubClass(best.owner))
            error(pos,
                  "erroneous reference to overloaded definition,\n"+
                  "most specific definition is: "+best+best.locationString+" of type "+pre.memberType(best)+
                  ",\nyet alternative definition   "+alt+alt.locationString+" of type "+pre.memberType(alt)+
                  "\nis defined in a subclass")
        }

    /** Assign <code>tree</code> the symbol and type of the alternative which
     *  matches prototype <code>pt</code>, if it exists.
     *  If several alternatives match `pt', take parameterless one.
     *  If no alternative matches `pt', take the parameterless one anyway.
     */
    def inferExprAlternative(tree: Tree, pt: Type): unit = tree.tpe match {
      case OverloadedType(pre, alts) => tryTwice {
        var alts1 = alts filter (alt => isCompatible(pre.memberType(alt), pt))
        if (alts1.isEmpty) alts1 = alts
        def improves(sym1: Symbol, sym2: Symbol): boolean =
          sym2 == NoSymbol ||
          { val tp1 = pre.memberType(sym1)
            val tp2 = pre.memberType(sym2)
            (tp2 == ErrorType ||
             !global.typer.infer.isCompatible(tp2, pt) && global.typer.infer.isCompatible(tp1, pt) ||
             isStrictlyBetter(tp1, tp2)) }
        val best = ((NoSymbol: Symbol) /: alts1) ((best, alt) =>
          if (improves(alt, best)) alt else best)
        val competing = alts1 dropWhile (alt => best == alt || improves(best, alt))
        if (best == NoSymbol) {
          if (settings.debug.value) {
            tree match {
              case Select(qual, _) =>
                Console.println("qual: " + qual + ":" + qual.tpe +
                                   " with decls " + qual.tpe.decls +
                                   " with members " + qual.tpe.members +
                                   " with members " + qual.tpe.member(newTermName("$minus")))
              case _ =>
            }
          }
          typeErrorTree(tree, tree.symbol.tpe, pt)
        } else if (!competing.isEmpty) {
          if (!pt.isErroneous)
            context.ambiguousError(tree.pos, pre, best, competing.head, "expected type " + pt)
          setError(tree)
          ()

        } else {
          val applicable = alts1 filter (alt =>
            global.typer.infer.isCompatible(pre.memberType(alt), pt))
          checkNotShadowed(tree.pos, pre, best, applicable)
          tree.setSymbol(best).setType(pre.memberType(best))
        }
      }
    }

    /** Assign <code>tree</code> the type of an alternative which is applicable
     *  to <code>argtpes</code>, and whose result type is compatible with `pt'.
     *  If several applicable alternatives exist, take the
     *  most specialized one.
     *  If no applicable alternative exists, and pt != WildcardType, try again
     *  with pt = WildcardType.
     *  Otherwise, if there is no best alternative, error.
     */
    def inferMethodAlternative(tree: Tree, undetparams: List[Symbol], argtpes: List[Type], pt: Type): unit = tree.tpe match {
      case OverloadedType(pre, alts) => tryTwice {
        if (settings.debug.value) log("infer method alt " + tree.symbol + " with alternatives " + (alts map pre.memberType) + ", argtpes = " + argtpes + ", pt = " + pt)
        val applicable = alts filter (alt => isApplicable(undetparams, pre.memberType(alt), argtpes, pt))
        def improves(sym1: Symbol, sym2: Symbol) = (
          sym2 == NoSymbol || sym2.isError ||
          specializes(pre.memberType(sym1), pre.memberType(sym2))
        )
        val best = ((NoSymbol: Symbol) /: applicable) ((best, alt) =>
          if (improves(alt, best)) alt else best)
        val competing = applicable dropWhile (alt => best == alt || improves(best, alt))
        if (best == NoSymbol) {
          if (pt == WildcardType) {
            errorTree(tree, applyErrorMsg(tree, " cannot be applied to ", argtpes, pt))
          } else {
            inferMethodAlternative(tree, undetparams, argtpes, WildcardType)
          }
        } else if (!competing.isEmpty) {
          if (!(argtpes exists (.isErroneous)) && !pt.isErroneous)
            context.ambiguousError(tree.pos, pre, best, competing.head,
                                   "argument types " + argtpes.mkString("(", ",", ")") +
                                   (if (pt == WildcardType) "" else " and expected result type " + pt))
          setError(tree)
          ()
        } else {
          checkNotShadowed(tree.pos, pre, best, applicable)
          tree.setSymbol(best).setType(pre.memberType(best))
        }
      }
    }

    /** Try inference twice, once without views and once with views,
     *  unless views are already disabled.
     *
     *  @param infer ...
     */
    def tryTwice(infer: => unit): unit = {
      if (context.implicitsEnabled) {
        val reportGeneralErrors = context.reportGeneralErrors
        context.reportGeneralErrors = false
        context.implicitsEnabled = false
        try {
          infer
        } catch {
          case ex: TypeError =>
            context.reportGeneralErrors = reportGeneralErrors
            context.implicitsEnabled = true
            infer
        }
        context.reportGeneralErrors = reportGeneralErrors
        context.implicitsEnabled = true
      } else infer
    }

    /** Assign <code>tree</code> the type of unique polymorphic alternative
     *  with <code>nparams</code> as the number of type parameters, if it exists.
     *  If several or none such polymorphic alternatives exist, error.
     *
     *  @param tree ...
     *  @param nparams ...
     */
    def inferPolyAlternatives(tree: Tree, argtypes: List[Type]): unit = tree.tpe match {
      case OverloadedType(pre, alts) =>
        val sym0 = tree.symbol filter { alt => alt.typeParams.length == argtypes.length }
        if (sym0 == NoSymbol) {
          error(
            tree.pos,
            if (alts exists (alt => alt.typeParams.length > 0))
              "wrong number of type parameters for " + treeSymTypeMsg(tree)
            else treeSymTypeMsg(tree) + " does not take type parameters")
          return
        }
        val sym = sym0 filter { alt => isWithinBounds(pre, alt.owner, alt.typeParams, argtypes) }
        if (sym == NoSymbol) {
          if (!(argtypes exists (.isErroneous))) {
            Console.println(":"+sym0.alternatives.map(
              alt => alt.typeParams.map(
                p => p.info.asSeenFrom(pre, alt.owner))))
            error(
              tree.pos,
              "type arguments " + argtypes.mkString("[", ",", "]") +
              " conform to the bounds of none of the overloaded alternatives of\n "+sym0+
              ": "+sym0.info)
            return
          }
        }
        if (sym.hasFlag(OVERLOADED)) {
          val tparams = new AsSeenFromMap(pre, sym.alternatives.head.owner).mapOver(
            sym.alternatives.head.typeParams)
          val bounds = tparams map (.tpe)
          val tpe =
            PolyType(tparams,
                     OverloadedType(AntiPolyType(pre, bounds), sym.alternatives))
          sym.setInfo(tpe)
          tree.setSymbol(sym).setType(tpe)
        } else {
          tree.setSymbol(sym).setType(pre.memberType(sym))
        }
    }
  }
}