diff options
author | Paul Phillips <paulp@improving.org> | 2009-10-21 20:57:27 +0000 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2009-10-21 20:57:27 +0000 |
commit | 7349476e5cf7984acf40055cb55d78cbaed41043 (patch) | |
tree | 527229fd0cdab2451fd9feabfcdef2730f9ec453 | |
parent | 322b823276a3f40db95bb3306c842021e77572df (diff) | |
download | scala-7349476e5cf7984acf40055cb55d78cbaed41043.tar.gz scala-7349476e5cf7984acf40055cb55d78cbaed41043.tar.bz2 scala-7349476e5cf7984acf40055cb55d78cbaed41043.zip |
A selection of cleanups stemming from recent in...
A selection of cleanups stemming from recent investigations.
8 files changed, 68 insertions, 55 deletions
diff --git a/src/compiler/scala/tools/nsc/symtab/Symbols.scala b/src/compiler/scala/tools/nsc/symtab/Symbols.scala index 7602696488..a2e30e0cd0 100644 --- a/src/compiler/scala/tools/nsc/symtab/Symbols.scala +++ b/src/compiler/scala/tools/nsc/symtab/Symbols.scala @@ -1172,9 +1172,13 @@ trait Symbols { */ def mixinClasses: List[Symbol] = { val sc = superClass - info.baseClasses.tail.takeWhile(sc ne) + ancestors takeWhile (sc ne) } + /** All directly or indirectly inherited classes. + */ + def ancestors: List[Symbol] = info.baseClasses drop 1 + /** The package containing this symbol, or NoSymbol if there * is not one. */ def enclosingPackage: Symbol = @@ -1308,18 +1312,15 @@ trait Symbols { if (isClassConstructor) NoSymbol else matchingSymbol(ofclazz, ofclazz.thisType) final def allOverriddenSymbols: List[Symbol] = - if (owner.isClass && !owner.info.baseClasses.isEmpty) - for { bc <- owner.info.baseClasses.tail - val s = overriddenSymbol(bc) - if s != NoSymbol } yield s - else List() + if (!owner.isClass) Nil + else owner.ancestors map overriddenSymbol filter (_ != NoSymbol) /** The virtual classes overridden by this virtual class (excluding `clazz' itself) * Classes appear in linearization order (with superclasses before subclasses) */ final def overriddenVirtuals: List[Symbol] = if (isVirtualTrait && hasFlag(OVERRIDE)) - this.owner.info.baseClasses.tail + this.owner.ancestors .map(_.info.decl(name)) .filter(_.isVirtualTrait) .reverse diff --git a/src/compiler/scala/tools/nsc/transform/UnCurry.scala b/src/compiler/scala/tools/nsc/transform/UnCurry.scala index a0afdeabaf..24c5493858 100644 --- a/src/compiler/scala/tools/nsc/transform/UnCurry.scala +++ b/src/compiler/scala/tools/nsc/transform/UnCurry.scala @@ -72,11 +72,11 @@ abstract class UnCurry extends InfoTransform with TypingTransformers { apply(MethodType(List(), restpe)) case PolyType(tparams, restpe) => PolyType(tparams, apply(MethodType(List(), restpe))) - case TypeRef(pre, sym, List(arg)) if (sym == ByNameParamClass) => + case TypeRef(pre, ByNameParamClass, List(arg)) => apply(functionType(List(), arg)) - case TypeRef(pre, sym, args) if (sym == RepeatedParamClass) => + case TypeRef(pre, RepeatedParamClass, args) => apply(appliedType(SeqClass.typeConstructor, args)) - case TypeRef(pre, sym, args) if (sym == JavaRepeatedParamClass) => + case TypeRef(pre, JavaRepeatedParamClass, args) => apply(arrayType( if (isUnboundedGeneric(args.head)) ObjectClass.tpe else args.head)) case _ => @@ -557,12 +557,11 @@ abstract class UnCurry extends InfoTransform with TypingTransformers { inPattern = false val fn1 = transform(fn) inPattern = true - val args1 = transformTrees( - if (fn.symbol.name == nme.unapply) - args - else if (fn.symbol.name == nme.unapplySeq) - transformArgs(tree.pos, fn.symbol, args, analyzer.unapplyTypeListFromReturnTypeSeq(fn.tpe)) - else { assert(false,"internal error: UnApply node has wrong symbol"); null }) + val args1 = transformTrees(fn.symbol.name match { + case nme.unapply => args + case nme.unapplySeq => transformArgs(tree.pos, fn.symbol, args, analyzer.unapplyTypeListFromReturnTypeSeq(fn.tpe)) + case _ => Predef.error("internal error: UnApply node has wrong symbol") + }) treeCopy.UnApply(tree, fn1, args1) case Apply(fn, args) => @@ -619,7 +618,7 @@ abstract class UnCurry extends InfoTransform with TypingTransformers { } setType uncurryTreeType(tree.tpe) def postTransform(tree: Tree): Tree = atPhase(phase.next) { - def applyUnary(tree: Tree): Tree = + def applyUnary(): Tree = if (tree.symbol.isMethod && (!tree.tpe.isInstanceOf[PolyType] || tree.tpe.typeParams.isEmpty)) { if (!tree.tpe.isInstanceOf[MethodType]) tree.tpe = MethodType(List(), tree.tpe); @@ -666,11 +665,9 @@ abstract class UnCurry extends InfoTransform with TypingTransformers { treeCopy.Apply(tree, fn, args ::: args1) case Ident(name) => assert(name != nme.WILDCARD_STAR.toTypeName) - applyUnary(tree); - case Select(qual, name) => - applyUnary(tree) - case TypeApply(_, _) => - applyUnary(tree) + applyUnary() + case Select(_, _) | TypeApply(_, _) => + applyUnary() case Return(expr) if (tree.symbol != currentOwner.enclMethod || currentOwner.hasFlag(LAZY)) => if (settings.debug.value) log("non local return in "+tree.symbol+" from "+currentOwner.enclMethod) atPos(tree.pos)(nonLocalReturnThrow(expr, tree.symbol)) diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala index 76e4818a72..54b24bf071 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala @@ -624,7 +624,7 @@ self: Analyzer => case TypeRef(pre, sym, args) if (!sym.isPackageClass) => if (sym.isClass && !sym.isRefinementClass && !sym.isAnonymousClass) { if (addType(tp)) { - for (bc <- sym.info.baseClasses.tail) + for (bc <- sym.ancestors) getParts(tp.baseType(bc)) getParts(pre) args foreach getParts diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala index 5b1ec93ffb..c619f08ce3 100644 --- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala +++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala @@ -374,7 +374,7 @@ abstract class RefChecks extends InfoTransform { // 4. Check that every defined member with an `override' modifier overrides some other member. for (member <- clazz.info.decls.toList) if ((member hasFlag (OVERRIDE | ABSOVERRIDE)) && - (clazz.info.baseClasses.tail forall { + (clazz.ancestors forall { bc => member.matchingSymbol(bc, clazz.thisType) == NoSymbol })) { // for (bc <- clazz.info.baseClasses.tail) Console.println("" + bc + " has " + bc.info.decl(member.name) + ":" + bc.info.decl(member.name).tpe);//DEBUG diff --git a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala index 4fa66a242b..e3d75752f2 100644 --- a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala +++ b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala @@ -226,7 +226,7 @@ trait SyntheticMethods extends ast.TreeDSL { if (!phase.erasedTypes) try { if (clazz hasFlag Flags.CASE) { - val isTop = !(clazz.info.baseClasses.tail exists (_ hasFlag Flags.CASE)) + val isTop = !(clazz.ancestors exists (_ hasFlag Flags.CASE)) // case classes are implicitly declared serializable clazz addAnnotation AnnotationInfo(SerializableAttr.tpe, Nil, Nil) diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 7307a0d379..b81c087901 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -879,23 +879,16 @@ trait Typers { self: Analyzer => if (extractor != NoSymbol) { tree setSymbol extractor val unapply = unapplyMember(extractor.tpe) - val clazz = if (unapply.tpe.paramTypes.length == 1) unapply.tpe.paramTypes.head.typeSymbol - else NoSymbol - if ((unapply hasFlag CASE) && (clazz hasFlag CASE) && - !(clazz.info.baseClasses.tail exists (_ hasFlag CASE))) { - if (!phase.erasedTypes) checkStable(tree) //todo: do we need to demand this? + val clazz = unapplyParameterType(unapply) + + if ((unapply hasFlag CASE) && (clazz hasFlag CASE) && !(clazz.ancestors exists (_ hasFlag CASE))) { + if (!phase.erasedTypes) checkStable(tree) // todo: do we need to demand this? // convert synthetic unapply of case class to case class constructor val prefix = tree.tpe.prefix val tree1 = TypeTree(clazz.primaryConstructor.tpe.asSeenFrom(prefix, clazz.owner)) .setOriginal(tree) - try { - inferConstructorInstance(tree1, clazz.typeParams, pt) - } catch { - case tpe : TypeError => throw tpe - case t : Exception => - logError("CONTEXT: " + (tree.pos).dbgString, t) - throw t - } + + inferConstructorInstance(tree1, clazz.typeParams, pt) tree1 } else { tree @@ -1051,6 +1044,20 @@ trait Typers { self: Analyzer => typed(cbody) } + private def validateNoCaseAncestor(clazz: Symbol) = { + // XXX I think this should issue a sharper warning of some kind like + // "change your code now!" as there are material bugs (which are very unlikely + // to be fixed) associated with case class inheritance. + if (!phase.erasedTypes) { + for (ancestor <- clazz.ancestors find (_ hasFlag CASE)) + unit.deprecationWarning(clazz.pos, ( + "case class `%s' has case class ancestor `%s'. This has been deprecated " + + "for unduly complicating both usage and implementation. You should instead " + + "use extractors for pattern matching on non-leaf nodes." ).format(clazz, ancestor) + ) + } + } + def parentTypes(templ: Template): List[Tree] = if (templ.parents.isEmpty) List() else try { @@ -1177,17 +1184,6 @@ trait Typers { self: Analyzer => if (psym hasFlag FINAL) { error(parent.pos, "illegal inheritance from final "+psym) } - // XXX I think this should issue a sharper warning of some kind like - // "change your code now!" as there are material bugs (which will not be fixed) - // associated with case class inheritance. - if ((context.owner hasFlag CASE) && !phase.erasedTypes) { - for (ancestor <- parent.tpe.baseClasses find (_ hasFlag CASE)) - unit.deprecationWarning(parent.pos, ( - "case class `%s' has case class ancestor `%s'. This has been deprecated " + - "for unduly complicating both usage and implementation. You should instead " + - "use extractors for pattern matching on non-leaf nodes." ).format(context.owner, ancestor) - ) - } if (psym.isSealed && !phase.erasedTypes) { if (context.unit.source.file != psym.sourceFile) error(parent.pos, "illegal inheritance from sealed "+psym) @@ -1435,6 +1431,9 @@ trait Typers { self: Analyzer => assert(clazz.info.decls != EmptyScope) enterSyms(context.outer.make(templ, clazz, clazz.info.decls), templ.body) validateParentClasses(parents1, selfType) + if (clazz hasFlag CASE) + validateNoCaseAncestor(clazz) + if ((clazz isSubClass ClassfileAnnotationClass) && !clazz.owner.isPackageClass) unit.error(clazz.pos, "inner classes cannot be classfile annotations") if (!phase.erasedTypes && !clazz.info.resultType.isError) // @S: prevent crash for duplicated type members @@ -1897,7 +1896,7 @@ trait Typers { self: Analyzer => val stats1 = typedStats(stats, NoSymbol) for (stat <- stats1 if stat.isDef) { val member = stat.symbol - if (!(context.owner.info.baseClasses.tail forall + if (!(context.owner.ancestors forall (bc => member.matchingSymbol(bc, context.owner.thisType) == NoSymbol))) { member setFlag OVERRIDE } @@ -3945,8 +3944,22 @@ trait Typers { self: Analyzer => typed(tree, EXPRmode | FUNmode | POLYmode | TAPPmode, WildcardType) /** Types a pattern with prototype <code>pt</code> */ - def typedPattern(tree: Tree, pt: Type): Tree = + def typedPattern(tree: Tree, pt: Type): Tree = { + // The commented out code stems from investigation into whether + // "abc" match { case Seq('a', 'b', 'c') => true } + // can be ruled out statically. At present this is a runtime + // error both because there is an implicit from String to Seq + // (even though such implicits are not used by the matcher) and + // because the typer is fine with concluding that "abc" might + // be of type "String with Seq[T]" and thus eligible for a call + // to unapplySeq. + // + // val savedImplicitsEnabled = context.implicitsEnabled + // context.implicitsEnabled = false + // try typed(tree, PATTERNmode, pt) + // finally context.implicitsEnabled = savedImplicitsEnabled + } /** Types a (fully parameterized) type tree */ def typedType(tree: Tree, mode: Int): Tree = diff --git a/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala b/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala index b586298560..262e648e39 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala @@ -92,6 +92,12 @@ trait Unapplies extends ast.TreeDSL case NoSymbol => tp member nme.unapplySeq case unapp => unapp } + /** returns unapply member's parameter type. */ + def unapplyParameterType(extractor: Symbol) = { + val tps = extractor.tpe.paramTypes + if (tps.length == 1) tps.head.typeSymbol + else NoSymbol + } def copyUntyped[T <: Tree](tree: T): T = returning[T](UnTyper traverse _)(tree.duplicate) diff --git a/src/library/scala/collection/immutable/Stream.scala b/src/library/scala/collection/immutable/Stream.scala index 9550aec2ef..1d9adeab1c 100644 --- a/src/library/scala/collection/immutable/Stream.scala +++ b/src/library/scala/collection/immutable/Stream.scala @@ -79,10 +79,6 @@ self => this } - /** Does this stream have more than one elements defined? - */ - private def hasMoreThanOneElements = false - /** Prints elements of this stream one by one, separated by commas */ def print() { print(", ") } |