summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Definitions.scala7
-rw-r--r--src/compiler/scala/tools/nsc/symtab/SymbolTable.scala19
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Symbols.scala139
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Types.scala28
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/UnPickler.scala2
-rw-r--r--src/compiler/scala/tools/nsc/transform/Constructors.scala5
-rw-r--r--src/compiler/scala/tools/nsc/transform/Mixin.scala11
-rw-r--r--test/files/neg/overload.check7
-rw-r--r--test/files/neg/overload.scala11
-rw-r--r--test/files/pos/bug803.scala2
-rw-r--r--test/files/pos/bug805.scala19
-rw-r--r--test/files/pos/bug812.scala7
-rw-r--r--test/files/run/bug789.check2
-rw-r--r--test/files/run/bug789.scala32
14 files changed, 196 insertions, 95 deletions
diff --git a/src/compiler/scala/tools/nsc/symtab/Definitions.scala b/src/compiler/scala/tools/nsc/symtab/Definitions.scala
index 59bf1e71a0..b71af309af 100644
--- a/src/compiler/scala/tools/nsc/symtab/Definitions.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Definitions.scala
@@ -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
}
diff --git a/src/compiler/scala/tools/nsc/symtab/SymbolTable.scala b/src/compiler/scala/tools/nsc/symtab/SymbolTable.scala
index b1f7a817fd..85e0f95bec 100644
--- a/src/compiler/scala/tools/nsc/symtab/SymbolTable.scala
+++ b/src/compiler/scala/tools/nsc/symtab/SymbolTable.scala
@@ -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
@@ -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
@@ -82,4 +88,5 @@ abstract class SymbolTable extends Names
/** The phase which has given index as identifier */
val phaseWithId: Array[Phase]
+
}
diff --git a/src/compiler/scala/tools/nsc/symtab/Symbols.scala b/src/compiler/scala/tools/nsc/symtab/Symbols.scala
index 952ba7e582..ad3f6f9f47 100644
--- a/src/compiler/scala/tools/nsc/symtab/Symbols.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Symbols.scala
@@ -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)
@@ -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
@@ -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)
@@ -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
@@ -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
@@ -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
@@ -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:
@@ -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
@@ -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()
}
@@ -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 + ")"
}
-
}
diff --git a/src/compiler/scala/tools/nsc/symtab/Types.scala b/src/compiler/scala/tools/nsc/symtab/Types.scala
index 6ecf89ad04..f2e413130e 100644
--- a/src/compiler/scala/tools/nsc/symtab/Types.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Types.scala
@@ -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>.
@@ -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 */
@@ -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
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/UnPickler.scala b/src/compiler/scala/tools/nsc/symtab/classfile/UnPickler.scala
index ed09bc2433..5dad581a45 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/UnPickler.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/UnPickler.scala
@@ -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)
}
diff --git a/src/compiler/scala/tools/nsc/transform/Constructors.scala b/src/compiler/scala/tools/nsc/transform/Constructors.scala
index e7a8023c5f..9849af6dcf 100644
--- a/src/compiler/scala/tools/nsc/transform/Constructors.scala
+++ b/src/compiler/scala/tools/nsc/transform/Constructors.scala
@@ -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
}
diff --git a/src/compiler/scala/tools/nsc/transform/Mixin.scala b/src/compiler/scala/tools/nsc/transform/Mixin.scala
index e134c6b72c..82ff45a644 100644
--- a/src/compiler/scala/tools/nsc/transform/Mixin.scala
+++ b/src/compiler/scala/tools/nsc/transform/Mixin.scala
@@ -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 &&
diff --git a/test/files/neg/overload.check b/test/files/neg/overload.check
new file mode 100644
index 0000000000..65e6a9dc81
--- /dev/null
+++ b/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
diff --git a/test/files/neg/overload.scala b/test/files/neg/overload.scala
new file mode 100644
index 0000000000..311ea3874b
--- /dev/null
+++ b/test/files/neg/overload.scala
@@ -0,0 +1,11 @@
+class C {
+ def f(x: int) {}
+}
+
+class D extends C {
+ def f(x: Any) {}
+}
+
+object Test {
+ (new D).f(1)
+}
diff --git a/test/files/pos/bug803.scala b/test/files/pos/bug803.scala
new file mode 100644
index 0000000000..066abecffa
--- /dev/null
+++ b/test/files/pos/bug803.scala
@@ -0,0 +1,2 @@
+class B(x : () => Int)
+class A(i : Int) extends B(() => i) { i }
diff --git a/test/files/pos/bug805.scala b/test/files/pos/bug805.scala
new file mode 100644
index 0000000000..37bf6b5ef8
--- /dev/null
+++ b/test/files/pos/bug805.scala
@@ -0,0 +1,19 @@
+trait MatcherYYY {
+ trait NodeImpl;
+ trait Matchable extends NodeImpl {
+ protected def doMatch : Unit = {}
+ }
+}
+trait BraceMatcherXXX extends MatcherYYY {
+ trait NodeImpl extends super.NodeImpl {
+ def doMatch (braces : BracePair) : Unit
+ }
+ trait BracePair {
+ trait BraceImpl extends NodeImpl with Matchable {
+ override def doMatch : Unit = {
+ super.doMatch;
+ ();
+ }
+ }
+ }
+}
diff --git a/test/files/pos/bug812.scala b/test/files/pos/bug812.scala
new file mode 100644
index 0000000000..ccbe6db5ce
--- /dev/null
+++ b/test/files/pos/bug812.scala
@@ -0,0 +1,7 @@
+package test;
+import scala.{Application => Main};
+class Test extends Main {
+ import test.{Test => Hello}
+ super[Application].executionStart;
+ private[Test] def xxx = 10;
+}
diff --git a/test/files/run/bug789.check b/test/files/run/bug789.check
new file mode 100644
index 0000000000..a98c09dcac
--- /dev/null
+++ b/test/files/run/bug789.check
@@ -0,0 +1,2 @@
+hello size 42
+hello size 42
diff --git a/test/files/run/bug789.scala b/test/files/run/bug789.scala
new file mode 100644
index 0000000000..5a3c8d61e8
--- /dev/null
+++ b/test/files/run/bug789.scala
@@ -0,0 +1,32 @@
+object Test { // don't do this at home
+
+ trait Impl
+
+ trait SizeImpl extends Impl { def size = 42 }
+
+ trait ColorImpl extends Impl { def color = "red" }
+
+ type Both = SizeImpl with ColorImpl
+
+ def info(x:Impl) = x match {
+ case x:Both => "size "+x.size+" color "+x.color // you wish
+ case x:SizeImpl => "size "+x.size
+ case x:ColorImpl => "color "+x.color
+ case _ => "n.a."
+ }
+
+ def info2(x:Impl) = x match {
+ case x:SizeImpl with ColorImpl => "size "+x.size+" color "+x.color // you wish
+ case x:SizeImpl => "size "+x.size
+ case x:ColorImpl => "color "+x.color
+ case _ => "n.a."
+ }
+
+
+ def main(args:Array[String]): Unit = {
+ // make up some class that has a size
+ class MyNode extends SizeImpl
+ Console.println("hello " + info(new MyNode))
+ Console.println("hello " + info2(new MyNode))
+ }
+}