From ca8dccb13512aa9016ec130822ffdd9c8476fb74 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 27 Apr 2006 16:41:32 +0000 Subject: 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) --- .../scala/tools/nsc/CompilationUnits.scala | 5 +- .../scala/tools/nsc/backend/jvm/GenJVM.scala | 17 +---- src/compiler/scala/tools/nsc/symtab/Symbols.scala | 3 + .../scala/tools/nsc/transform/Erasure.scala | 4 +- .../scala/tools/nsc/transform/UnCurry.scala | 2 +- .../scala/tools/nsc/typechecker/Analyzer.scala | 4 +- .../scala/tools/nsc/typechecker/Contexts.scala | 30 +++++---- .../scala/tools/nsc/typechecker/RefChecks.scala | 9 +++ .../tools/nsc/typechecker/SyntheticMethods.scala | 73 +++++++++++----------- .../scala/tools/nsc/typechecker/TreeCheckers.scala | 2 +- .../scala/tools/nsc/typechecker/Typers.scala | 16 ++--- 11 files changed, 84 insertions(+), 81 deletions(-) (limited to 'src/compiler') 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() -- cgit v1.2.3