aboutsummaryrefslogblamecommitdiff
path: root/compiler/src/dotty/tools/dotc/core/SymDenotations.scala
blob: 1e0beb5f30bd96e66195ae0a5ae7cc5bd79d86d3 (plain) (tree)
1
2
3
4
5
6
7
8
9
10

                   

            
                                                                                         
                                                                                            
                             


                                  

                                         
            
                         
                        
                     
                 
                    
                                                            
 
                                       










                                                            

                                                                                   
                         

                                                                                                                                    



                                                                                         
 
                                                 
                                                                                 

                                 
                                                                             






                                                                         







                                                                                      
                          




                                                                          












                                                                                                
                                 

                                                                                   
                                                                              





                                                                                                                                               


                                                                 


                                                    
     
   
 
 

                       
                                                              

                      
                                               
                   
                          
                   
                       
                   
                                                                            
 

                                     

                                               

                                          


                         
                                                              
 
                                                                      
 
                                       



                                                                 
 





                                                                         
                                                              
                                     
 


                                                              
                       
                                                                                    
 



                                                       

                                                                  
                                                                                                 
 
                              
                                             
                                 

                                                
                                                                  
 
                                                  
                                                                     
 
                                                                                          
                                                       


                                                                     
 




                                                             
                                                            
                                                        
                                                   
     



                                                                                   
                                                                       
                                                                                  

                                                            
                                                              
                                                   



                                                                                   
                                                                               
                                                                                  
 

                                                                         
                                                         
       
                                                                

                                                         

     


                                                                           





                                                         
                                                                                  



                                                                                                 
                                                         
                        
 
                                                               
                                                                        
             


                                                                            
       




                                                                           
                                                              

     
                                            

                                                           
                                                                                                                  
                  


                                                                                        

                   
          
                                                          
                 
     
 


                                                                              

                               
                                              
                                                          
                                       
 

                                                                     
                                                                                                   

                             
                                                                  
                           

                                             
                                                                      
                                      
     
 
                                                    
                                                                           
                            

                                                                                   

                                                                 
 
                                                                    
                                                                                              
                                              
 



                                                                                        
                                                                     
                                                                                     
                                                    
                                      


                        








                                                                                          
                                                                     
                                                      
                                          
 



                                                                          





                                                                                  


                                                                                                
 
            
                                                                                                                                 



                                                                                        
                                                                                                  








                                                                                  
                                                                   

                                                    
                                                                                 
                                                                       


                                                                                              


                                                                                                
       
                                                                          


                                                
                                                                    
                          
     
 


                                                                          
                                                                         
       

                                                                                                     
                                              

     
                                                                  
 

                                                   
                                                      


                                                                                                  
                                                  
       


                                                                                                    
                                                              

                                                   
 
                                                                                        
                                             
                                                                         
                                                                                       




                                                                                          
       
                                                                                 


                                  
                                                          
            
                       


                                                        
                       
         




                                                                                             
                                                                                  



                                                                          
                                                    
       
 
 
                                                                                                                
                                                                           
 
                                                          
                                                                                
 
                                                                    




                                                  
                                                              
 


                                                                        


                                                                      


                                                                

                                    
                     
 
                                        


                                                                     
 
                                                                 
                               
                                                                                 
 
                                                                          

                                                              
 
                                                                          
                                                                               
 
                                             
                                                                
                                                         
 
                                                          
                                                                      
 
                                                           
                                                                           
 








                                                                        







                                                                                                      
                                             

                                                                                       
 
                                                     

                                                                                              
 


                                                                                   



                                                                           


                                                                 
                                                               
                                                           



                                                           
     
 
                                           
                                                                                  
 
                                        
                                                                                               

                                                    
                                                       
 
















                                                                                






                                                                                 
                                                                            


                             
 


                                                                                       
                                                                   
                                               
                                                                               
 
                                                                               
                                                             
                                                                 
 
                                                                                            
                                                                    
                                                     
                                               


                                                                    






                                                                                                        

       
                                                                        
                                               
                                                                                 
 



                                                                    
                                

                                                   


                                                  
 
                            

                                                                                           
 
                            


                                               
                                                                                                        
 


                                                   
                                              
                                                          

                                              
                                                                    

                                                        
                                                    
 
                                           
                                                           
 

                                                                                  
                                                         
 
                                                                                 


                                                          


                                                               

                                                                           

                                                                             
       
                                                                
 

                                                              
                      




                                                                                      
 

                                                                                  
                                                                                       
 


                                                                                 

                                                                           
       
                                                                                                                                        

                                                    



                                                                               
 





                                                                    
                                                                                       

                                                                   
                                                             

                                                                                 



                                         



                                                            
                                             
                                               



                                         
               


                                                                                                                  
                 
                                                                                     
                                                                            
                           
                                                                                   
             
               


                                                                                                       


                 


                                    

                                            

                          














                                                                                          



                                                                      

                            
                         
                                                

        



                                                                    

                                                                         






                                                                        
 








                                                                               
                                                                                           
                                              
 
                                                                                            
 
                                                                         
 









                                                                                   
                                                                          
                                                            
                                                                                      

                            


                                                                                                                       





                                               
         
                   
     

                                                                                   
                                                                          




                                                                             
                            
                         


                
 

                                                                                           
                                                                        



                                                            

     






                                                                       










                                                                                           


                                                                             
 

                                                                            


                                                            


                                                                    
                                                                                       
                              


                                                                                                 
       
                                                               









                                                                   
     
 


                                                                       
 

                                                                                 
                                                                                                       
 
                                                                                   

                                                                                
                                                                                                

     



                                                                              
                                                  
                                               

                                                 
 


                                                                         
                                                              
                                                
                                                                                           


                              


                                               
                                                       

                                                                       




                                                                                   
                                                                







                                                                                                      

     

                                                                            


                                                                          








                                                                                                     


                                                                       
                                                                                                   

                   




                                                                                
                                                                                    


















                                                                                     
 



                                                                         



                                                                     
                                                          
                                             





                                                                               

                                                               
 
                                                                                  
                           
                                                                            
                                                                           



                                                                       
       
                                                                                          
                                                   

                                                                       


                  








                                                                                            



                                                                         






                                                                               
 

                                                                                     
                                                                   
                                                


                                                                             


                                                   
                                                                           





                                                                                       
 




                                                                                     
                                                                           

                   




                                                                            
                                                                     
                          
                                                         







                                                            
                                                 



                                                                     
                                                                                     





                                                             







                                                                              
                              





                                                                            


                                                                                   
                                                                          




                                                                                      
                                                        
 
                                                          
                                                    
 
                                                          
                                                    
 
                                                         
                                                                                          
 

                                                                               
 
                                                          
                                                                          
 
                                                                          

                                                                                   
                                                    



                                        




                                                                       

                             
                                                  

                                 

                                            



                          

                                           
                                                             
 
                                                  


                                                                                 
                                               

                                                                   
                                                 
                                                                            
                                                                                       
                                                                    
                                                  






                                                                                  
                                                                            
 
                                                                                                             
 
                                                            
                                


                                   




                                                                                                   
                                                                                             




                                                                                           

       
 

                                                                       


                                                                                     





                                                                                                                          
 
                                                                                             

                                                 
                                                                                 
               

   
                                                        
     

                                                 
                          
                   

                       

                              
                                                                                                    
 
                        
 
                                                                           
 
                                                
                                                                                           
 

                                                                   
 
                                                   
                                                                                  
 
                                                               
                                                        
 
                                                                                  
                                                                         
                                                                                              





                                                                                 
                                            
                                                                              


                                                                                                           






                                                                                
           
                  

     




                                                                                         


                                                                         


                   








                                                                         

                                                                                        
                                                                                  

                                 




                                                                    

                                                                          

                                                     
                                                                              
     
 
                                                                            
 
                                             
 

                                                                            
       







                                                                                               
       








                                                                                                     
       
                            



                                                                                          
                                                    



                                               
                                   
                                        
     

                                                                          
 
                                             
 




                                                                                    
                                                          

                                                          

     
                                                              


                                                                                  
                                



                                                                                
       
  
                                               
 
                                                            

                                                      

     

                                                             
 
                                                                                 
                                                             

                                                                  
                            
                               
                                    

       
                                                                                    
                                                           
                         




                                                                       
                                                  
                             
                                         
                
                      
                           
           
                   



                                                                                                     
                                                                      
                   

            







                                                                      

     
                                                                   


                                                                                      
                            
                                                                           
       
 


                                                              


                                                                                                
                            
                                                                     
       
 
                                                                                  
                  





                                               
 
                                                                        
                          


                                                                      
 

                                                                           
                                                                            
 

                                                                                
                                  
                         
                          

                  
                           


                                       


                                                                         



                    
        

     




                                                                  






                                                                         
 
                                                                         
                                                           
 




                                                                                     
                   
     
 


                                                                                                            
                                                                              

                                                                       

                                                                   
       
                                                                                      
                                
                                   



                                                                                   
                                                                    
               
                                                
       




                                                           
         
       

     
                                                                                      
                                                                                         
                                                                                  




                                                     
                                            
                                                                                  
 
                      
 
                                                     
                                             
                                
                                         

     





                                                                                    
                                                               



                                                 





                                                                       
                                             

                                                                  

     
                                                                             
                                                                                             
       


                                                                                            

                              
                                                                          
                                                                        
                                                         

                           
     
 



                                                           
                                                                                
                                                                





                                                                          
                                                                                           
       
                                                                                                                      
                                            
                                     

                                                           
                                                         
                                                               
                                                   
                                                              
                                                                                                                                          

              
                                                   
     
 

                                                                                                                                                                          

                                              
                                                               
                         
                                                                      

                                                                 

                                                                                                   

                                             
                                              
                             
                                                                        
                                                               
                       
                       
             
                     
                  
         

                                             
                         
     
 



                                                                                                                  
 

                                                                                  
 

                                                                      
 
                                                              
                                                            


                    

                                                              






                                                                          

                                                    
                                                    
                                                     
                                                              

                                                                


                      
                                                  
                                         


                                                      








                                                                                              
                                           

                               
                                       
                                   
                                                   
                                  
                                                   

                                                                


                   

       
                                                                         
                  
                                
                                
                                                
                                 
                                                


                                                                  
                                            
                                            
                                         


                   
                                    
         


       
                                                                                          
 

                                                                               



                                                                              




                                                           

                                               
       
                                                             
                                                                                 



                                               
                                        



                                                                        
               
         
       
     
 


                                                                                                  

                                

                                                       
          
       
     
 


                                                                       
                                                                      

                                                                                  
                                                                                             

                                                                                  
     
 



                                                                       
                                                     
 

                                                                                   
       







                                                                                               
       
   
 


                                                                                              
                                                              




                          


                                                                                                             













                                                                                                      


                                                                                           


                                                                                       



















                                                                                                              
       








                                                                                        














                                                                                                        

   
                                           
                                                                 
                               

                               
                                                                               
                                                                                             
                                                                                         
                                                                                

   
                                               
 
                                                                             
 



                                                                                 
                              


                                                    
                                                          
 
                                                      
                                                                   
 

                                                             
 
                                           

                                                                
 


                                                                   
                                        
                                                                                               
     
 
                              

                                                                           

                                                                      

                                                                                                                    
   
 


                                                                                     
                                              
                                                                                       
                                                                                 

   
                                             
 
                            
                                                
                                                                                             
   
 

                                        
                                                              



                                                                          

                                                                     
                                                                       
                                          
                                                                    
                                                                     



                                                                                   
                                      
                                              
     

   
                                           
                                     
 
                                                                                                



                                                                             
                               
       
                                    

     
                                                                       
                            
                                   


                                                       
                                                                                           
                  


                                                                                                          

                                                                                             
                                      
                                         


     
                                                                            
 




                                                                    
 


                                                      
                                               

     


                                                         
 


                                                    
                                                     
     
   
 

                                                            
                                       



                                                       
   

                                                
 
                                                              
 
package dotty.tools
package dotc
package core

import Periods._, Contexts._, Symbols._, Denotations._, Names._, NameOps._, Annotations._
import Types._, Flags._, Decorators._, DenotTransformers._, StdNames._, Scopes._, Comments._
import NameOps._, NameKinds._
import Scopes.Scope
import collection.mutable
import collection.immutable.BitSet
import scala.reflect.io.AbstractFile
import Decorators.SymbolIteratorDecorator
import ast._
import annotation.tailrec
import CheckRealizable._
import util.SimpleMap
import util.Stats
import config.Config
import config.Printers.{completions, incremental, noPrinter}

trait SymDenotations { this: Context =>
  import SymDenotations._

  /** Factory method for SymDenotion creation. All creations
   *  should be done via this method.
   */
  def SymDenotation(
    symbol: Symbol,
    owner: Symbol,
    name: Name,
    initFlags: FlagSet,
    initInfo: Type,
    initPrivateWithin: Symbol = NoSymbol)(implicit ctx: Context): SymDenotation = {
    val result =
      if (symbol.isClass)
        if (initFlags is Package) new PackageClassDenotation(symbol, owner, name, initFlags, initInfo, initPrivateWithin, ctx.runId)
        else new ClassDenotation(symbol, owner, name, initFlags, initInfo, initPrivateWithin, ctx.runId)
      else new SymDenotation(symbol, owner, name, initFlags, initInfo, initPrivateWithin)
    result.validFor = stablePeriod
    result
  }

  def stillValid(denot: SymDenotation): Boolean =
    if (denot.is(ValidForever) || denot.isRefinementClass || denot.isImport) true
    else {
      val initial = denot.initial
      val firstPhaseId = initial.validFor.firstPhaseId.max(ctx.typerPhase.id)
     if ((initial ne denot) || ctx.phaseId != firstPhaseId) {
       ctx.withPhase(firstPhaseId).stillValidInOwner(initial) ||
         // Workaround #1895: A symbol might not be entered into an owner
         // until the second phase where it exists
         (denot.validFor.containsPhaseId(firstPhaseId + 1)) &&
           ctx.withPhase(firstPhaseId + 1).stillValidInOwner(initial)
      } else
        stillValidInOwner(denot)
    }

  private[SymDenotations] def stillValidInOwner(denot: SymDenotation): Boolean = try {
    val owner = denot.owner.denot
    stillValid(owner) && (
      !owner.isClass
      || owner.isRefinementClass
      || owner.is(Scala2x)
      || (owner.unforcedDecls.lookupAll(denot.name) contains denot.symbol)
      || denot.isSelfSym)
  } catch {
    case ex: StaleSymbol => false
  }

  /** Explain why symbol is invalid; used for debugging only */
  def traceInvalid(denot: Denotation): Boolean = {
    def show(d: Denotation) = s"$d#${d.symbol.id}"
    def explain(msg: String) = {
      println(s"${show(denot)} is invalid at ${this.period} because $msg")
      false
    }
    denot match {
      case denot: SymDenotation =>
        def explainSym(msg: String) = explain(s"$msg\n defined = ${denot.definedPeriodsString}")
        if (denot.is(ValidForever) || denot.isRefinementClass) true
        else {
          implicit val ctx = this
          val initial = denot.initial
          if ((initial ne denot) || ctx.phaseId != initial.validFor.firstPhaseId) {
            ctx.withPhase(initial.validFor.firstPhaseId).traceInvalid(initial)
          } else try {
            val owner = denot.owner.denot
            if (!traceInvalid(owner)) explainSym("owner is invalid")
            else if (!owner.isClass || owner.isRefinementClass || denot.isSelfSym) true
            else if (owner.unforcedDecls.lookupAll(denot.name) contains denot.symbol) true
            else explainSym(s"decls of ${show(owner)} are ${owner.unforcedDecls.lookupAll(denot.name).toList}, do not contain ${denot.symbol}")
          } catch {
            case ex: StaleSymbol => explainSym(s"$ex was thrown")
          }
      }
      case _ =>
        explain("denotation is not a SymDenotation")
    }
  }
}

object SymDenotations {

  /** A sym-denotation represents the contents of a definition
   *  during a period.
   */
  class SymDenotation private[SymDenotations] (
    symbol: Symbol,
    ownerIfExists: Symbol,
    initName: Name,
    initFlags: FlagSet,
    initInfo: Type,
    initPrivateWithin: Symbol = NoSymbol) extends SingleDenotation(symbol) {

    //assert(symbol.id != 4940, name)

    override def hasUniqueSym: Boolean = exists

    /** Debug only
    override def validFor_=(p: Period) = {
      super.validFor_=(p)
    }
    */
    if (Config.checkNoSkolemsInInfo) assertNoSkolems(initInfo)

    // ------ Getting and setting fields -----------------------------

    private[this] var myName = initName
    private[this] var myFlags: FlagSet = adaptFlags(initFlags)
    private[this] var myInfo: Type = initInfo
    private[this] var myPrivateWithin: Symbol = initPrivateWithin
    private[this] var myAnnotations: List[Annotation] = Nil

    /** The name of the symbol */
    def name = myName

    /** Update the name; only called when unpickling top-level classes */
    def name_=(n: Name) = myName = n

    /** The owner of the symbol; overridden in NoDenotation */
    def owner: Symbol = ownerIfExists

    /** Same as owner, except returns NoSymbol for NoSymbol */
    def maybeOwner: Symbol = if (exists) owner else NoSymbol

    /** The flag set */
    final def flags(implicit ctx: Context): FlagSet = { ensureCompleted(); myFlags }

    /** The flag set without forcing symbol completion.
     *  Should be used only for printing.
     */
    private[dotc] final def flagsUNSAFE = myFlags

    /** Adapt flag set to this denotation's term or type nature */
    private def adaptFlags(flags: FlagSet) = if (isType) flags.toTypeFlags else flags.toTermFlags

    /** Update the flag set */
    final def flags_=(flags: FlagSet): Unit =
      myFlags = adaptFlags(flags)

    /** Set given flags(s) of this denotation */
    final def setFlag(flags: FlagSet): Unit = { myFlags |= flags }

    /** Unset given flags(s) of this denotation */
    final def resetFlag(flags: FlagSet): Unit = { myFlags &~= flags }

    /** Set applicable flags from `flags` which is a subset of {NoInits, PureInterface} */
    final def setNoInitsFlags(flags: FlagSet): Unit = {
      val mask = if (myFlags.is(Trait)) NoInitsInterface else NoInits
      setFlag(flags & mask)
    }

    private def isCurrent(fs: FlagSet) =
      fs <= (
        if (myInfo.isInstanceOf[SymbolLoader]) FromStartFlags
        else AfterLoadFlags)

    /** Has this denotation one of the flags in `fs` set? */
    final def is(fs: FlagSet)(implicit ctx: Context) = {
      (if (isCurrent(fs)) myFlags else flags) is fs
    }

    /** Has this denotation one of the flags in `fs` set, whereas none of the flags
     *  in `butNot` are set?
     */
    final def is(fs: FlagSet, butNot: FlagSet)(implicit ctx: Context) =
      (if (isCurrent(fs) && isCurrent(butNot)) myFlags else flags) is (fs, butNot)

    /** Has this denotation all of the flags in `fs` set? */
    final def is(fs: FlagConjunction)(implicit ctx: Context) =
      (if (isCurrent(fs)) myFlags else flags) is fs

    /** Has this denotation all of the flags in `fs` set, whereas none of the flags
     *  in `butNot` are set?
     */
    final def is(fs: FlagConjunction, butNot: FlagSet)(implicit ctx: Context) =
      (if (isCurrent(fs) && isCurrent(butNot)) myFlags else flags) is (fs, butNot)

    /** The type info.
     *  The info is an instance of TypeType iff this is a type denotation
     *  Uncompleted denotations set myInfo to a LazyType.
     */
    final def info(implicit ctx: Context): Type = myInfo match {
      case myInfo: LazyType => completeFrom(myInfo); info
      case _ => myInfo
    }

    /** The type info, or, if symbol is not yet completed, the completer */
    final def infoOrCompleter = myInfo

    /** Optionally, the info if it is completed */
    final def unforcedInfo: Option[Type] = myInfo match {
      case myInfo: LazyType => None
      case _ => Some(myInfo)
    }

    private def completeFrom(completer: LazyType)(implicit ctx: Context): Unit = {
      if (completions ne noPrinter) {
        completions.println(i"${"  " * indent}completing ${if (isType) "type" else "val"} $name")
        indent += 1
      }
      if (myFlags is Touched) throw CyclicReference(this)
      myFlags |= Touched

      // completions.println(s"completing ${this.debugString}")
      try completer.complete(this)(ctx.withPhase(validFor.firstPhaseId))
      catch {
        case ex: CyclicReference =>
          completions.println(s"error while completing ${this.debugString}")
          throw ex
      }
      finally
        if (completions ne noPrinter) {
          indent -= 1
          completions.println(i"${"  " * indent}completed $name in $owner")
        }
      // completions.println(s"completed ${this.debugString}")
    }

    protected[dotc] def info_=(tp: Type) = {
      /* // DEBUG
       def illegal: String = s"illegal type for $this: $tp"
      if (this is Module) // make sure module invariants that allow moduleClass and sourceModule to work are kept.
        tp match {
          case tp: ClassInfo => assert(tp.selfInfo.isInstanceOf[TermRefBySym], illegal)
          case tp: NamedType => assert(tp.isInstanceOf[TypeRefBySym], illegal)
          case tp: ExprType => assert(tp.resultType.isInstanceOf[TypeRefBySym], illegal)
          case _ =>
        }
        */
      if (Config.checkNoSkolemsInInfo) assertNoSkolems(tp)
      myInfo = tp
    }

    /** The name, except
     *   - if this is a module class, strip the module class suffix
     *   - if this is a companion object with a clash-avoiding name, strip the
     *     "avoid clash" suffix
     */
    def effectiveName(implicit ctx: Context) =
      if (this is ModuleClass) name.stripModuleClassSuffix
      else name.exclude(AvoidClashName)

    /** The privateWithin boundary, NoSymbol if no boundary is given.
     */
    final def privateWithin(implicit ctx: Context): Symbol = { ensureCompleted(); myPrivateWithin }

    /** Set privateWithin. */
    protected[core] final def privateWithin_=(sym: Symbol): Unit =
      myPrivateWithin = sym

    /** The annotations of this denotation */
    final def annotations(implicit ctx: Context): List[Annotation] = {
      ensureCompleted(); myAnnotations
    }

    /** Update the annotations of this denotation */
    private[core] final def annotations_=(annots: List[Annotation]): Unit =
      myAnnotations = annots

    /** Does this denotation have an annotation matching the given class symbol? */
    final def hasAnnotation(cls: Symbol)(implicit ctx: Context) =
      dropOtherAnnotations(annotations, cls).nonEmpty

    /** Apply transform `f` to all annotations of this denotation */
    final def transformAnnotations(f: Annotation => Annotation)(implicit ctx: Context): Unit =
      annotations = annotations.mapConserve(f)

    /** Keep only those annotations that satisfy `p` */
    final def filterAnnotations(p: Annotation => Boolean)(implicit ctx: Context): Unit =
      annotations = annotations.filterConserve(p)

    /** Optionally, the annotation matching the given class symbol */
    final def getAnnotation(cls: Symbol)(implicit ctx: Context): Option[Annotation] =
      dropOtherAnnotations(annotations, cls) match {
        case annot :: _ => Some(annot)
        case nil => None
      }

    /** The same as getAnnotation, but without ensuring
     *  that the symbol carrying the annotation is completed
     */
    final def unforcedAnnotation(cls: Symbol)(implicit ctx: Context): Option[Annotation] =
      dropOtherAnnotations(myAnnotations, cls) match {
        case annot :: _ => Some(annot)
        case nil => None
      }

    /** Add given annotation to the annotations of this denotation */
    final def addAnnotation(annot: Annotation): Unit =
      annotations = annot :: myAnnotations

    /** Remove annotation with given class from this denotation */
    final def removeAnnotation(cls: Symbol)(implicit ctx: Context): Unit =
      annotations = myAnnotations.filterNot(_ matches cls)

    /** Remove any annotations with same class as `annot`, and add `annot` */
    final def updateAnnotation(annot: Annotation)(implicit ctx: Context): Unit = {
      removeAnnotation(annot.symbol)
      addAnnotation(annot)
    }

    /** Add all given annotations to this symbol */
    final def addAnnotations(annots: TraversableOnce[Annotation])(implicit ctx: Context): Unit =
      annots.foreach(addAnnotation)

    @tailrec
    private def dropOtherAnnotations(anns: List[Annotation], cls: Symbol)(implicit ctx: Context): List[Annotation] = anns match {
      case ann :: rest => if (ann matches cls) anns else dropOtherAnnotations(rest, cls)
      case Nil => Nil
    }

    /** The denotation is completed: info is not a lazy type and attributes have defined values */
    final def isCompleted: Boolean = !myInfo.isInstanceOf[LazyType]

    /** The denotation is in train of being completed */
    final def isCompleting: Boolean = (myFlags is Touched) && !isCompleted

    /** The completer of this denotation. @pre: Denotation is not yet completed */
    final def completer: LazyType = myInfo.asInstanceOf[LazyType]

    /** Make sure this denotation is completed */
    final def ensureCompleted()(implicit ctx: Context): Unit = info

    /** The symbols defined in this class or object.
     *  Careful! This does not force the type, so is compilation order dependent.
     *  This method should be used only in the following circumstances:
     *
     *  1. When accessing type parameters or type parameter accessors (both are entered before
     *     completion).
     *  2. When obtaining the current scope in order to enter, rename or delete something there.
     *  3. When playing it safe in order not to raise CylicReferences, e.g. for printing things
     *     or taking more efficient shortcuts (e.g. the stillValid test).
     */
    final def unforcedDecls(implicit ctx: Context): Scope = myInfo match {
      case cinfo: LazyType =>
        val knownDecls = cinfo.decls
        if (knownDecls ne EmptyScope) knownDecls
        else { completeFrom(cinfo); unforcedDecls } // complete-once
      case _ => info.decls
    }

    /** If this is a package class, the symbols entered in it
     *  before it is completed. (this is needed to eagerly enter synthetic
     *  aliases such as AnyRef into a package class without forcing it.
     *  Right now, the only usage is for the AnyRef alias in Definitions.
     */
    final private[core] def currentPackageDecls(implicit ctx: Context): MutableScope = myInfo match {
      case pinfo: SymbolLoaders # PackageLoader => pinfo.currentDecls
      case _ => unforcedDecls.openForMutations
    }

    // ------ Names ----------------------------------------------

    /** The expanded name of this denotation. */
    final def expandedName(implicit ctx: Context) =
      if (name.is(ExpandedName) || isConstructor) name
      else {
        def legalize(name: Name): Name = // JVM method names may not contain `<' or `>' characters
          if (is(Method)) name.replace('<', '(').replace('>', ')') else name
        legalize(name.expandedName(initial.owner))
      }
        // need to use initial owner to disambiguate, as multiple private symbols with the same name
        // might have been moved from different origins into the same class

    /** The name with which the denoting symbol was created */
    final def originalName(implicit ctx: Context) =
      initial.effectiveName

    /** The encoded full path name of this denotation, where outer names and inner names
     *  are separated by `separator` strings.
     *  Never translates expansions of operators back to operator symbol.
     *  Drops package objects. Represents each term in the owner chain by a simple `~`.
     *  (Note: scalac uses nothing to represent terms, which can cause name clashes
     *   between same-named definitions in different enclosing methods. Before this commit
     *   we used `$' but this can cause ambiguities with the class separator '$').
     *  A separator "" means "flat name"; the real separator in this case is "$" and
     *  enclosing packages do not form part of the name.
     */
    def fullNameSeparated(kind: QualifiedNameKind)(implicit ctx: Context): Name =
      if (symbol == NoSymbol ||
          owner == NoSymbol ||
          owner.isEffectiveRoot ||
          kind == FlatName && owner.is(PackageClass)) name
      else {
        var filler = ""
        var encl = owner
        while (!encl.isClass && !encl.isPackageObject) {
          encl = encl.owner
          filler += "~"
        }
        var prefix = encl.fullNameSeparated(kind)
        if (kind.separator == "$")
          // duplicate scalac's behavior: don't write a double '$$' for module class members.
          prefix = prefix.exclude(ModuleClassName)
        def qualify(n: SimpleTermName) =
          kind(prefix.toTermName, if (filler.isEmpty) n else termName(filler + n))
        val fn = name rewrite {
          case name: SimpleTermName => qualify(name)
          case name @ AnyQualifiedName(_, _) => qualify(name.toSimpleName)
        }
        if (isType) fn.toTypeName else fn.toTermName
      }


    /** The encoded flat name of this denotation, where joined names are separated by `separator` characters. */
    def flatName(implicit ctx: Context): Name = fullNameSeparated(FlatName)

    /** `fullName` where `.' is the separator character */
    def fullName(implicit ctx: Context): Name = fullNameSeparated(QualifiedName)

    // ----- Tests -------------------------------------------------

    /** Is this denotation a type? */
    override def isType: Boolean = name.isTypeName

    /** Is this denotation a class? */
    final def isClass: Boolean = isInstanceOf[ClassDenotation]

    /** Is this denotation a non-trait class? */
    final def isRealClass(implicit ctx: Context) = isClass && !is(Trait)

    /** Cast to class denotation */
    final def asClass: ClassDenotation = asInstanceOf[ClassDenotation]

    /** is this symbol the result of an erroneous definition? */
    def isError: Boolean = false

    /** Make denotation not exist */
    final def markAbsent(): Unit =
      myInfo = NoType

    /** Is symbol known to not exist? */
    final def isAbsent(implicit ctx: Context): Boolean =
      myInfo == NoType ||
      (this is (ModuleVal, butNot = Package)) && moduleClass.isAbsent

    /** Is this symbol the root class or its companion object? */
    final def isRoot: Boolean =
      (name.toTermName == nme.ROOT || name == nme.ROOTPKG) && (owner eq NoSymbol)

    /** Is this symbol the empty package class or its companion object? */
    final def isEmptyPackage(implicit ctx: Context): Boolean =
      name.toTermName == nme.EMPTY_PACKAGE && owner.isRoot

    /** Is this symbol the empty package class or its companion object? */
    final def isEffectiveRoot(implicit ctx: Context) = isRoot || isEmptyPackage

    /** Is this symbol an anonymous class? */
    final def isAnonymousClass(implicit ctx: Context): Boolean =
      isClass && (initial.name startsWith str.ANON_CLASS)

    final def isAnonymousFunction(implicit ctx: Context) =
      this.symbol.is(Method) && (initial.name startsWith str.ANON_FUN)

    final def isAnonymousModuleVal(implicit ctx: Context) =
      this.symbol.is(ModuleVal) && (initial.name startsWith str.ANON_CLASS)

    /** Is this a companion class method or companion object method?
     *  These methods are generated by Symbols#synthesizeCompanionMethod
     *  and used in SymDenotations#companionClass and
     *  SymDenotations#companionModule .
     */
    final def isCompanionMethod(implicit ctx: Context) =
      name.toTermName == nme.COMPANION_CLASS_METHOD ||
      name.toTermName == nme.COMPANION_MODULE_METHOD

    /** Is this a syntetic method that represents conversions between representations of a value class
      *  These methods are generated in ExtensionMethods
      *  and used in ElimErasedValueType.
      */
    final def isValueClassConvertMethod(implicit ctx: Context) =
      name.toTermName == nme.U2EVT ||
      name.toTermName == nme.EVT2U

    /** Is symbol a primitive value class? */
    def isPrimitiveValueClass(implicit ctx: Context) =
      maybeOwner == defn.ScalaPackageClass && defn.ScalaValueClasses().contains(symbol)

    /** Is symbol a primitive numeric value class? */
    def isNumericValueClass(implicit ctx: Context) =
      maybeOwner == defn.ScalaPackageClass && defn.ScalaNumericValueClasses().contains(symbol)

    /** Is symbol a phantom class for which no runtime representation exists? */
    def isPhantomClass(implicit ctx: Context) = defn.PhantomClasses contains symbol

    /** Is this symbol a class representing a refinement? These classes
     *  are used only temporarily in Typer and Unpickler as an intermediate
     *  step for creating Refinement types.
     */
    final def isRefinementClass(implicit ctx: Context): Boolean =
      name.decode == tpnme.REFINE_CLASS

    /** Is this symbol a package object or its module class? */
    def isPackageObject(implicit ctx: Context): Boolean = {
      val nameMatches =
        if (isType) name == tpnme.PACKAGE.moduleClassName
        else name == nme.PACKAGE
      nameMatches && (owner is Package) && (this is Module)
    }

    /** Is this symbol an abstract type? */
    final def isAbstractType(implicit ctx: Context) = isType && (this is Deferred)

    /** Is this symbol an alias type? */
    final def isAliasType(implicit ctx: Context) = isAbstractOrAliasType && !(this is Deferred)

    /** Is this symbol an abstract or alias type? */
    final def isAbstractOrAliasType = isType & !isClass

    /** Is this the denotation of a self symbol of some class?
     *  This is the case if one of two conditions holds:
     *  1. It is the symbol referred to in the selfInfo part of the ClassInfo
     *     which is the type of this symbol's owner.
     *  2. This symbol is owned by a class, it's selfInfo field refers to a type
     *     (indicating the self definition does not introduce a name), and the
     *     symbol's name is "_".
     *  TODO: Find a more robust way to characterize self symbols, maybe by
     *       spending a Flag on them?
     */
    final def isSelfSym(implicit ctx: Context) = owner.infoOrCompleter match {
      case ClassInfo(_, _, _, _, selfInfo) =>
        selfInfo == symbol ||
          selfInfo.isInstanceOf[Type] && name == nme.WILDCARD
      case _ => false
    }

    /** Is this definition contained in `boundary`?
     *  Same as `ownersIterator contains boundary` but more efficient.
     */
    final def isContainedIn(boundary: Symbol)(implicit ctx: Context): Boolean = {
      def recur(sym: Symbol): Boolean =
        if (sym eq boundary) true
        else if (sym eq NoSymbol) false
        else if ((sym is PackageClass) && !(boundary is PackageClass)) false
        else recur(sym.owner)
      recur(symbol)
    }

    final def isProperlyContainedIn(boundary: Symbol)(implicit ctx: Context): Boolean =
      symbol != boundary && isContainedIn(boundary)

    /** Is this denotation static (i.e. with no outer instance)? */
    final def isStatic(implicit ctx: Context) =
      (this is JavaStatic) || this.exists && owner.isStaticOwner || this.isRoot

    /** Is this a package class or module class that defines static symbols? */
    final def isStaticOwner(implicit ctx: Context): Boolean =
      (this is PackageClass) || (this is ModuleClass) && isStatic

    /** Is this denotation defined in the same scope and compilation unit as that symbol? */
    final def isCoDefinedWith(that: Symbol)(implicit ctx: Context) =
      (this.effectiveOwner == that.effectiveOwner) &&
      (  !(this.effectiveOwner is PackageClass)
        || this.isAbsent || that.isAbsent
        || { // check if they are defined in the same file(or a jar)
           val thisFile = this.symbol.associatedFile
           val thatFile = that.symbol.associatedFile
           (  thisFile == null
           || thatFile == null
           || thisFile.path == thatFile.path // Cheap possibly wrong check, then expensive normalization
           || thisFile.canonicalPath == thatFile.canonicalPath
           )
         }
      )

    /** Is this a denotation of a stable term (or an arbitrary type)? */
    final def isStable(implicit ctx: Context) =
      isType || is(Stable) || !(is(UnstableValue) || info.isInstanceOf[ExprType])

    /** Is this a "real" method? A real method is a method which is:
     *  - not an accessor
     *  - not a label
     *  - not an anonymous function
     *  - not a companion method
     */
    final def isRealMethod(implicit ctx: Context) =
      this.is(Method, butNot = AccessorOrLabel) &&
        !isAnonymousFunction &&
        !isCompanionMethod

    /** Is this a getter? */
    final def isGetter(implicit ctx: Context) =
      (this is Accessor) && !originalName.isSetterName && !originalName.isScala2LocalSuffix

    /** Is this a setter? */
    final def isSetter(implicit ctx: Context) =
      (this is Accessor) &&
      originalName.isSetterName &&
      (!isCompleted || info.firstParamTypes.nonEmpty) // to avoid being fooled by   var x_= : Unit = ...

    /** is this a symbol representing an import? */
    final def isImport = name == nme.IMPORT

    /** is this the constructor of a class? */
    final def isClassConstructor = name == nme.CONSTRUCTOR

    /** Is this the constructor of a trait? */
    final def isImplClassConstructor = name == nme.TRAIT_CONSTRUCTOR

    /** Is this the constructor of a trait or a class */
    final def isConstructor = name.isConstructorName

    /** Is this a local template dummmy? */
    final def isLocalDummy: Boolean = name.isLocalDummyName

    /** Does this symbol denote the primary constructor of its enclosing class? */
    final def isPrimaryConstructor(implicit ctx: Context) =
      isConstructor && owner.primaryConstructor == symbol

    /** Does this symbol denote the static constructor of its enclosing class? */
    final def isStaticConstructor(implicit ctx: Context) =
      name.isStaticConstructorName

    /** Is this a subclass of the given class `base`? */
    def isSubClass(base: Symbol)(implicit ctx: Context) = false

    /** Is this a subclass of `base`,
     *  and is the denoting symbol also different from `Null` or `Nothing`?
     *  @note  erroneous classes are assumed to derive from all other classes
     *         and all classes derive from them.
     */
    def derivesFrom(base: Symbol)(implicit ctx: Context) = false

    /** Is this symbol a class that extends `AnyVal`? */
    final def isValueClass(implicit ctx: Context): Boolean = {
      val di = initial
      di.isClass &&
      di.derivesFrom(defn.AnyValClass)(ctx.withPhase(di.validFor.firstPhaseId))
        // We call derivesFrom at the initial phase both because AnyVal does not exist
        // after Erasure and to avoid cyclic references caused by forcing denotations
    }

    /** Is this symbol a class references to which that are supertypes of null? */
    final def isNullableClass(implicit ctx: Context): Boolean =
      isClass && !isValueClass && !(this is ModuleClass) && symbol != defn.NothingClass

    /** Is this definition accessible as a member of tree with type `pre`?
     *  @param pre          The type of the tree from which the selection is made
     *  @param superAccess  Access is via super
     *  Everything is accessible if `pre` is `NoPrefix`.
     *  A symbol with type `NoType` is not accessible for any other prefix.
     */
    final def isAccessibleFrom(pre: Type, superAccess: Boolean = false, whyNot: StringBuffer = null)(implicit ctx: Context): Boolean = {

      /** Are we inside definition of `boundary`? */
      def accessWithin(boundary: Symbol) =
        ctx.owner.isContainedIn(boundary) &&
          (!(this is JavaDefined) || // disregard package nesting for Java
             ctx.owner.enclosingPackageClass == boundary.enclosingPackageClass)

      /** Are we within definition of linked class of `boundary`? */
      def accessWithinLinked(boundary: Symbol) = {
        val linked = boundary.linkedClass
        (linked ne NoSymbol) && accessWithin(linked)
      }

      /** Is `pre` the same as C.thisThis, where C is exactly the owner of this symbol,
       *  or, if this symbol is protected, a subclass of the owner?
       */
      def isCorrectThisType(pre: Type): Boolean = pre match {
        case pre: ThisType =>
          (pre.cls eq owner) || (this is Protected) && pre.cls.derivesFrom(owner)
        case pre: TermRef =>
          pre.symbol.moduleClass == owner
        case _ =>
          false
      }

      /** Is protected access to target symbol permitted? */
      def isProtectedAccessOK = {
        def fail(str: => String): Boolean = {
          if (whyNot != null) whyNot append str
          false
        }
        val cls = owner.enclosingSubClass
        if (!cls.exists)
          fail(
            i"""
               | Access to protected $this not permitted because enclosing ${ctx.owner.enclosingClass.showLocated}
               | is not a subclass of ${owner.showLocated} where target is defined""")
        else if (
          !(  isType // allow accesses to types from arbitrary subclasses fixes #4737
           || pre.baseTypeRef(cls).exists // ??? why not use derivesFrom ???
           || isConstructor
           || (owner is ModuleClass) // don't perform this check for static members
           ))
          fail(
            i"""
               | Access to protected ${symbol.show} not permitted because prefix type ${pre.widen.show}
               | does not conform to ${cls.showLocated} where the access takes place""")
        else true
      }

      if (pre eq NoPrefix) true
      else if (info eq NoType) false
      else {
        val boundary = accessBoundary(owner)

        (  boundary.isTerm
        || boundary.isRoot
        || (accessWithin(boundary) || accessWithinLinked(boundary)) &&
             (  !(this is Local)
             || (owner is ImplClass) // allow private local accesses to impl class members
             || isCorrectThisType(pre)
             )
        || (this is Protected) &&
             (  superAccess
             || pre.isInstanceOf[ThisType]
             || ctx.phase.erasedTypes
             || isProtectedAccessOK
             )
        )
      }
    }

    /** Do members of this symbol need translation via asSeenFrom when
     *  accessed via prefix `pre`?
     */
    def membersNeedAsSeenFrom(pre: Type)(implicit ctx: Context) =
      !(  this.isTerm
       || this.isStaticOwner
       || ctx.erasedTypes
       || (pre eq NoPrefix) || (pre eq thisType)
       )

    /** Is this symbol concrete, or that symbol deferred? */
    def isAsConcrete(that: Symbol)(implicit ctx: Context): Boolean =
      !(this is Deferred) || (that is Deferred)

    /** Does this symbol have defined or inherited default parameters? */
    def hasDefaultParams(implicit ctx: Context): Boolean =
      if (this is HasDefaultParams) true
      else if (this is NoDefaultParams) false
      else {
        val result = allOverriddenSymbols exists (_.hasDefaultParams)
        setFlag(if (result) InheritedDefaultParams else NoDefaultParams)
        result
      }

    /** Symbol is an owner that would be skipped by effectiveOwner. Skipped are
     *   - package objects
     *   - labels
     *   - non-lazy valdefs
     */
    def isWeakOwner(implicit ctx: Context): Boolean =
      isPackageObject ||
      isTerm && !is(MethodOrLazy, butNot = Label) && !isLocalDummy

    //    def isOverridable: Boolean = !!! need to enforce that classes cannot be redefined
    def isSkolem: Boolean = name == nme.SKOLEM

    def isInlineMethod(implicit ctx: Context): Boolean = is(InlineMethod, butNot = Accessor)

    // ------ access to related symbols ---------------------------------

    /* Modules and module classes are represented as follows:
     *
     * object X extends Y { def f() }
     *
     * <module> lazy val X: X$ = new X$
     * <module> class X$ extends Y { this: X.type => def f() }
     *
     * During completion, references to moduleClass and sourceModules are stored in
     * the completers.
     */
    /** The class implementing this module, NoSymbol if not applicable. */
    final def moduleClass(implicit ctx: Context): Symbol = {
      def notFound = { println(s"missing module class for $name: $myInfo"); NoSymbol }
      if (this is ModuleVal)
        myInfo match {
          case info: TypeRef           => info.symbol
          case ExprType(info: TypeRef) => info.symbol // needed after uncurry, when module terms might be accessor defs
          case info: LazyType          => info.moduleClass
          case t: MethodType           =>
            t.resultType match {
              case info: TypeRef => info.symbol
              case _ => notFound
            }
          case _ => notFound
        }
      else NoSymbol
    }

    /** The module implemented by this module class, NoSymbol if not applicable. */
    final def sourceModule(implicit ctx: Context): Symbol = myInfo match {
      case ClassInfo(_, _, _, _, selfType) if this is ModuleClass =>
        selfType match {
          case selfType: TermRef => selfType.symbol
          case selfType: Symbol => selfType.info.asInstanceOf[TermRef].symbol
        }
      case info: LazyType =>
        info.sourceModule
      case _ =>
        NoSymbol
    }

    /** The field accessed by this getter or setter, or if it does not exist, the getter */
    def accessedFieldOrGetter(implicit ctx: Context): Symbol = {
      val fieldName = if (isSetter) name.asTermName.getterName else name
      val d = owner.info.decl(fieldName)
      val field = d.suchThat(!_.is(Method)).symbol
      def getter = d.suchThat(_.info.isParameterless).symbol
      field orElse getter
    }

    /** The field accessed by a getter or setter, or
     *  if it does not exists, the getter of a setter, or
     *  if that does not exist the symbol itself.
     */
    def underlyingSymbol(implicit ctx: Context): Symbol =
      if (is(Accessor)) accessedFieldOrGetter orElse symbol else symbol

    /** The chain of owners of this denotation, starting with the denoting symbol itself */
    final def ownersIterator(implicit ctx: Context) = new Iterator[Symbol] {
      private[this] var current = symbol
      def hasNext = current.exists
      def next: Symbol = {
        val result = current
        current = current.owner
        result
      }
    }

    /** If this is a weak owner, its owner, otherwise the denoting symbol. */
    final def skipWeakOwner(implicit ctx: Context): Symbol =
      if (isWeakOwner) owner.skipWeakOwner else symbol

    /** The owner, skipping package objects, labels and non-lazy valdefs. */
    final def effectiveOwner(implicit ctx: Context) = owner.skipWeakOwner

    /** The class containing this denotation.
     *  If this denotation is already a class, return itself
     *  Definitions flagged with InSuperCall are treated specially.
     *  Their enclosing class is not the lexically enclosing class,
     *  but in turn the enclosing class of the latter. This reflects
     *  the context created by `Context#superCallContext`, `Context#thisCallArgContext`
     *  for these definitions.
     *
     *  Note, that as packages have ClassSymbols, top level classes will have an `enclosingClass`
     *  with Package flag set.
     */
    final def enclosingClass(implicit ctx: Context): Symbol = {
      def enclClass(sym: Symbol, skip: Boolean): Symbol = {
        def newSkip = sym.is(InSuperCall) || sym.is(JavaStaticTerm)
        if (!sym.exists)
          NoSymbol
        else if (sym.isClass)
          if (skip) enclClass(sym.owner, newSkip) else sym
        else
          enclClass(sym.owner, skip || newSkip)
      }
      enclClass(symbol, false)
    }

    /** A class that in source code would be lexically enclosing */
    final def lexicallyEnclosingClass(implicit ctx: Context): Symbol =
      if (!exists || isClass) symbol else owner.lexicallyEnclosingClass

    /** A symbol is effectively final if it cannot be overridden in a subclass */
    final def isEffectivelyFinal(implicit ctx: Context): Boolean =
      is(PrivateOrFinalOrInline) || !owner.isClass || owner.is(ModuleOrFinal) || owner.isAnonymousClass

    /** The class containing this denotation which has the given effective name. */
    final def enclosingClassNamed(name: Name)(implicit ctx: Context): Symbol = {
      val cls = enclosingClass
      if (cls.effectiveName == name || !cls.exists) cls else cls.owner.enclosingClassNamed(name)
    }

    /** The closest enclosing method containing this definition.
     *  A local dummy owner is mapped to the primary constructor of the class.
     */
    final def enclosingMethod(implicit ctx: Context): Symbol =
      if (this is (Method, butNot = Label)) symbol
      else if (this.isClass) primaryConstructor
      else if (this.exists) owner.enclosingMethod
      else NoSymbol

    /** The top-level class containing this denotation,
     *  except for a toplevel module, where its module class is returned.
     */
    final def topLevelClass(implicit ctx: Context): Symbol = {
      def topLevel(d: SymDenotation): Symbol = {
        if (d.isEffectiveRoot || (d is PackageClass) || (d.owner is PackageClass)) d.symbol
        else topLevel(d.owner)
      }
      val sym = topLevel(this)
      if (sym.isClass) sym else sym.moduleClass
    }

    /** The package class containing this denotation */
    final def enclosingPackageClass(implicit ctx: Context): Symbol =
      if (this is PackageClass) symbol else owner.enclosingPackageClass

    /** The module object with the same (term-) name as this class or module class,
     *  and which is also defined in the same scope and compilation unit.
     *  NoSymbol if this module does not exist.
     */
    final def companionModule(implicit ctx: Context): Symbol = {
      if (this.flagsUNSAFE is Flags.Module) this.sourceModule
      else {
        val companionMethod = info.decls.denotsNamed(nme.COMPANION_MODULE_METHOD, selectPrivate).first
        if (companionMethod.exists)
          companionMethod.info.resultType.classSymbol.sourceModule
        else
          NoSymbol
      }
    }


    /** The class with the same (type-) name as this module or module class,
      *  and which is also defined in the same scope and compilation unit.
      *  NoSymbol if this class does not exist.
      */
    final def companionClass(implicit ctx: Context): Symbol =
      if (is(Package)) NoSymbol
      else {
        val companionMethod = info.decls.denotsNamed(nme.COMPANION_CLASS_METHOD, selectPrivate).first
        if (companionMethod.exists)
          companionMethod.info.resultType.classSymbol
        else
          NoSymbol
      }

    final def scalacLinkedClass(implicit ctx: Context): Symbol =
      if (this is ModuleClass) companionNamed(effectiveName.toTypeName)
      else if (this.isClass) companionNamed(effectiveName.moduleClassName).sourceModule.moduleClass
      else NoSymbol


    /** Find companion class symbol with given name, or NoSymbol if none exists.
     *  Three alternative strategies:
     *  1. If owner is a class, look in its members, otherwise
     *  2. If current compilation unit has a typed tree,
     *     determine the defining statement sequence and search its trees, otherwise
     *  3. If context has an enclosing scope which defines this symbol,
     *     lookup its companion in the same scope.
     */
    private def companionNamed(name: TypeName)(implicit ctx: Context): Symbol =
      if (owner.isClass)
        owner.info.decl(name).suchThat(_.isCoDefinedWith(symbol)).symbol
      else if (!owner.exists || ctx.compilationUnit == null)
        NoSymbol
      else if (!ctx.compilationUnit.tpdTree.isEmpty)
        tpd.definingStats(symbol).iterator
          .map(tpd.definedSym)
          .find(_.name == name)
          .getOrElse(NoSymbol)
      else if (ctx.scope == null)
        NoSymbol
      else if (ctx.scope.lookup(this.name) == symbol)
        ctx.scope.lookup(name)
      else
        companionNamed(name)(ctx.outersIterator.dropWhile(_.scope eq ctx.scope).next)

    /** Is this symbol the same or a linked class of `sym`? */
    final def isLinkedWith(sym: Symbol)(implicit ctx: Context): Boolean =
      (symbol eq sym) || (linkedClass eq sym)

    /** If this is a class, the module class of its companion object.
     *  If this is a module class, its companion class.
     *  NoSymbol otherwise.
     */
    final def linkedClass(implicit ctx: Context): Symbol =
      if (this is ModuleClass) companionClass
      else if (this.isClass) companionModule.moduleClass
      else NoSymbol

    /** The class that encloses the owner of the current context
     *  and that is a subclass of this class. NoSymbol if no such class exists.
     */
    final def enclosingSubClass(implicit ctx: Context) =
      ctx.owner.ownersIterator.findSymbol(_.isSubClass(symbol))

    /** The non-private symbol whose name and type matches the type of this symbol
     *  in the given class.
     *  @param inClass   The class containing the result symbol's definition
     *  @param site      The base type from which member types are computed
     *
     *  inClass <-- find denot.symbol      class C { <-- symbol is here
     *
     *                   site: Subtype of both inClass and C
     */
    final def matchingDecl(inClass: Symbol, site: Type)(implicit ctx: Context): Symbol = {
      var denot = inClass.info.nonPrivateDecl(name)
      if (denot.isTerm) // types of the same name always match
        denot = denot.matchingDenotation(site, site.memberInfo(symbol))
      denot.symbol
    }

    /** The non-private member of `site` whose name and type matches the type of this symbol
     */
    final def matchingMember(site: Type)(implicit ctx: Context): Symbol = {
      var denot = site.nonPrivateMember(name)
      if (denot.isTerm) // types of the same name always match
        denot = denot.matchingDenotation(site, site.memberInfo(symbol))
      denot.symbol
    }

    /** If false, this symbol cannot possibly participate in an override,
     *  either as overrider or overridee.
     */
    final def canMatchInheritedSymbols(implicit ctx: Context): Boolean =
      maybeOwner.isClass && memberCanMatchInheritedSymbols

    /** If false, this class member cannot possibly participate in an override,
     *  either as overrider or overridee.
     */
    final def memberCanMatchInheritedSymbols(implicit ctx: Context): Boolean =
      !isConstructor && !is(Private)

    /** The symbol, in class `inClass`, that is overridden by this denotation. */
    final def overriddenSymbol(inClass: ClassSymbol)(implicit ctx: Context): Symbol =
      if (!canMatchInheritedSymbols && (owner ne inClass)) NoSymbol
      else matchingDecl(inClass, owner.thisType)

    /** All symbols overriden by this denotation. */
    final def allOverriddenSymbols(implicit ctx: Context): Iterator[Symbol] =
      if (!canMatchInheritedSymbols) Iterator.empty
      else overriddenFromType(owner.info)

    /** Returns all matching symbols defined in parents of the selftype. */
    final def extendedOverriddenSymbols(implicit ctx: Context): Iterator[Symbol] =
      if (!canMatchInheritedSymbols) Iterator.empty
      else overriddenFromType(owner.asClass.classInfo.selfType)

    private def overriddenFromType(tp: Type)(implicit ctx: Context): Iterator[Symbol] =
      tp.baseClasses.tail.iterator map overriddenSymbol filter (_.exists)

    /** The symbol overriding this symbol in given subclass `ofclazz`.
     *
     *  @param ofclazz is a subclass of this symbol's owner
     */
    final def overridingSymbol(inClass: ClassSymbol)(implicit ctx: Context): Symbol =
      if (canMatchInheritedSymbols) matchingDecl(inClass, inClass.thisType)
      else NoSymbol

    /** The symbol accessed by a super in the definition of this symbol when
     *  seen from class `base`. This symbol is always concrete.
     *  pre: `this.owner` is in the base class sequence of `base`.
     */
    final def superSymbolIn(base: Symbol)(implicit ctx: Context): Symbol = {
      @tailrec def loop(bcs: List[ClassSymbol]): Symbol = bcs match {
        case bc :: bcs1 =>
          val sym = matchingDecl(bcs.head, base.thisType)
            .suchThat(alt => !(alt is Deferred)).symbol
          if (sym.exists) sym else loop(bcs.tail)
        case _ =>
          NoSymbol
      }
      loop(base.info.baseClasses.dropWhile(owner != _).tail)
    }

    /** A member of class `base` is incomplete if
     *  (1) it is declared deferred or
     *  (2) it is abstract override and its super symbol in `base` is
     *      nonexistent or incomplete.
     */
    @tailrec final def isIncompleteIn(base: Symbol)(implicit ctx: Context): Boolean =
      (this is Deferred) ||
      (this is AbsOverride) && {
        val supersym = superSymbolIn(base)
        supersym == NoSymbol || supersym.isIncompleteIn(base)
      }

    /** The class or term symbol up to which this symbol is accessible,
     *  or RootClass if it is public.  As java protected statics are
     *  otherwise completely inaccessible in scala, they are treated
     *  as public.
     *  @param base  The access boundary to assume if this symbol is protected
     */
    final def accessBoundary(base: Symbol)(implicit ctx: Context): Symbol = {
      val fs = flags
      if (fs is Private) owner
      else if (fs is StaticProtected) defn.RootClass
      else if (privateWithin.exists && !ctx.phase.erasedTypes) privateWithin
      else if (fs is Protected) base
      else defn.RootClass
    }

    /** The primary constructor of a class or trait, NoSymbol if not applicable. */
    def primaryConstructor(implicit ctx: Context): Symbol = NoSymbol

    // ----- type-related ------------------------------------------------

    /** The type parameters of a class symbol, Nil for all other symbols */
    def typeParams(implicit ctx: Context): List[TypeSymbol] = Nil

    /** The type This(cls), where cls is this class, NoPrefix for all other symbols */
    def thisType(implicit ctx: Context): Type = NoPrefix

    override def typeRef(implicit ctx: Context): TypeRef =
      TypeRef(owner.thisType, name.asTypeName, this)

    override def termRef(implicit ctx: Context): TermRef =
      TermRef(owner.thisType, name.asTermName, this)

    override def valRef(implicit ctx: Context): TermRef =
      TermRef.withSigAndDenot(owner.thisType, name.asTermName, Signature.NotAMethod, this)

    override def termRefWithSig(implicit ctx: Context): TermRef =
      TermRef.withSigAndDenot(owner.thisType, name.asTermName, signature, this)

    def nonMemberTermRef(implicit ctx: Context): TermRef =
      TermRef.withFixedSym(owner.thisType, name.asTermName, symbol.asTerm)

    /** The variance of this type parameter or type member as an Int, with
     *  +1 = Covariant, -1 = Contravariant, 0 = Nonvariant, or not a type parameter
     */
    final def variance(implicit ctx: Context): Int =
      if (this is Covariant) 1
      else if (this is Contravariant) -1
      else 0

    /** The flags to be used for a type parameter owned by this symbol.
     *  Overridden by ClassDenotation.
     */
    def typeParamCreationFlags: FlagSet = TypeParam

    override def toString = {
      val kindString =
        if (myFlags is ModuleClass) "module class"
        else if (isClass) "class"
        else if (isType) "type"
        else if (myFlags is Module) "module"
        else if (myFlags is Method) "method"
        else "val"
      s"$kindString $name"
    }

    // ----- Sanity checks and debugging */

    def debugString = toString + "#" + symbol.id // !!! DEBUG

    def hasSkolems(tp: Type): Boolean = tp match {
      case tp: SkolemType => true
      case tp: NamedType => hasSkolems(tp.prefix)
      case tp: RefinedType => hasSkolems(tp.parent) || hasSkolems(tp.refinedInfo)
      case tp: RecType => hasSkolems(tp.parent)
      case tp: TypeBounds => hasSkolems(tp.lo) || hasSkolems(tp.hi)
      case tp: TypeVar => hasSkolems(tp.inst)
      case tp: ExprType => hasSkolems(tp.resType)
      case tp: HKApply => hasSkolems(tp.tycon) || tp.args.exists(hasSkolems)
      case tp: LambdaType => tp.paramInfos.exists(hasSkolems) || hasSkolems(tp.resType)
      case tp: AndOrType => hasSkolems(tp.tp1) || hasSkolems(tp.tp2)
      case tp: AnnotatedType => hasSkolems(tp.tpe)
      case _ => false
    }

    def assertNoSkolems(tp: Type) =
      if (!this.isSkolem)
        assert(!hasSkolems(tp), s"assigning type $tp containing skolems to $this")

    // ----- copies and transforms  ----------------------------------------

    protected def newLikeThis(s: Symbol, i: Type): SingleDenotation = new UniqueRefDenotation(s, i, validFor)

    /** Copy this denotation, overriding selective fields */
    final def copySymDenotation(
      symbol: Symbol = this.symbol,
      owner: Symbol = this.owner,
      name: Name = this.name,
      initFlags: FlagSet = UndefinedFlags,
      info: Type = null,
      privateWithin: Symbol = null,
      annotations: List[Annotation] = null)(implicit ctx: Context) =
    { // simulate default parameters, while also passing implicit context ctx to the default values
      val initFlags1 = (if (initFlags != UndefinedFlags) initFlags else this.flags) &~ Frozen
      val info1 = if (info != null) info else this.info
      val privateWithin1 = if (privateWithin != null) privateWithin else this.privateWithin
      val annotations1 = if (annotations != null) annotations else this.annotations
      val d = ctx.SymDenotation(symbol, owner, name, initFlags1, info1, privateWithin1)
      d.annotations = annotations1
      d
    }

    override def initial: SymDenotation = super.initial.asSymDenotation

    /** Install this denotation as the result of the given denotation transformer. */
    override def installAfter(phase: DenotTransformer)(implicit ctx: Context): Unit =
      super.installAfter(phase)

    /** Apply a transformation `f` to all denotations in this group that start at or after
     *  given phase. Denotations are replaced while keeping the same validity periods.
     */
    override def transformAfter(phase: DenotTransformer, f: SymDenotation => SymDenotation)(implicit ctx: Context): Unit =
      super.transformAfter(phase, f)

    /** If denotation is private, remove the Private flag and expand the name if necessary */
    def ensureNotPrivate(implicit ctx: Context) =
      if (is(Private))
        copySymDenotation(name = expandedName, initFlags = this.flags &~ Private)
      else this
  }

  /** The contents of a class definition during a period
   */
  class ClassDenotation private[SymDenotations] (
    symbol: Symbol,
    ownerIfExists: Symbol,
    initName: Name,
    initFlags: FlagSet,
    initInfo: Type,
    initPrivateWithin: Symbol,
    initRunId: RunId)
    extends SymDenotation(symbol, ownerIfExists, initName, initFlags, initInfo, initPrivateWithin) {

    import util.LRUCache

    // ----- denotation fields and accessors ------------------------------

    if (initFlags is (Module, butNot = Package))
      assert(name.is(ModuleClassName), s"module naming inconsistency: ${name.debugString}")

    /** The symbol asserted to have type ClassSymbol */
    def classSymbol: ClassSymbol = symbol.asInstanceOf[ClassSymbol]

    /** The info asserted to have type ClassInfo */
    def classInfo(implicit ctx: Context): ClassInfo = info.asInstanceOf[ClassInfo]

    /** TODO: Document why caches are supposedly safe to use */
    private[this] var myTypeParams: List[TypeSymbol] = _

    /** The type parameters in this class, in the order they appear in the current
     *  scope `decls`. This might be temporarily the incorrect order when
     *  reading Scala2 pickled info. The problem is fixed by `ensureTypeParamsInCorrectOrder`,
     *  which is called once an unpickled symbol has been completed.
     */
    private def typeParamsFromDecls(implicit ctx: Context) =
      unforcedDecls.filter(sym =>
        (sym is TypeParam) && sym.owner == symbol).asInstanceOf[List[TypeSymbol]]

    /** The type parameters of this class */
    override final def typeParams(implicit ctx: Context): List[TypeSymbol] = {
      if (myTypeParams == null)
        myTypeParams =
          if (ctx.erasedTypes || is(Module)) Nil // fast return for modules to avoid scanning package decls
          else {
            val di = initial
            if (this ne di) di.typeParams
            else infoOrCompleter match {
              case info: TypeParamsCompleter => info.completerTypeParams(symbol)
              case _ => typeParamsFromDecls
            }
          }
      myTypeParams
    }

    override protected[dotc] final def info_=(tp: Type) = {
      super.info_=(tp)
      myTypeParams = null // changing the info might change decls, and with it typeParams
    }

    /** The denotations of all parents in this class. */
    def classParents(implicit ctx: Context): List[TypeRef] = info match {
      case classInfo: ClassInfo => classInfo.classParents
      case _ => Nil
    }

    /** The symbol of the superclass, NoSymbol if no superclass exists */
    def superClass(implicit ctx: Context): Symbol = classParents match {
      case parent :: _ =>
        val cls = parent.classSymbol
        if (cls is Trait) NoSymbol else cls
      case _ =>
        NoSymbol
    }

    /** The denotation is fully completed: all attributes are fully defined.
     *  ClassDenotations compiled from source are first completed, then fully completed.
     *  Packages are never fully completed since members can be added at any time.
     *  @see Namer#ClassCompleter
     */
    private def isFullyCompleted(implicit ctx: Context): Boolean = {
      def isFullyCompletedRef(tp: TypeRef) = tp.denot match {
        case d: ClassDenotation => d.isFullyCompleted
        case _ => false
      }
      def testFullyCompleted =
        if (classParents.isEmpty) !is(Package) && symbol.eq(defn.AnyClass)
        else classParents.forall(isFullyCompletedRef)
      flagsUNSAFE.is(FullyCompleted) ||
        isCompleted && testFullyCompleted && { setFlag(FullyCompleted); true }
    }

    // ------ syncing inheritance-related info -----------------------------

    private var firstRunId: RunId = initRunId

    /** invalidate caches influenced by parent classes if one of the parents
     *  is younger than the denotation itself.
     */
    override def syncWithParents(implicit ctx: Context): SingleDenotation = {
      def isYounger(tref: TypeRef) = tref.symbol.denot match {
        case denot: ClassDenotation =>
          if (denot.validFor.runId < ctx.runId) denot.current // syncs with its parents in turn
          val result = denot.firstRunId > this.firstRunId
          if (result) incremental.println(s"$denot is younger than $this")
          result
        case _ => false
      }
      val parentIsYounger = (firstRunId < ctx.runId) && {
        infoOrCompleter match {
          case cinfo: ClassInfo => cinfo.classParents exists isYounger
          case _ => false
        }
      }
      if (parentIsYounger) {
        incremental.println(s"parents of $this are invalid; symbol id = ${symbol.id}, copying ...\n")
        invalidateInheritedInfo()
      }
      firstRunId = ctx.runId
      this
    }

    /** Invalidate all caches and fields that depend on base classes and their contents */
    override def invalidateInheritedInfo(): Unit = {
      myBaseClasses = null
      mySuperClassBits = null
      myMemberFingerPrint = FingerPrint.unknown
      myMemberCache = null
      myMemberCachePeriod = Nowhere
      memberNamesCache = SimpleMap.Empty
    }

   // ------ class-specific operations -----------------------------------

    private[this] var myThisType: Type = null

    /** The this-type depends on the kind of class:
     *  - for a package class `p`:  ThisType(TypeRef(Noprefix, p))
     *  - for a module class `m`: A term ref to m's source module.
     *  - for all other classes `c` with owner `o`: ThisType(TypeRef(o.thisType, c))
     */
    override def thisType(implicit ctx: Context): Type = {
      if (myThisType == null) myThisType = computeThisType
      myThisType
    }

    private def computeThisType(implicit ctx: Context): Type =
      ThisType.raw(
        TypeRef(if (this is Package) NoPrefix else owner.thisType, symbol.asType))
/*      else {
        val pre = owner.thisType
        if (this is Module)
          if (isMissing(pre)) TermRef(pre, sourceModule.asTerm)
          else TermRef.withSig(pre, name.sourceModuleName, Signature.NotAMethod)
        else ThisType.raw(TypeRef(pre, symbol.asType))
      }
*/
    private[this] var myTypeRef: TypeRef = null

    override def typeRef(implicit ctx: Context): TypeRef = {
      if (myTypeRef == null) myTypeRef = super.typeRef
      myTypeRef
    }

    private[this] var myBaseClasses: List[ClassSymbol] = null
    private[this] var mySuperClassBits: BitSet = null

    /** Invalidate baseTypeRefCache, baseClasses and superClassBits on new run */
    private def checkBasesUpToDate()(implicit ctx: Context) =
      if (baseTypeRefValid != ctx.runId) {
        baseTypeRefCache = new java.util.HashMap[CachedType, Type]
        myBaseClasses = null
        mySuperClassBits = null
        baseTypeRefValid = ctx.runId
      }

    private def computeBases(implicit ctx: Context): (List[ClassSymbol], BitSet) = {
      if (myBaseClasses eq Nil) throw CyclicReference(this)
      myBaseClasses = Nil
      val seen = new mutable.BitSet
      val locked = new mutable.BitSet
      def addBaseClasses(bcs: List[ClassSymbol], to: List[ClassSymbol])
          : List[ClassSymbol] = bcs match {
        case bc :: bcs1 =>
          val bcs1added = addBaseClasses(bcs1, to)
          val id = bc.superId
          if (seen contains id) bcs1added
          else {
            seen += id
            bc :: bcs1added
          }
        case nil =>
          to
      }
      def addParentBaseClasses(ps: List[Type], to: List[ClassSymbol]): List[ClassSymbol] = ps match {
        case p :: ps1 =>
          addParentBaseClasses(ps1, addBaseClasses(p.baseClasses, to))
        case nil =>
          to
      }
      val bcs = classSymbol :: addParentBaseClasses(classParents, Nil)
      val scbits = seen.toImmutable
      if (isFullyCompleted) {
        myBaseClasses = bcs
        mySuperClassBits = scbits
      }
      else myBaseClasses = null
      (bcs, scbits)
    }

    /** A bitset that contains the superId's of all base classes */
    private def superClassBits(implicit ctx: Context): BitSet =
      if (classParents.isEmpty) BitSet() // can happen when called too early in Namers
      else {
        checkBasesUpToDate()
        if (mySuperClassBits != null) mySuperClassBits else computeBases._2
      }

    /** The base classes of this class in linearization order,
     *  with the class itself as first element.
     */
    def baseClasses(implicit ctx: Context): List[ClassSymbol] =
      if (classParents.isEmpty) classSymbol :: Nil // can happen when called too early in Namers
      else {
        checkBasesUpToDate()
        if (myBaseClasses != null) myBaseClasses else computeBases._1
      }

    final override def derivesFrom(base: Symbol)(implicit ctx: Context): Boolean =
      !isAbsent &&
      base.isClass &&
      (  (symbol eq base)
      || (superClassBits contains base.superId)
      || (this is Erroneous)
      || (base is Erroneous)
      )

    final override def isSubClass(base: Symbol)(implicit ctx: Context) =
      derivesFrom(base) ||
        base.isClass && (
          (symbol eq defn.NothingClass) ||
            (symbol eq defn.NullClass) && (base ne defn.NothingClass))

    final override def typeParamCreationFlags = ClassTypeParamCreationFlags

    private[this] var myMemberFingerPrint: FingerPrint = FingerPrint.unknown

    private def computeMemberFingerPrint(implicit ctx: Context): FingerPrint = {
      var fp = FingerPrint()
      var e = info.decls.lastEntry
      while (e != null) {
        fp.include(e.name)
        e = e.prev
      }
      var ps = classParents
      while (ps.nonEmpty) {
        val parent = ps.head.typeSymbol
        parent.denot match {
          case parentDenot: ClassDenotation =>
            fp.include(parentDenot.memberFingerPrint)
            if (parentDenot.isFullyCompleted) parentDenot.setFlag(Frozen)
          case _ =>
        }
        ps = ps.tail
      }
      fp
    }

    /** A bloom filter for the names of all members in this class.
     *  Makes sense only for parent classes, and should definitely
     *  not be used for package classes because cache never
     *  gets invalidated.
     */
    def memberFingerPrint(implicit ctx: Context): FingerPrint =
      if (myMemberFingerPrint != FingerPrint.unknown) myMemberFingerPrint
      else {
        val fp = computeMemberFingerPrint
        if (isFullyCompleted) myMemberFingerPrint = fp
        fp
      }

    private[this] var myMemberCache: LRUCache[Name, PreDenotation] = null
    private[this] var myMemberCachePeriod: Period = Nowhere

    private def memberCache(implicit ctx: Context): LRUCache[Name, PreDenotation] = {
      if (myMemberCachePeriod != ctx.period) {
        myMemberCache = new LRUCache
        myMemberCachePeriod = ctx.period
      }
      myMemberCache
    }

    /** Hook to do a pre-enter test. Overridden in PackageDenotation */
    protected def proceedWithEnter(sym: Symbol, mscope: MutableScope)(implicit ctx: Context): Boolean = true

    /** Enter a symbol in current scope, and future scopes of same denotation.
     *  Note: We require that this does not happen after the first time
     *  someone does a findMember on a subclass.
     *  @param scope   The scope in which symbol should be entered.
     *                 If this is EmptyScope, the scope is `decls`.
     */
    def enter(sym: Symbol, scope: Scope = EmptyScope)(implicit ctx: Context): Unit = {
      val mscope = scope match {
        case scope: MutableScope =>
          // if enter gets a scope as an argument,
          // than this is a scope that will eventually become decls of this symbol.
          // And this should only happen if this is first time the scope of symbol
          // is computed, ie symbol yet has no future.
          assert(this.nextInRun.validFor.code <= this.validFor.code)
          scope
        case _ => unforcedDecls.openForMutations
      }
      if (proceedWithEnter(sym, mscope)) {
        enterNoReplace(sym, mscope)
        val nxt = this.nextInRun
        if (nxt.validFor.code > this.validFor.code) {
          this.nextInRun.asSymDenotation.asClass.enter(sym)
        }
      }
    }

    /** Enter a symbol in given `scope` without potentially replacing the old copy. */
    def enterNoReplace(sym: Symbol, scope: MutableScope)(implicit ctx: Context): Unit = {
      def isUsecase = ctx.docCtx.isDefined && sym.name.show.takeRight(4) == "$doc"
      require(
          (sym.denot.flagsUNSAFE is Private) ||
          !(this is Frozen) ||
          (scope ne this.unforcedDecls) ||
          sym.hasAnnotation(defn.ScalaStaticAnnot) ||
          sym.name.is(InlineAccessorName) ||
          isUsecase, i"trying to enter $sym in $this, frozen = ${this is Frozen}")

      scope.enter(sym)

      if (myMemberFingerPrint != FingerPrint.unknown)
        myMemberFingerPrint.include(sym.name)
      if (myMemberCache != null)
        myMemberCache invalidate sym.name
    }

    /** Replace symbol `prev` (if defined in current class) by symbol `replacement`.
     *  If `prev` is not defined in current class, do nothing.
     *  @pre `prev` and `replacement` have the same name.
     */
    def replace(prev: Symbol, replacement: Symbol)(implicit ctx: Context): Unit = {
      require(!(this is Frozen))
      unforcedDecls.openForMutations.replace(prev, replacement)
      if (myMemberCache != null)
        myMemberCache invalidate replacement.name
    }

    /** Delete symbol from current scope.
     *  Note: We require that this does not happen after the first time
     *  someone does a findMember on a subclass.
     */
    def delete(sym: Symbol)(implicit ctx: Context) = {
      require(!(this is Frozen))
      info.decls.openForMutations.unlink(sym)
      myMemberFingerPrint = FingerPrint.unknown
      if (myMemberCache != null) myMemberCache invalidate sym.name
    }

    /** Make sure the type parameters of this class appear in the order given
     *  by `typeParams` in the scope of the class. Reorder definitions in scope if necessary.
     */
    def ensureTypeParamsInCorrectOrder()(implicit ctx: Context): Unit = {
      val tparams = typeParams
      if (!ctx.erasedTypes && !typeParamsFromDecls.corresponds(tparams)(_.name == _.name)) {
        val decls = info.decls
        val decls1 = newScope
        for (tparam <- typeParams) decls1.enter(decls.lookup(tparam.name))
        for (sym <- decls) if (!tparams.contains(sym)) decls1.enter(sym)
        info = classInfo.derivedClassInfo(decls = decls1)
        myTypeParams = null
      }
    }

    /** All members of this class that have the given name.
     *  The elements of the returned pre-denotation all
     *  have existing symbols.
     */
    final def membersNamed(name: Name)(implicit ctx: Context): PreDenotation = {
      val privates = info.decls.denotsNamed(name, selectPrivate)
      privates union nonPrivateMembersNamed(name).filterDisjoint(privates)
    }

    /** All non-private members of this class that have the given name.
     *  The elements of the returned pre-denotation all
     *  have existing symbols.
     *  @param inherited  The method is called on a parent class from computeNPMembersNamed
     */
    final def nonPrivateMembersNamed(name: Name, inherited: Boolean = false)(implicit ctx: Context): PreDenotation = {
      Stats.record("nonPrivateMembersNamed")
      if (Config.cacheMembersNamed) {
        var denots: PreDenotation = memberCache lookup name
        if (denots == null) {
          denots = computeNPMembersNamed(name, inherited)
          if (isFullyCompleted) memberCache.enter(name, denots)
        } else if (Config.checkCacheMembersNamed) {
          val denots1 = computeNPMembersNamed(name, inherited)
          assert(denots.exists == denots1.exists, s"cache inconsistency: cached: $denots, computed $denots1, name = $name, owner = $this")
        }
        denots
      } else computeNPMembersNamed(name, inherited)
    }

    private[core] def computeNPMembersNamed(name: Name, inherited: Boolean)(implicit ctx: Context): PreDenotation = /*>|>*/ Stats.track("computeNPMembersNamed") /*<|<*/ {
      if (!inherited ||
          !Config.useFingerPrints ||
          (memberFingerPrint contains name)) {
        Stats.record("computeNPMembersNamed after fingerprint")
        ensureCompleted()
        val ownDenots = info.decls.denotsNamed(name, selectNonPrivate)
        if (debugTrace)  // DEBUG
          println(s"$this.member($name), ownDenots = $ownDenots")
        def collect(denots: PreDenotation, parents: List[TypeRef]): PreDenotation = parents match {
          case p :: ps =>
            val denots1 = collect(denots, ps)
            p.symbol.denot match {
              case parentd: ClassDenotation =>
                denots1 union
                  parentd.nonPrivateMembersNamed(name, inherited = true)
                    .mapInherited(ownDenots, denots1, thisType)
              case _ =>
                denots1
            }
          case nil =>
            denots
        }
        if (name.isConstructorName) ownDenots
        else collect(ownDenots, classParents)
      } else NoDenotation
    }

    override final def findMember(name: Name, pre: Type, excluded: FlagSet)(implicit ctx: Context): Denotation = {
      val raw = if (excluded is Private) nonPrivateMembersNamed(name) else membersNamed(name)
      raw.filterExcluded(excluded).asSeenFrom(pre).toDenot(pre)
    }

    private[this] var baseTypeRefCache: java.util.HashMap[CachedType, Type] = null
    private[this] var baseTypeRefValid: RunId = NoRunId

    /** Compute tp.baseTypeRef(this) */
    final def baseTypeRefOf(tp: Type)(implicit ctx: Context): Type = {

      def foldGlb(bt: Type, ps: List[Type]): Type = ps match {
        case p :: ps1 => foldGlb(bt & baseTypeRefOf(p), ps1)
        case _ => bt
      }

      def inCache(tp: Type) = baseTypeRefCache.containsKey(tp)

      /** We cannot cache:
       *  - type variables which are uninstantiated or whose instances can
       *    change, depending on typerstate.
       *  - types where the underlying type is an ErasedValueType, because
       *    this underlying type will change after ElimErasedValueType,
       *    and this changes subtyping relations. As a shortcut, we do not
       *    cache ErasedValueType at all.
       */
      def isCachable(tp: Type): Boolean = tp match {
        case _: TypeErasure.ErasedValueType => false
        case tp: TypeRef if tp.symbol.isClass => true
        case tp: TypeVar => tp.inst.exists && inCache(tp.inst)
        case tp: TypeProxy => inCache(tp.underlying)
        case tp: AndOrType => inCache(tp.tp1) && inCache(tp.tp2)
        case _ => true
      }

      def computeBaseTypeRefOf(tp: Type): Type = {
        Stats.record("computeBaseTypeOf")
        if (symbol.isStatic && tp.derivesFrom(symbol))
          symbol.typeRef
        else tp match {
          case tp: TypeRef =>
            val subcls = tp.symbol
            if (subcls eq symbol)
              tp
            else subcls.denot match {
              case cdenot: ClassDenotation =>
                if (cdenot.superClassBits contains symbol.superId) foldGlb(NoType, tp.parents)
                else NoType
              case _ =>
                baseTypeRefOf(tp.superType)
            }
          case tp: TypeProxy =>
            baseTypeRefOf(tp.superType)
          case AndType(tp1, tp2) =>
            baseTypeRefOf(tp1) & baseTypeRefOf(tp2)
          case OrType(tp1, tp2) =>
            baseTypeRefOf(tp1) | baseTypeRefOf(tp2)
          case JavaArrayType(_) if symbol == defn.ObjectClass =>
            this.typeRef
          case _ =>
            NoType
        }
      }

      /*>|>*/ ctx.debugTraceIndented(s"$tp.baseTypeRef($this)") /*<|<*/ {
        tp match {
          case tp: CachedType =>
            checkBasesUpToDate()
            var basetp = baseTypeRefCache get tp
            if (basetp == null) {
              baseTypeRefCache.put(tp, NoPrefix)
              basetp = computeBaseTypeRefOf(tp)
              if (isCachable(tp)) baseTypeRefCache.put(tp, basetp)
              else baseTypeRefCache.remove(tp)
            } else if (basetp == NoPrefix) {
              baseTypeRefCache.put(tp, null)
              throw CyclicReference(this)
            }
            basetp
          case _ =>
            computeBaseTypeRefOf(tp)
        }
      }
    }

    private[this] var memberNamesCache: SimpleMap[NameFilter, Set[Name]] = SimpleMap.Empty

    def memberNames(keepOnly: NameFilter)(implicit ctx: Context): Set[Name] = {
      def computeMemberNames: Set[Name] = {
        var names = Set[Name]()
        def maybeAdd(name: Name) = if (keepOnly(thisType, name)) names += name
        for (p <- classParents)
          for (name <- p.memberNames(keepOnly, thisType)) maybeAdd(name)
        val ownSyms =
          if (keepOnly == implicitFilter)
            if (this is Package) Iterator.empty
            else info.decls.iterator filter (_ is Implicit)
          else info.decls.iterator
        for (sym <- ownSyms) maybeAdd(sym.name)
        names
      }
      if ((this is PackageClass) || !Config.cacheMemberNames)
        computeMemberNames // don't cache package member names; they might change
      else {
        val cached = memberNamesCache(keepOnly)
        if (cached != null) cached
        else {
          val names = computeMemberNames
          if (isFullyCompleted) {
            setFlag(Frozen)
            memberNamesCache = memberNamesCache.updated(keepOnly, names)
          }
          names
        }
      }
    }

    private[this] var fullNameCache: SimpleMap[QualifiedNameKind, Name] = SimpleMap.Empty
    override final def fullNameSeparated(kind: QualifiedNameKind)(implicit ctx: Context): Name = {
      val cached = fullNameCache(kind)
      if (cached != null) cached
      else {
        val fn = super.fullNameSeparated(kind)
        fullNameCache = fullNameCache.updated(kind, fn)
        fn
      }
    }

    // to avoid overloading ambiguities
    override def fullName(implicit ctx: Context): Name = super.fullName

    override def primaryConstructor(implicit ctx: Context): Symbol = {
      def constrNamed(cname: TermName) = info.decls.denotsNamed(cname).last.symbol
        // denotsNamed returns Symbols in reverse order of occurrence
      if (this.is(ImplClass)) constrNamed(nme.TRAIT_CONSTRUCTOR) // ignore normal constructor
      else if (this.is(Package)) NoSymbol
      else constrNamed(nme.CONSTRUCTOR).orElse(constrNamed(nme.TRAIT_CONSTRUCTOR))
    }

    /** The parameter accessors of this class. Term and type accessors,
     *  getters and setters are all returned int his list
     */
    def paramAccessors(implicit ctx: Context): List[Symbol] =
      unforcedDecls.filter(_ is ParamAccessor).toList

    /** If this class has the same `decls` scope reference in `phase` and
     *  `phase.next`, install a new denotation with a cloned scope in `phase.next`.
     */
    def ensureFreshScopeAfter(phase: DenotTransformer)(implicit ctx: Context): Unit =
      if (ctx.phaseId != phase.next.id) ensureFreshScopeAfter(phase)(ctx.withPhase(phase.next))
      else {
        val prevCtx = ctx.withPhase(phase)
        val ClassInfo(pre, _, ps, decls, selfInfo) = classInfo
        if (classInfo(prevCtx).decls eq decls)
          copySymDenotation(info = ClassInfo(pre, classSymbol, ps, decls.cloneScope, selfInfo))
            .installAfter(phase)
      }
  }

  /** The denotation of a package class.
   *  It overrides ClassDenotation to take account of package objects when looking for members
   */
  final class PackageClassDenotation private[SymDenotations] (
    symbol: Symbol,
    ownerIfExists: Symbol,
    name: Name,
    initFlags: FlagSet,
    initInfo: Type,
    initPrivateWithin: Symbol,
    initRunId: RunId)
    extends ClassDenotation(symbol, ownerIfExists, name, initFlags, initInfo, initPrivateWithin, initRunId) {

    private[this] var packageObjCache: SymDenotation = _
    private[this] var packageObjRunId: RunId = NoRunId

    /** The package object in this class, of one exists */
    def packageObj(implicit ctx: Context): SymDenotation = {
      if (packageObjRunId != ctx.runId) {
        packageObjRunId = ctx.runId
        packageObjCache = NoDenotation // break cycle in case we are looking for package object itself
        packageObjCache = findMember(nme.PACKAGE, thisType, EmptyFlags).asSymDenotation
      }
      packageObjCache
    }

    /** Looks in both the package object and the package for members. The precise algorithm
     *  is as follows:
     *
     *  If this is the scala package look in the package first, and if nothing is found
     *  there, look in the package object second. Otherwise, look in the package object
     *  first, and if nothing is found there, in the package second.
     *
     *  The reason for the special treatment of the scala package is that if we
     *  complete it too early, we freeze its superclass Any, so that no members can
     *  be entered in it. As a consequence, there should be no entry in the scala package
     *  object that hides a class or object in the scala package of the same name, because
     *  the behavior would then be unintuitive for such members.
     */
    override def computeNPMembersNamed(name: Name, inherited: Boolean)(implicit ctx: Context): PreDenotation =
      packageObj.moduleClass.denot match {
        case pcls: ClassDenotation if !pcls.isCompleting =>
          if (symbol eq defn.ScalaPackageClass) {
            val denots = super.computeNPMembersNamed(name, inherited)
            if (denots.exists) denots else pcls.computeNPMembersNamed(name, inherited)
          }
          else {
            val denots = pcls.computeNPMembersNamed(name, inherited)
            if (denots.exists) denots else super.computeNPMembersNamed(name, inherited)
          }
        case _ =>
          super.computeNPMembersNamed(name, inherited)
      }

    /** The union of the member names of the package and the package object */
    override def memberNames(keepOnly: NameFilter)(implicit ctx: Context): Set[Name] = {
      val ownNames = super.memberNames(keepOnly)
      packageObj.moduleClass.denot match {
        case pcls: ClassDenotation => ownNames union pcls.memberNames(keepOnly)
        case _ => ownNames
      }
    }

    /** If another symbol with the same name is entered, unlink it,
     *  and, if symbol is a package object, invalidate the packageObj cache.
     *  @return  `sym` is not already entered
     */
    override def proceedWithEnter(sym: Symbol, mscope: MutableScope)(implicit ctx: Context): Boolean = {
      val entry = mscope.lookupEntry(sym.name)
      if (entry != null) {
        if (entry.sym == sym) return false
        mscope.unlink(entry)
        entry.sym.denot = sym.denot // to avoid stale symbols
        if (sym.name == nme.PACKAGE) packageObjRunId = NoRunId
      }
      true
    }
  }

  class NoDenotation extends SymDenotation(
    NoSymbol, NoSymbol, "<none>".toTermName, Permanent, NoType) {
    override def exists = false
    override def isTerm = false
    override def isType = false
    override def owner: Symbol = throw new AssertionError("NoDenotation.owner")
    override def computeAsSeenFrom(pre: Type)(implicit ctx: Context): SingleDenotation = this
    override def mapInfo(f: Type => Type)(implicit ctx: Context): SingleDenotation = this
    validFor = Period.allInRun(NoRunId) // will be brought forward automatically
  }

  @sharable val NoDenotation = new NoDenotation

  // ---- Completion --------------------------------------------------------

  /** Instances of LazyType are carried by uncompleted symbols.
   *  Note: LazyTypes double up as (constant) functions from Symbol and
   *  from (TermSymbol, ClassSymbol) to LazyType. That way lazy types can be
   *  directly passed to symbol creation methods in Symbols that demand instances
   *  of these function types.
   */
  abstract class LazyType extends UncachedGroundType
    with (Symbol => LazyType)
    with ((TermSymbol, ClassSymbol) => LazyType) { self =>

    /** Sets all missing fields of given denotation */
    def complete(denot: SymDenotation)(implicit ctx: Context): Unit

    def apply(sym: Symbol) = this
    def apply(module: TermSymbol, modcls: ClassSymbol) = this

    private var myDecls: Scope = EmptyScope
    private var mySourceModuleFn: Context => Symbol = NoSymbolFn
    private var myModuleClassFn: Context => Symbol = NoSymbolFn

    /** A proxy to this lazy type that keeps the complete operation
     *  but provides fresh slots for scope/sourceModule/moduleClass
     */
    def proxy: LazyType = new LazyType {
      override def complete(denot: SymDenotation)(implicit ctx: Context) = self.complete(denot)
    }

    def decls: Scope = myDecls
    def sourceModule(implicit ctx: Context): Symbol = mySourceModuleFn(ctx)
    def moduleClass(implicit ctx: Context): Symbol = myModuleClassFn(ctx)

    def withDecls(decls: Scope): this.type = { myDecls = decls; this }
    def withSourceModule(sourceModuleFn: Context => Symbol): this.type = { mySourceModuleFn = sourceModuleFn; this }
    def withModuleClass(moduleClassFn: Context => Symbol): this.type = { myModuleClassFn = moduleClassFn; this }
  }

  /** A subclass of LazyTypes where type parameters can be completed independently of
   *  the info.
   */
  trait TypeParamsCompleter extends LazyType {
    /** The type parameters computed by the completer before completion has finished */
    def completerTypeParams(sym: Symbol)(implicit ctx: Context): List[TypeSymbol]
  }

  val NoSymbolFn = (ctx: Context) => NoSymbol

  /** A missing completer */
  @sharable class NoCompleter extends LazyType {
    def complete(denot: SymDenotation)(implicit ctx: Context): Unit = unsupported("complete")
  }

  object NoCompleter extends NoCompleter

  /** A lazy type for modules that points to the module class.
   *  Needed so that `moduleClass` works before completion.
   *  Completion of modules is always completion of the underlying
   *  module class, followed by copying the relevant fields to the module.
   */
  class ModuleCompleter(_moduleClass: ClassSymbol) extends LazyType {
    override def moduleClass(implicit ctx: Context) = _moduleClass
    def complete(denot: SymDenotation)(implicit ctx: Context): Unit = {
      val from = moduleClass.denot.asClass
      denot.setFlag(from.flags.toTermFlags & RetainedModuleValFlags)
      denot.annotations = from.annotations filter (_.appliesToModule)
        // !!! ^^^ needs to be revised later. The problem is that annotations might
        // only apply to the module but not to the module class. The right solution
        // is to have the module class completer set the annotations of both the
        // class and the module.
      denot.info = moduleClass.typeRef
      denot.privateWithin = from.privateWithin
    }
  }

  /** A completer for missing references */
  class StubInfo() extends LazyType {

    def initializeToDefaults(denot: SymDenotation, errMsg: => String)(implicit ctx: Context) = {
      denot.info = denot match {
        case denot: ClassDenotation =>
          ClassInfo(denot.owner.thisType, denot.classSymbol, Nil, EmptyScope)
        case _ =>
          new ErrorType(errMsg)
      }
      denot.privateWithin = NoSymbol
    }

    def complete(denot: SymDenotation)(implicit ctx: Context): Unit = {
      val sym = denot.symbol
      val file = sym.associatedFile
      val (location, src) =
        if (file != null) (s" in $file", file.toString)
        else ("", "the signature")
      val name = ctx.fresh.setSetting(ctx.settings.debugNames, true).nameString(denot.name)
      def errMsg =
        i"""bad symbolic reference. A signature$location
           |refers to $name in ${denot.owner.showKind} ${denot.owner.showFullName} which is not available.
           |It may be completely missing from the current classpath, or the version on
           |the classpath might be incompatible with the version used when compiling $src."""
      ctx.error(errMsg)
      if (ctx.debug) throw new Error()
      initializeToDefaults(denot, errMsg)
    }
  }

  // ---- Fingerprints -----------------------------------------------------

  /** A fingerprint is a bitset that acts as a bloom filter for sets
   *  of names.
   */
  class FingerPrint(val bits: Array[Long]) extends AnyVal {
    import FingerPrint._

    /** Include some bits of name's hashcode in set */
    def include(name: Name): Unit = {
      val hash = name.hashCode & Mask
      bits(hash >> WordSizeLog) |= (1L << hash)
    }

    /** Include all bits of `that` fingerprint in set */
    def include(that: FingerPrint): Unit =
      for (i <- 0 until NumWords) bits(i) |= that.bits(i)

    /** Does set contain hash bits of given name? */
    def contains(name: Name): Boolean = {
      val hash = name.hashCode & Mask
      (bits(hash >> WordSizeLog) & (1L << hash)) != 0
    }
  }

  object FingerPrint {
    def apply() = new FingerPrint(new Array[Long](NumWords))
    val unknown = new FingerPrint(null)
    private final val WordSizeLog = 6
    private final val NumWords = 32
    private final val NumBits = NumWords << WordSizeLog
    private final val Mask = NumBits - 1
  }

  private val AccessorOrLabel = Accessor | Label

  @sharable private var indent = 0 // for completions printing
}