Skip to content

Commit

Permalink
No commit message
Browse files Browse the repository at this point in the history
  • Loading branch information
odersky committed Nov 16, 2006
1 parent 821551d commit cb7711d
Show file tree
Hide file tree
Showing 14 changed files with 196 additions and 95 deletions.
7 changes: 5 additions & 2 deletions src/compiler/scala/tools/nsc/symtab/Definitions.scala
Expand Up @@ -257,8 +257,11 @@ trait Definitions requires SymbolTable {

def getMember(owner: Symbol, name: Name) = {
val result = owner.info.nonPrivateMember(name)
if (result == NoSymbol)
throw new FatalError(owner.toString() + " does not have a member " + name);
if (result == NoSymbol) {
Console.println(owner.infosString)
Console.println(owner.info.decls)
throw new FatalError(owner.toString() + " does not have a member " + name)
}
result
}

Expand Down
19 changes: 13 additions & 6 deletions src/compiler/scala/tools/nsc/symtab/SymbolTable.scala
Expand Up @@ -37,9 +37,9 @@ abstract class SymbolTable extends Names
private var ph: Phase = NoPhase
private var per = NoPeriod

def phase: Phase = ph
final def phase: Phase = ph

def phase_=(p: Phase): unit = {
final def phase_=(p: Phase): unit = {
//System.out.println("setting phase to " + p)
assert((p ne null) && p != NoPhase)
ph = p
Expand All @@ -50,22 +50,28 @@ abstract class SymbolTable extends Names
def currentRunId: RunId

/** The run identifier of the given period */
def runId(period: Period): RunId = period >> 8
final def runId(period: Period): RunId = period >> 8

/** The phase identifier of the given period */
def phaseId(period: Period): Phase#Id = period & 0xFF
final def phaseId(period: Period): Phase#Id = period & 0xFF

/** The period at the start of run that includes `period' */
final def startRun(period: Period): Period = period & 0xFFFFFF00

/** The current period */
def currentPeriod: Period = {
final def currentPeriod: Period = {
//assert(per == (currentRunId << 8) + phase.id)
per
}

/** The phase associated with given period */
final def phaseOf(period: Period): Phase = phaseWithId(phaseId(period))

final def period(rid: RunId, pid: Phase#Id): Period =
(currentRunId << 8) + pid

/** Perform given operation at given phase */
def atPhase[T](ph: Phase)(op: => T): T = {
final def atPhase[T](ph: Phase)(op: => T): T = {
val current = phase
phase = ph
val result = op
Expand All @@ -82,4 +88,5 @@ abstract class SymbolTable extends Names

/** The phase which has given index as identifier */
val phaseWithId: Array[Phase]

}
139 changes: 85 additions & 54 deletions src/compiler/scala/tools/nsc/symtab/Symbols.scala
Expand Up @@ -311,7 +311,7 @@ trait Symbols requires SymbolTable {
this != NoSymbol && (!owner.isPackageClass || { rawInfo.load(this); rawInfo != NoType })

final def isInitialized: boolean =
runId(validTo) == currentRunId
validTo != NoPeriod

final def isCovariant: boolean = isType && hasFlag(COVARIANT)

Expand Down Expand Up @@ -362,7 +362,7 @@ trait Symbols requires SymbolTable {

// Info and Type -------------------------------------------------------------------

private var infos: TypeHistory = null
private[Symbols] var infos: TypeHistory = null

/** Get type. The type of a symbol is:
* for a type symbol, the type corresponding to the symbol itself
Expand All @@ -375,14 +375,11 @@ trait Symbols requires SymbolTable {
*/
final def info: Type = {
var cnt = 0
while (runId(validTo) != currentRunId) {
while (validTo == NoPeriod) {
//if (settings.debug.value) System.out.println("completing " + this);//DEBUG
var ifs = infos
assert(ifs ne null, this.name)
while (ifs.prev ne null) {
ifs = ifs.prev
}
val tp = ifs.info
assert(infos ne null, this.name)
assert(infos.prev eq null, this.name)
val tp = infos.info
//if (settings.debug.value) System.out.println("completing " + this.rawname + tp.getClass());//debug
if ((rawflags & LOCKED) != 0) {
setInfo(ErrorType)
Expand All @@ -391,7 +388,7 @@ trait Symbols requires SymbolTable {
rawflags = rawflags | LOCKED
val current = phase
try {
phase = phaseWithId(ifs.start)
phase = phaseOf(infos.validFrom)
tp.complete(this)
// if (settings.debug.value && runId(validTo) == currentRunId) System.out.println("completed " + this/* + ":" + info*/);//DEBUG
rawflags = rawflags & ~LOCKED
Expand All @@ -403,19 +400,14 @@ trait Symbols requires SymbolTable {
// one: sourceCompleter to LazyType, two: LazyType to completed type
if (cnt == 3) throw new Error("no progress in completing " + this + ":" + tp)
}
rawInfo
val result = rawInfo
result
}

/** Set initial info. */
def setInfo(info: Type): this.type = {
assert(info ne null)
var period = currentPeriod
if (phaseId(period) == 0) {
// can happen when we initialize NoSymbol before running the compiler
assert(name == nme.NOSYMBOL)
period = period + 1
}
infos = new TypeHistory(phaseId(period), info, null)
infos = TypeHistory(currentPeriod, info, null)
if (info.isComplete) {
rawflags = rawflags & ~LOCKED
validTo = currentPeriod
Expand All @@ -428,45 +420,81 @@ trait Symbols requires SymbolTable {

/** Set new info valid from start of this phase. */
final def updateInfo(info: Type): Symbol = {
assert(infos.start <= phase.id)
if (infos.start == phase.id) infos = infos.prev
infos = new TypeHistory(phase.id, info, infos)
assert(phaseId(infos.validFrom) <= phase.id)
if (phaseId(infos.validFrom) == phase.id) infos = infos.prev
infos = TypeHistory(currentPeriod, info, infos)
this
}

/** Return info without checking for initialization or completing */
final def rawInfo: Type =
if (validTo == currentPeriod) {
infos.info
} else {
var limit = phaseId(validTo)
if (limit < phase.id) {
if (runId(validTo) == currentRunId) {
val current = phase
var itr = infoTransformers.nextFrom(limit)
infoTransformers = itr; // caching optimization
while (itr.pid != NoPhase.id && itr.pid < current.id) {
limit = itr.pid
phase = phaseWithId(limit)
val info1 = itr.transform(this, infos.info)
validTo = currentPeriod + 1
if (info1 ne infos.info) {
infos = new TypeHistory(limit + 1, info1, infos)
def rawInfo: Type = {
var infos = this.infos
assert(infos != null, name)
val curPeriod = currentPeriod
val curPid = phaseId(curPeriod)

if (validTo != NoPeriod) {

// skip any infos that concern later phases
while (curPid < phaseId(infos.validFrom) && infos.prev != null)
infos = infos.prev

if (validTo < curPeriod) {
// adapt any infos that come from previous runs
val current = phase
try {
infos = adaptInfos(infos)

//assert(runId(validTo) == currentRunId, name)
//assert(runId(infos.validFrom) == currentRunId, name)

if (validTo < curPeriod) {
var itr = infoTransformers.nextFrom(phaseId(validTo))
infoTransformers = itr; // caching optimization
while (itr.pid != NoPhase.id && itr.pid < current.id) {
phase = phaseWithId(itr.pid)
val info1 = itr.transform(this, infos.info)
if (info1 ne infos.info) {
infos = TypeHistory(currentPeriod + 1, info1, infos)
this.infos = infos
}
validTo = currentPeriod + 1 // to enable reads from same symbol during info-transform
itr = itr.next
}
itr = itr.nextFrom(limit + 1)
validTo = if (itr.pid == NoPhase.id) curPeriod
else period(currentRunId, itr.pid)
}
} finally {
phase = current
validTo = currentPeriod
}
assert(infos ne null, name)
infos.info
} else {
var infos = this.infos
while (phase.id < infos.start && (infos.prev ne null)) infos = infos.prev
infos.info
}
}
infos.info
}

private def adaptInfos(infos: TypeHistory): TypeHistory =
if (infos == null || runId(infos.validFrom) == currentRunId) {
infos
} else {
val prev1 = adaptInfos(infos.prev)
if (prev1 ne infos.prev) prev1
else {
def adaptToNewRun(info: Type): Type =
if (isPackageClass) info else adaptToNewRunMap(info)
val pid = phaseId(infos.validFrom)
validTo = period(currentRunId, pid)
phase = phaseWithId(pid)
val info1 = adaptToNewRun(infos.info)
if (info1 eq infos.info) {
infos.validFrom = validTo
infos
} else {
this.infos = TypeHistory(validTo, info1, prev1)
this.infos
}
}
}

/** Initialize the symbol */
final def initialize: this.type = {
if (!isInitialized) info
Expand All @@ -476,8 +504,8 @@ trait Symbols requires SymbolTable {
/** Was symbol's type updated during given phase? */
final def isUpdatedAt(pid: Phase#Id): boolean = {
var infos = this.infos
while ((infos ne null) && infos.start != pid + 1) infos = infos.prev
(infos ne null)
while ((infos ne null) && phaseId(infos.validFrom) != pid + 1) infos = infos.prev
infos ne null
}

/** The type constructor of a symbol is:
Expand Down Expand Up @@ -1233,7 +1261,10 @@ trait Symbols requires SymbolTable {
setInfo(NoType)
privateWithin = this
override def setInfo(info: Type): this.type = {
assert(info eq NoType); super.setInfo(info)
infos = TypeHistory(1, NoType, null)
rawflags = rawflags & ~ LOCKED
validTo = currentPeriod
this
}
override def enclClass: Symbol = this
override def toplevelClass: Symbol = this
Expand All @@ -1243,6 +1274,7 @@ trait Symbols requires SymbolTable {
override def ownerChain: List[Symbol] = List()
override def alternatives: List[Symbol] = List()
override def reset(completer: Type): unit = {}
override def rawInfo: Type = NoType
def cloneSymbolImpl(owner: Symbol): Symbol = throw new Error()
}

Expand All @@ -1263,11 +1295,10 @@ trait Symbols requires SymbolTable {
extends TypeError("illegal cyclic reference involving " + sym)

/** A class for type histories */
private case class TypeHistory(start: Phase#Id, info: Type, prev: TypeHistory) {
assert((prev eq null) || start > prev.start, this)
assert(start != 0)
private case class TypeHistory(var validFrom: Period, info: Type, prev: TypeHistory) {
assert((prev eq null) || phaseId(validFrom) > phaseId(prev.validFrom), this)
assert(validFrom != NoPeriod)
override def toString() =
"TypeHistory(" + phaseWithId(start) + "," + info + "," + prev + ")"
"TypeHistory(" + phaseOf(validFrom)+":"+runId(validFrom) + "," + info + "," + prev + ")"
}

}
28 changes: 8 additions & 20 deletions src/compiler/scala/tools/nsc/symtab/Types.scala
Expand Up @@ -364,18 +364,7 @@ trait Types requires SymbolTable {
def isComplete: boolean = true

/** If this is a lazy type, assign a new type to <code>sym</code>. */
def complete(sym: Symbol): unit = {
if (sym == NoSymbol || sym.isPackageClass)
sym.validTo = period(currentRunId, phaseId(sym.validTo))
else {
val this1 = adaptToNewRunMap(this)
if (this1 eq this) sym.validTo = period(currentRunId, phaseId(sym.validTo))
else {
//Console.println("new type of " + sym + "=" + this1 + ", used to be " + this);//DEBUG
sym.setInfo(this1)
}
}
}
def complete(sym: Symbol) = {}

/** If this is a symbol loader type, load and assign a new type to
* <code>sym</code>.
Expand Down Expand Up @@ -1645,16 +1634,12 @@ trait Types requires SymbolTable {
}
}


object adaptToNewRunMap extends TypeMap {
private def adaptToNewRun(pre: Type, sym: Symbol): Symbol = {
if (sym.isModuleClass && !phase.flatClasses) {
adaptToNewRun(pre, sym.sourceModule).moduleClass
} else if ((pre eq NoPrefix) || (pre eq NoType)) {
} else if ((pre eq NoPrefix) || (pre eq NoType) || sym.owner.isPackageClass) {
sym
} else if (sym.owner.isPackageClass) {
val sym1 = sym.owner.info.decl(sym.name)
if (sym1 != NoSymbol && sym1.validTo > sym.validTo) sym1 else sym
} else {
var rebind0 = pre.findMember(sym.name, BRIDGE, 0, true)
/** The two symbols have the same fully qualified name */
Expand Down Expand Up @@ -1703,9 +1688,12 @@ trait Types requires SymbolTable {
if (restp1 eq restp) tp
else PolyType(tparams, restp1)
case ClassInfoType(parents, decls, clazz) =>
val parents1 = List.mapConserve(parents)(this)
if (parents1 eq parents) tp
else ClassInfoType(parents1, decls, clazz)
if (clazz.isPackageClass) tp
else {
val parents1 = List.mapConserve(parents)(this)
if (parents1 eq parents) tp
else ClassInfoType(parents1, decls, clazz)
}
case RefinedType(parents, decls) =>
val parents1 = List.mapConserve(parents)(this)
if (parents1 eq parents) tp
Expand Down
Expand Up @@ -280,7 +280,7 @@ abstract class UnPickler {
override def complete(sym: Symbol): unit = {
val tp = at(i, readType)
sym setInfo tp
if (currentRunId != definedAtRunId) tp.complete(sym)
if (currentRunId != definedAtRunId) sym.setInfo(adaptToNewRunMap(tp))
}
override def load(sym: Symbol): unit = complete(sym)
}
Expand Down
5 changes: 4 additions & 1 deletion src/compiler/scala/tools/nsc/transform/Constructors.scala
Expand Up @@ -55,7 +55,10 @@ abstract class Constructors extends Transform {
parameterNamed(nme.getterName(acc.originalName))

def parameterNamed(name: Name): Symbol = {
val ps = constrParams.filter(param => param.name == name || param.originalName == name)
def matchesName(param: Symbol) =
param.name == name ||
param.name.startsWith(name) && param.name(name.length) == '$'
val ps = constrParams filter matchesName
if (ps.isEmpty) assert(false, "" + name + " not in " + constrParams)
ps.head
}
Expand Down
11 changes: 0 additions & 11 deletions src/compiler/scala/tools/nsc/transform/Mixin.scala
Expand Up @@ -190,17 +190,6 @@ abstract class Mixin extends InfoTransform {
assert (impl.isImplClass)
for (val member <- impl.info.decls.toList) {
if (isForwarded(member)) {
for (val im <- iface.info.member(member.name).alternatives) {
// There's a subtle reason why we need to complete the interface symbol:
// It might be that the type of the interface symbol refers to
// an abstract type in the interface bounded by a nested class outside
// the interface. Assume now that the nested class is recompiled in resident mode.
// The interface symbol will be valid for the whole run because
// the abstract type has not changed. But the erased type *has* changed
// and therefore needs to be updated. See bug809 for an example where
// this comes up.
im.info.complete(im)
}
val imember = member.overriddenSymbol(iface)
//Console.println("mixin member "+member+":"+member.tpe+member.locationString+" "+imember+" "+imember.overridingSymbol(clazz)+" to "+clazz+" with scope "+clazz.info.decls)//DEBUG
if (imember.overridingSymbol(clazz) == NoSymbol &&
Expand Down
7 changes: 7 additions & 0 deletions test/files/neg/overload.check
@@ -0,0 +1,7 @@
overload.scala:10 error: erroneous reference to overloaded definition,
most specific definition is: method f in class C of type (scala.Int)scala.Unit,
yet alternative definition method f in class D of type (scala.Any)scala.Unit
is defined in a subclass
(new D).f(1)
^
one error found

0 comments on commit cb7711d

Please sign in to comment.