summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2006-04-27 16:41:32 +0000
committerMartin Odersky <odersky@gmail.com>2006-04-27 16:41:32 +0000
commitca8dccb13512aa9016ec130822ffdd9c8476fb74 (patch)
tree9f3704fd7b5ae22b61f3cf3746486fc8594180a2
parent0b47ca3e5bb8d724240b49b970f4017d6a8798a9 (diff)
downloadscala-ca8dccb13512aa9016ec130822ffdd9c8476fb74.tar.gz
scala-ca8dccb13512aa9016ec130822ffdd9c8476fb74.tar.bz2
scala-ca8dccb13512aa9016ec130822ffdd9c8476fb74.zip
1. fixed bugs 578+579
2. optimization: don't emit any code guarded by an if which is constant-false 3. Changed treatment of startContext to get rid of -nopredefs (but no success there yet)
-rw-r--r--src/compiler/scala/tools/nsc/CompilationUnits.scala5
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala17
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Symbols.scala3
-rw-r--r--src/compiler/scala/tools/nsc/transform/Erasure.scala4
-rw-r--r--src/compiler/scala/tools/nsc/transform/UnCurry.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Analyzer.scala4
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Contexts.scala30
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala9
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala73
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala16
-rw-r--r--test/pending/pos/bug577.scala21
-rw-r--r--test/pending/pos/bug579.scala15
13 files changed, 120 insertions, 81 deletions
diff --git a/src/compiler/scala/tools/nsc/CompilationUnits.scala b/src/compiler/scala/tools/nsc/CompilationUnits.scala
index 60799c3c37..64a3cc97b1 100644
--- a/src/compiler/scala/tools/nsc/CompilationUnits.scala
+++ b/src/compiler/scala/tools/nsc/CompilationUnits.scala
@@ -13,10 +13,7 @@ import scala.collection.mutable.HashSet;
trait CompilationUnits requires Global {
- class CompilationUnit(val source: SourceFile, val mixinOnly: boolean) {
-
- /** short constructor */
- def this(source: SourceFile) = this(source, false);
+ class CompilationUnit(val source: SourceFile) {
/** the fresh name creator */
val fresh = new FreshNameCreator;
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
index 3bff265aff..f3aa7e29cb 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
@@ -60,7 +60,6 @@ abstract class GenJVM extends SubComponent {
// Scala attributes
val SerializableAttr = definitions.SerializableAttr.tpe;
- val BeanPropertyAttr = definitions.BeanPropertyAttr.tpe;
val SerialVersionUID = definitions.getClass("scala.SerialVersionUID").tpe;
val CloneableAttr = definitions.getClass("scala.cloneable").tpe;
val TransientAtt = definitions.getClass("scala.transient").tpe;
@@ -966,21 +965,7 @@ abstract class GenJVM extends SubComponent {
(if (sym.isClass || (sym.isModule && !sym.isMethod))
sym.fullNameString('/')
else
- {
- if ( sym.hasFlag(Flags.ACCESSOR) && sym.attributes.exists(a => a match{
- case Pair(BeanPropertyAttr, _) => true
- case _ => false
- }))
- {
- if (sym.isSetter)
- "set" + nme.setterToGetter(sym.simpleName).toString()
- else "get" + sym.simpleName.toString()
- }
- else {
- sym.simpleName.toString()
- }.trim()
- }
- ) + suffix;
+ sym.simpleName.toString().trim()) + suffix
}
def javaNames(syms: List[Symbol]): Array[String] = {
diff --git a/src/compiler/scala/tools/nsc/symtab/Symbols.scala b/src/compiler/scala/tools/nsc/symtab/Symbols.scala
index 08df424779..613470c975 100644
--- a/src/compiler/scala/tools/nsc/symtab/Symbols.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Symbols.scala
@@ -271,6 +271,9 @@ trait Symbols requires SymbolTable {
}
);
+ final def exists: boolean =
+ this != NoSymbol && (!owner.isPackageClass || { rawInfo.load(this); rawInfo != NoType });
+
final def isInitialized: boolean =
validForRun == currentRun;
diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala
index 45367bf440..50c1ee16be 100644
--- a/src/compiler/scala/tools/nsc/transform/Erasure.scala
+++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala
@@ -613,9 +613,7 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer {
atPhase(phase.next) {
val tree2 = mixinTransformer.transform(tree1);
if (settings.debug.value) log("tree after addinterfaces: \n" + tree2);
- newTyper(startContext.make(
- unit, tree, startContext.owner, startContext.scope, startContext.imports))
- .typed(tree2)
+ newTyper(rootContext(unit, tree, true)).typed(tree2)
}
}
}
diff --git a/src/compiler/scala/tools/nsc/transform/UnCurry.scala b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
index cd1a9959dd..d2955bf9e5 100644
--- a/src/compiler/scala/tools/nsc/transform/UnCurry.scala
+++ b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
@@ -72,7 +72,7 @@ abstract class UnCurry extends InfoTransform {
private var needTryLift = false;
private var inPattern = false;
private var inConstructorFlag = 0L;
- private var localTyper: analyzer.Typer = analyzer.newTyper(analyzer.startContext.make(unit));
+ private var localTyper: analyzer.Typer = analyzer.newTyper(analyzer.rootContext(unit));
override def transform(tree: Tree): Tree = try { //debug
postTransform(mainTransform(tree));
diff --git a/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala b/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala
index 56d4d4bd4c..ee666c8e49 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala
@@ -25,7 +25,7 @@ trait Analyzer
val phaseName = "namer";
def newPhase(_prev: Phase): StdPhase = new StdPhase(_prev) {
def apply(unit: CompilationUnit): unit =
- new Namer(startContext.make(unit)).enterSym(unit.body);
+ new Namer(rootContext(unit)).enterSym(unit.body);
}
}
@@ -35,7 +35,7 @@ trait Analyzer
def newPhase(_prev: Phase): StdPhase = new StdPhase(_prev) {
resetTyper;
def apply(unit: CompilationUnit): unit =
- unit.body = newTyper(startContext.make(unit)).typed(unit.body)
+ unit.body = newTyper(rootContext(unit)).typed(unit.body)
}
}
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
index d823c7081f..215d338e3e 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
@@ -17,19 +17,23 @@ trait Contexts requires Analyzer {
NoContext.enclClass = NoContext;
NoContext.enclMethod = NoContext;
- val startContext = {
+ private val startContext = NoContext.make(
+ Template(List(), List()) setSymbol NoSymbol setType NoType,
+ definitions.RootClass,
+ definitions.RootClass.info.decls);
+
+ def rootContext(unit: CompilationUnit): Context = rootContext(unit, EmptyTree, false);
+
+ def rootContext(unit: CompilationUnit, tree: Tree, erasedTypes: boolean): Context = {
import definitions._;
- var sc = NoContext.make(
- Template(List(), List()) setSymbol NoSymbol setType NoType,
- definitions.RootClass,
- definitions.RootClass.info.decls);
+ var sc = startContext;
def addImport(pkg: Symbol): unit = {
- assert(pkg != null, "package is null");
+ assert(pkg != null);
val qual = gen.mkStableRef(pkg);
sc = sc.makeNewImport(
- Import(qual, List(Pair(nme.WILDCARD, null)))
- setSymbol NoSymbol.newImport(Position.NOPOS).setInfo(ImportType(qual))
- setType NoType);
+ Import(qual, List(Pair(nme.WILDCARD, null)))
+ .setSymbol(NoSymbol.newImport(Position.NOPOS).setInfo(ImportType(qual)))
+ .setType(NoType));
sc.depth = sc.depth + 1
}
if (!settings.noimports.value) {
@@ -37,10 +41,14 @@ trait Contexts requires Analyzer {
addImport(JavaLangPackage);
assert(ScalaPackage != null, "Scala package is null");
addImport(ScalaPackage);
- if (!settings.nopredefs.value)
+ if (!settings.nopredefs.value/* || unit.source.file.name != "Predef.scala"*/)
addImport(PredefModule);
}
- sc
+ val c = sc.make(unit, tree, sc.owner, sc.scope, sc.imports);
+ c.reportAmbiguousErrors = !erasedTypes;
+ c.reportGeneralErrors = !erasedTypes;
+ c.implicitsEnabled = !erasedTypes;
+ c
}
def resetContexts: unit = {
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
index ea640cc661..386d369d71 100644
--- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
@@ -25,6 +25,7 @@ import transform.InfoTransform;
* - Calls to case factory methods are replaced by new's.
* - References to parameter accessors with aliases are replaced by super references to
* these aliases.
+ * - eliminate branches in a conditional if the condition is a constant
*/
abstract class RefChecks extends InfoTransform {
@@ -579,6 +580,14 @@ abstract class RefChecks extends InfoTransform {
isIrrefutable(pat1, tpt.tpe)) =>
result = qual
+ case If(cond, thenpart, elsepart) =>
+ cond.tpe match {
+ case ConstantType(value) =>
+ result = if (value.booleanValue) thenpart else elsepart;
+ if (result == EmptyTree) result = Literal(()).setPos(tree.pos).setType(UnitClass.tpe)
+ case _ =>
+ }
+
case New(tpt) =>
enterReference(tree.pos, tpt.tpe.symbol);
diff --git a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
index 306dad37c6..cc0f89f4ea 100644
--- a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
@@ -149,45 +149,48 @@ trait SyntheticMethods requires Analyzer {
else Apply(gen.mkRef(sym), List(Ident(vparamss.head.head)))))
}
- if ((clazz hasFlag CASE) && !phase.erasedTypes) {
- // case classes are implicitly declared serializable
- clazz.attributes = Pair(SerializableAttr.tpe, List()) :: clazz.attributes;
-
- for (val stat <- templ.body) {
- if (stat.isDef && stat.symbol.isMethod && stat.symbol.hasFlag(CASEACCESSOR) &&
- (stat.symbol.hasFlag(PRIVATE | PROTECTED) || stat.symbol.privateWithin != NoSymbol)) {
- ts += newAccessorMethod(stat);
- stat.symbol.resetFlag(CASEACCESSOR)
+ if (!phase.erasedTypes) {
+
+ if (clazz hasFlag CASE) {
+ // case classes are implicitly declared serializable
+ clazz.attributes = Pair(SerializableAttr.tpe, List()) :: clazz.attributes;
+
+ for (val stat <- templ.body) {
+ if (stat.isDef && stat.symbol.isMethod && stat.symbol.hasFlag(CASEACCESSOR) &&
+ (stat.symbol.hasFlag(PRIVATE | PROTECTED) || stat.symbol.privateWithin != NoSymbol)) {
+ ts += newAccessorMethod(stat);
+ stat.symbol.resetFlag(CASEACCESSOR)
+ }
}
- }
- ts += tagMethod;
- if (clazz.isModuleClass) {
- if (!hasImplementation(nme.toString_)) ts += moduleToStringMethod;
- } else {
- if (!hasImplementation(nme.hashCode_)) ts += forwardingMethod(nme.hashCode_);
- if (!hasImplementation(nme.toString_)) ts += forwardingMethod(nme.toString_);
- if (!hasImplementation(nme.equals_)) ts += forwardingMethod(nme.equals_);
+ ts += tagMethod;
+ if (clazz.isModuleClass) {
+ if (!hasImplementation(nme.toString_)) ts += moduleToStringMethod;
+ } else {
+ if (!hasImplementation(nme.hashCode_)) ts += forwardingMethod(nme.hashCode_);
+ if (!hasImplementation(nme.toString_)) ts += forwardingMethod(nme.toString_);
+ if (!hasImplementation(nme.equals_)) ts += forwardingMethod(nme.equals_);
+ }
+ if (!hasImplementation(nme.caseElement)) ts += caseElementMethod;
+ if (!hasImplementation(nme.caseArity)) ts += caseArityMethod;
+ if (!hasImplementation(nme.caseName)) ts += caseNameMethod;
}
- if (!hasImplementation(nme.caseElement)) ts += caseElementMethod;
- if (!hasImplementation(nme.caseArity)) ts += caseArityMethod;
- if (!hasImplementation(nme.caseName)) ts += caseNameMethod;
- }
- if (!phase.erasedTypes && clazz.isModuleClass && isSerializable(clazz)) {
- // If you serialize a singleton and then deserialize it twice,
- // you will have two instances of your singleton, unless you implement
- // the readResolve() method (see http://www.javaworld.com/javaworld/
- // jw-04-2003/jw-0425-designpatterns_p.html)
- if (!hasImplementation(nme.readResolve)) ts += readResolveMethod;
+ if (clazz.isModuleClass && isSerializable(clazz)) {
+ // If you serialize a singleton and then deserialize it twice,
+ // you will have two instances of your singleton, unless you implement
+ // the readResolve() method (see http://www.javaworld.com/javaworld/
+ // jw-04-2003/jw-0425-designpatterns_p.html)
+ if (!hasImplementation(nme.readResolve)) ts += readResolveMethod;
+ }
+ for (val sym <- clazz.info.decls.toList)
+ if (!sym.getAttributes(BeanPropertyAttr).isEmpty)
+ if (sym.isGetter)
+ addBeanGetterMethod(sym)
+ else if (sym.isSetter)
+ addBeanSetterMethod(sym)
+ else if (sym.isMethod || sym.isType)
+ unit.error(sym.pos, "attribute `BeanProperty' is not applicable to " + sym);
}
- for (val sym <- clazz.info.decls.toList)
- if (!sym.getAttributes(BeanPropertyAttr).isEmpty)
- if (sym.isGetter)
- addBeanGetterMethod(sym)
- else if (sym.isSetter)
- addBeanSetterMethod(sym)
- else if (sym.isMethod || sym.isType)
- unit.error(sym.pos, "attribute `BeanProperty' is not applicable to " + sym);
val synthetics = ts.toList;
copy.Template(
templ, templ.parents, if (synthetics.isEmpty) templ.body else templ.body ::: synthetics)
diff --git a/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala b/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala
index b494e1c33f..5b5fc31e5b 100644
--- a/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala
@@ -29,7 +29,7 @@ abstract class TreeCheckers extends Analyzer {
ret;
} else false;
- val context = startContext.make(unit);
+ val context = rootContext(unit);
context.checking = true;
tpeOfTree.clear;
val checker = new TreeChecker(context);
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 68763b2a09..9680a32292 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -1156,7 +1156,7 @@ trait Typers requires Analyzer {
val qual1 = adaptToName(qual, name)
if (qual1 ne qual) return typed(copy.Select(tree, qual1, name), mode, pt)
}
- if (sym.info == NoType) {
+ if (!sym.exists) {
if (settings.debug.value) System.err.println("qual = "+qual+":"+qual.tpe+"\nSymbol="+qual.tpe.symbol+"\nsymbol-info = "+qual.tpe.symbol.info+"\nscope-id = "+qual.tpe.symbol.info.decls.hashCode()+"\nmembers = "+qual.tpe.members+"\nfound = "+sym)
if (!qual.tpe.widen.isErroneous) {
if (context.unit == null) assert(false, "("+qual+":"+qual.tpe+")."+name)
@@ -1198,12 +1198,12 @@ trait Typers requires Analyzer {
//if (phase.name == "uncurry") System.out.println("typing " + name + " " + cx.owner + " " + (if (cx.enclClass == null) "null" else cx.enclClass.owner));//DEBUG
pre = cx.enclClass.prefix
defEntry = cx.scope.lookupEntry(name)
- if (defEntry != null && defEntry.sym.tpe != NoType) {
+ if (defEntry != null && defEntry.sym.exists) {
defSym = defEntry.sym
} else {
cx = cx.enclClass
defSym = pre.member(name) filter (
- sym => sym.tpe != NoType && context.isAccessible(sym, pre, false))
+ sym => sym.exists && context.isAccessible(sym, pre, false))
if (defSym == NoSymbol) cx = cx.outer
}
}
@@ -1223,14 +1223,14 @@ trait Typers requires Analyzer {
// imported symbols take precedence over package-owned symbols in different
// compilation units
- if (defSym.tpe != NoType && impSym.tpe != NoType &&
+ if (defSym.exists && impSym.exists &&
defSym.owner.isPackageClass &&
(!currentRun.compiles(defSym) ||
context.unit != null && defSym.sourceFile != context.unit.source.file))
defSym = NoSymbol
- if (defSym.tpe != NoType) {
- if (impSym.tpe != NoType)
+ if (defSym.exists) {
+ if (impSym.exists)
ambiguousError(
"it is both defined in "+defSym.owner +
" and imported subsequently by \n"+imports.head)
@@ -1239,7 +1239,7 @@ trait Typers requires Analyzer {
else
qual = atPos(tree.pos)(gen.mkQualifier(pre))
} else {
- if (impSym.tpe != NoType) {
+ if (impSym.exists) {
var impSym1 = NoSymbol
var imports1 = imports.tail
def ambiguousImport() = {
@@ -1251,7 +1251,7 @@ trait Typers requires Analyzer {
(!imports.head.isExplicitImport(name) ||
imports1.head.depth == imports.head.depth)) {
var impSym1 = imports1.head.importedSymbol(name)
- if (impSym1 != NoSymbol) {
+ if (impSym1.exists) {
if (imports1.head.isExplicitImport(name)) {
if (imports.head.isExplicitImport(name) ||
imports1.head.depth != imports.head.depth) ambiguousImport()
diff --git a/test/pending/pos/bug577.scala b/test/pending/pos/bug577.scala
new file mode 100644
index 0000000000..ede45399a0
--- /dev/null
+++ b/test/pending/pos/bug577.scala
@@ -0,0 +1,21 @@
+trait PriorityTree {
+ type Node <: BasicTreeNode;
+
+ val top = initTree;
+ top.next = (initTree);
+ top.next.prev = (top);
+
+ def initTree : Node;
+
+
+
+
+ trait BasicTreeNode {
+ private[PriorityTree] var next : Node = _;
+ private[PriorityTree] var prev : Node = _;
+ private[PriorityTree] var chld : Node = _;
+ //var next : Node = _;
+ //var prev : Node = _;
+ //var chld : Node = _;
+ }
+}
diff --git a/test/pending/pos/bug579.scala b/test/pending/pos/bug579.scala
new file mode 100644
index 0000000000..9b4575835b
--- /dev/null
+++ b/test/pending/pos/bug579.scala
@@ -0,0 +1,15 @@
+package my.webapp.bean.stuff;
+
+import scala.reflect.BeanProperty
+
+class MyBean {
+ [BeanProperty]
+ var frombulizer: String = _;
+}
+
+object Test extends Application {
+
+ val x = new MyBean;
+ x.frombulizer = "hello"
+
+}