diff --git a/config/list/library.lst b/config/list/library.lst index f3d82effe..f1ad7ba66 100644 --- a/config/list/library.lst +++ b/config/list/library.lst @@ -37,12 +37,12 @@ MatchError.java Monitor.scala Nil.scala None.scala -Object.java Option.scala Ord.scala PartialFunction.scala Predef.scala Ref.java +ScalaObject.java Seq.scala Short.java Some.scala @@ -110,7 +110,6 @@ collection/immutable/Queue.scala collection/immutable/Set.scala collection/immutable/Stack.scala -concurrent/LinkedList.scala concurrent/Actor.scala concurrent/MailBox.scala concurrent/Channel.scala diff --git a/doc/reference/ScalaByExample.tex b/doc/reference/ScalaByExample.tex index 90c45145a..786d83611 100644 --- a/doc/reference/ScalaByExample.tex +++ b/doc/reference/ScalaByExample.tex @@ -1409,17 +1409,18 @@ Every class in Scala has a superclass which it extends. only the root class \code{Object}, which does not have a superclass, and which is indirectly extended by every other class. } If a class -does not mention a superclass in its definition, the root class -\code{scala.Object} is implicitly assumed. For instance, class +does not mention a superclass in its definition, the root type +\code{scala.AnyRef} is implicitly assumed (for Java implementations, +this type is an alias for \code{java.lang.Object}. For instance, class \code{Rational} could equivalently be defined as \begin{lstlisting} -class Rational(n: int, d: int) extends Object { +class Rational(n: int, d: int) extends AnyRef { ... // as before } \end{lstlisting} A class inherits all members from its superclass. It may also redefine (or: {\em override}) some inherited members. For instance, class -\code{Object} defines +\code{java.lang.Object} defines a method \code{toString} which returns a representation of the object as a string: \begin{lstlisting} @@ -1433,7 +1434,7 @@ forms a string consisting of the object's class name and a number. It makes sense to redefine this method for objects that are rational numbers: \begin{lstlisting} -class Rational(n: int, d: int) extends Object { +class Rational(n: int, d: int) extends AnyRef { ... // as before override def toString() = "" + numer + "/" + denom; } @@ -1444,10 +1445,10 @@ by an \code{override} modifier. If class $A$ extends class $B$, then objects of type $A$ may be used wherever objects of type $B$ are expected. We say in this case that type $A$ {\em conforms} to type $B$. For instance, \code{Rational} -conforms to \code{Object}, so it is legal to assign a \code{Rational} -value to a variable of type \code{Object}: +conforms to \code{AnyRef}, so it is legal to assign a \code{Rational} +value to a variable of type \code{AnyRef}: \begin{lstlisting} -var x: Object = new Rational(1,2); +var x: AnyRef = new Rational(1,2); \end{lstlisting} \paragraph{Parameterless Methods} @@ -1462,7 +1463,7 @@ Unlike in Java, methods in Scala do not necessarily take a parameter list. An example is the \code{square} method below. This method is invoked by simply mentioning its name. \begin{lstlisting} -class Rational(n: int, d: int) extends Object { +class Rational(n: int, d: int) extends AnyRef { ... // as before def square = Rational(numer*numer, denom*denom); } @@ -1665,8 +1666,8 @@ For efficiency, the compiler usually represents values of type \code{scala.Int} by 32 bit integers, values of type \code{scala.Boolean} by Java's booleans, etc. But it converts these specialized representations to objects when required, for instance -when a primitive \code{int} value is passed to a function that with a -parameter of type \code{Object}. Hence, the special representation of +when a primitive \code{int} value is passed to a function with a +parameter of type \code{AnyRef}. Hence, the special representation of primitive values is just an optimization, it does not change the meaning of a program. @@ -2032,7 +2033,7 @@ Sum(Sum(Number(1), Number(2)), Number(3)) \item Case classes and case objects implicity come with implementations of methods \code{toString}, \code{equals} and \code{hashCode}, which override the -methods with the same name in class \code{Object}. The implementation +methods with the same name in class \code{AnyRef}. The implementation of these methods takes in each case the structure of a member of a case class into account. The \code{toString} method represents an expression tree the way it was constructed. So, @@ -2040,7 +2041,7 @@ expression tree the way it was constructed. So, Sum(Sum(Number(1), Number(2)), Number(3)) \end{lstlisting} would be converted to exactly that string, whereas the default -implementation in class \code{Object} would return a string consisting +implementation in class \code{AnyRef} would return a string consisting of the outermost constructor name \code{Sum} and a number. The \code{equals} methods treats two case members of a case class as equal if they have been constructed with the same constructor and with @@ -2052,7 +2053,7 @@ Sum(Number(1), Number(2)) == Sum(Number(1), Number(2)) \end{lstlisting} will yield \code{true}. If \code{Sum} or \code{Number} were not case classes, the same expression would be \code{false}, since the standard -implementation of \code{equals} in class \code{Object} always treats +implementation of \code{equals} in class \code{AnyRef} always treats objects created by different constructor calls as being different. The \code{hashCode} method follows the same principle as other two methods. It computes a hash code from the case class constructor name @@ -2435,9 +2436,9 @@ trait Ord[t <: Ord[t]]: t { The combination of type parameters and subtyping poses some interesting questions. For instance, should \code{Stack[String]} be a -subtype of \code{Stack[Object]}? Intuitively, this seems OK, since a +subtype of \code{Stack[AnyRef]}? Intuitively, this seems OK, since a stack of \code{String}s is a special case of a stack of -\code{Object}s. More generally, if \code{T} is a subtype of type \code{S} +\code{AnyRef}s. More generally, if \code{T} is a subtype of type \code{S} then \code{Stack[T]} should be a subtype of \code{Stack[S]}. This property is called {\em co-variant} subtyping. @@ -2568,9 +2569,9 @@ also have generalized the definition of \code{push}. Before, we were required to push only elements with types that conform to the declared element type of the stack. Now, we can push also elements of a supertype of this type, but the type of the returned stack will change -accordingly. For instance, we can now push an \code{Object} onto a +accordingly. For instance, we can now push an \code{AnyRef} onto a stack of \code{String}s, but the resulting stack will be a stack of -\code{Object}s instead of a stack of \code{String}s! +\code{AnyRef}s instead of a stack of \code{String}s! In summary, one should not hesitate to add variance annotations to your data structures, as this yields rich natural subtyping @@ -2594,7 +2595,7 @@ which is a subtype of all other types. Hence, for co-variant stacks, \code{T}. This makes it possible to use a single empty stack object in user code. For instance: \begin{lstlisting} -val s = EmptyStack.push("abc").push(new Object()); +val s = EmptyStack.push("abc").push(new AnyRef()); \end{lstlisting} Let's analyze the type assignment for this expression in detail. The \code{EmptyStack} object is of type \code{Stack[All]}, which has a @@ -2610,10 +2611,10 @@ should be instantiated to \code{String} in the application push[b >: String](elem: b): Stack[b] . \end{lstlisting} The final part of the value definition above is the application of -this method to \code{new Object()}. Local type inference will +this method to \code{new AnyRef()}. Local type inference will determine that the type parameter \code{b} should this time be -instantiated to \code{Object}, with result type \code{Stack[Object]}. -Hence, the type assigned to value \code{s} is \code{Stack[Object]}. +instantiated to \code{AnyRef}, with result type \code{Stack[AnyRef]}. +Hence, the type assigned to value \code{s} is \code{Stack[AnyRef]}. Besides \code{scala.All}, which is a subtype of every other type, there is also the type \code{scala.AllRef}, which is a subtype of @@ -2733,12 +2734,12 @@ shorthand for \code{a.apply(i)}. Functions are an example where a contra-variant type parameter declaration is useful. For example, consider the following code: \begin{lstlisting} -val f: (Object => int) = x => x.hashCode(); +val f: (AnyRef => int) = x => x.hashCode(); val g: (String => int) = f g("abc") \end{lstlisting} It's sound to bind the value \code{g} of type \code{String => int} to -\code{f}, which is of type \code{Object => int}. Indeed, all one can +\code{f}, which is of type \code{AnyRef => int}. Indeed, all one can do with function of type \code{String => int} is pass it a string in order to obtain an integer. Clearly, the same works for function \code{f}: If we pass it a string (or any other object), we obtain an @@ -5714,7 +5715,7 @@ TypeScheme(List(TyVar("a"), TyVar("b")), Arrow(Tyvar("a"), Tyvar("b"))) . \end{lstlisting} The class definition of type schemes does not carry an extends clause; this means that type schemes extend directly class -\code{Object}. Even though there is only one possible way to +\code{AnyRef}. Even though there is only one possible way to construct a type scheme, a case class representation was chosen since it offers convenient ways to decompose an instance of this type into its parts. @@ -6101,7 +6102,7 @@ time, only one thread can execute a \code{synchronized} argument of a given monitor. Threads can suspend inside a monitor by waiting on a signal. The -standard \code{java.lang.Object} class offers for this prupose methods +standard \code{java.lang.Object} class offers for this purpose methods \code{send} and \code{notify}. Threads that call the \code{wait} method wait until a \code{notify} method of the same object is called subsequently by some other thread. Calls to \code{notify} with no @@ -6629,7 +6630,7 @@ one for sent but unconsumed messages, the other for waiting receivers. if (r1 != null) { r.next = r1.next; r1.elem.msg = msg; r1.elem.notify; } else { - lastSent = lastSent.insert(msg); + lastSent = insert(lastSent, msg); } } \end{lstlisting} @@ -6646,7 +6647,7 @@ Otherwise, the message is appended to the linked list of sent messages. if (s1 != null) { s.next = s1.next; s1.elem } else { - val r = lastReceiver.insert(new Receiver { + val r = insert(lastReceiver, new Receiver { def isDefined(msg: Any) = f.isDefinedAt(msg); }); lastReceiver = r; @@ -6663,8 +6664,16 @@ was not yet consumed. If yes, the thread continues immediately by applying \code{f} to the message. Otherwise, a new receiver is created and linked into the \code{receivers} list, and the thread waits for a notification on this receiver. Once the thread is woken up again, it -continues by applying \code{f} to the message that was stored in the receiver. - +continues by applying \code{f} to the message that was stored in the +receiver. The insert method on linked lists is defined as follows. +\begin{lstlisting} + def insert(l: LinkedList[a], x: a): LinkedList[a] = { + l.next = new LinkedList[a]; + l.next.elem = x; + l.next.next = l.next; + l + } +\end{lstlisting} The mailbox class also offers a method \code{receiveWithin} which blocks for only a specified maximal amount of time. If no message is received within the specified time interval (given in @@ -6681,7 +6690,7 @@ with the special \code{TIMEOUT} message. The implementation of if (s1 != null) { s.next = s1.next; s1.elem } else { - val r = lastReceiver.insert(new Receiver { + val r = insert(lastReceiver, new Receiver { def isDefined(msg: Any) = f.isDefinedAt(msg); }); lastReceiver = r; @@ -6877,6 +6886,7 @@ class Bidder (auction: Process, minBid: int, maxBid: int) def transferPayment(seller: Process, amount: int) } \end{lstlisting} +} \bibliographystyle{alpha} \bibliography{Scala} diff --git a/doc/reference/ScalaReference.tex b/doc/reference/ScalaReference.tex index c62e0f04b..5c106a3e5 100644 --- a/doc/reference/ScalaReference.tex +++ b/doc/reference/ScalaReference.tex @@ -1194,7 +1194,7 @@ type Abs = Comparable[Abs]; // recursive type alias type S <: T; // S, T are bounded by themselves. type T <: S; -type T <: Object with T; // T is abstract, may not be part of +type T <: AnyRef with T; // T is abstract, may not be part of // compound type type T >: Comparable[T.That]; // Cannot select from T. @@ -1310,7 +1310,7 @@ class P[a, b] { }\end{lstlisting} With this variance annotation, elements of type $P$ subtype covariantly with respect to their arguments. -For instance, ~\lstinline@P[IOExeption, String] <: P[Throwable, Object]@. +For instance, ~\lstinline@P[IOExeption, String] <: P[Throwable, AnyRef]@. If we make the elements of $P$ mutable, the variance annotation becomes illegal. @@ -1348,7 +1348,7 @@ trait OutputChannel[-a] { } \end{lstlisting} With that annotation, we have that -\lstinline@OutputChannel[Object]@ conforms to \lstinline@OutputChannel[String]@. +\lstinline@OutputChannel[AnyRef]@ conforms to \lstinline@OutputChannel[String]@. That is, a channel on which one can write any object can substitute for a channel on which one can write only strings. @@ -1965,7 +1965,7 @@ $sc$ with $mc_1$ with $\ldots$ with $mc_n$ { $stats$ } which defines the base classes, behavior and initial state of objects of the class. The extends clause ~\lstinline@extends $sc$ with $\ldots$ with $mc_n$@~ can be omitted, in which case -~\lstinline@extends scala.Object@~ is assumed. The class body +~\lstinline@extends scala.AnyRef@~ is assumed. The class body ~\lstinline@{$stats\,$}@~ may also be omitted, in which case the empty body \lstinline@{}@ is assumed. \end{itemize} @@ -2077,10 +2077,10 @@ $x$ that defines $x$ to be an alias of the parameter. %parameters. Every case class implicitly overrides some method definitions of class -\lstinline@scala.Object@ (\sref{sec:cls-object}) unless a definition of the same +\lstinline@scala.AnyRef@ (\sref{sec:cls-object}) unless a definition of the same method is already given in the case class itself or a concrete definition of the same method is given in some base class of the case -class different from \code{Object}. In particular: +class different from \code{AnyRef}. In particular: \begin{itemize} \item[] Method ~\lstinline@equals: (Any)boolean@~ is structural equality, where two instances are equal if they belong to the same class and @@ -2211,7 +2211,7 @@ $sc$ with $mc_1$ with $\ldots$ with $mc_n$ { $stats$ } which defines the base classes, behavior and initial state of $m$. The extends clause ~\lstinline@extends $sc$ with $\ldots$ with $mc_n$@~ can be omitted, in which case -~\lstinline@extends scala.Object@~ is assumed. The class body +~\lstinline@extends scala.AnyRef@~ is assumed. The class body ~\lstinline@{$stats\,$}@~ may also be omitted, in which case the empty body \lstinline@{}@ is assumed. \end{itemize} @@ -2711,7 +2711,7 @@ object, which is initialized by evaluating the expression template. \example Consider the class \begin{lstlisting} abstract class C { - type T; val x: T; def f(x: T): Object + type T; val x: T; def f(x: T): AnyRef } \end{lstlisting} and the instance creation expression @@ -3637,11 +3637,12 @@ indirectly from this class. Class \code{Any} has two direct subclasses: \code{AnyRef} and\code{AnyVal}. The subclass \code{AnyRef} represents all values which are represented -as objects in the underlying host system. A subclass of \code{AnyRef} -is class \code{Object}. Every user-defined Scala class inherits -directly or indirectly from this class. Classes written in other -languages still inherit from \code{scala.AnyRef}, but not necessarily -from \code{scala.Object}. +as objects in the underlying host system. Every user-defined Scala +class inherits directly or indirectly from this class. Furthermore, +every user-defined Scala class also inherits the trait +\code{scala.ScalaObject}. Classes written in other languages still +inherit from \code{scala.AnyRef}, but not from +\code{scala.ScalaObject}. The class \code{AnyVal} has a fixed number subclasses, which describe values which are not implemented as objects in the underlying host @@ -3695,7 +3696,7 @@ abstract class Any { } final class AnyVal extends Any; class AnyRef extends Any; -class Object extends AnyRef; +trait ScalaObject extends AnyRef; \end{lstlisting} The type cast operation \verb@asInstanceOf@ has a special meaning (not diff --git a/sources/scala/Array.java b/sources/scala/Array.java index 4cd1deee9..6a139ffd9 100644 --- a/sources/scala/Array.java +++ b/sources/scala/Array.java @@ -14,7 +14,7 @@ package scala; /** @meta class [?T] extends scala.Function1[scala.Int, ?T]; */ public abstract class Array - extends scala.Object + extends java.lang.Object implements Function1, Cloneable, java.io.Serializable { /** @meta constr (scala.Int); diff --git a/sources/scala/Object.java b/sources/scala/Object.java deleted file mode 100644 index 4a44ad0ca..000000000 --- a/sources/scala/Object.java +++ /dev/null @@ -1,24 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $OldId: Object.java,v 1.7 2002/03/12 13:32:46 zenger Exp $ -// $Id$ - -package scala; - -/** @meta class extends scala.AnyRef; - */ -public class Object { - - /** This method is needed for optimizing pattern matching expressions - * which match on constructors of case classes. - */ - public int $tag() { - return 0; - } -} diff --git a/sources/scala/Ref.java b/sources/scala/Ref.java index 5635e433a..4f45a2856 100644 --- a/sources/scala/Ref.java +++ b/sources/scala/Ref.java @@ -11,9 +11,9 @@ package scala; -/** @meta class [?T] extends scala.Object; +/** @meta class [?T] extends java.lang.Object; */ -public class Ref extends scala.Object { +public class Ref extends java.lang.Object { /** @meta field ?T; */ diff --git a/sources/scala/concurrent/MailBox.scala b/sources/scala/concurrent/MailBox.scala index efa5984ef..972101eb8 100644 --- a/sources/scala/concurrent/MailBox.scala +++ b/sources/scala/concurrent/MailBox.scala @@ -1,7 +1,7 @@ package scala.concurrent; //class MailBox with Monitor with LinkedListQueueCreator { -class MailBox with Monitor with ListQueueCreator { +class MailBox extends Monitor with ListQueueCreator { type Message = AnyRef; diff --git a/sources/scala/runtime/ResultOrException.java b/sources/scala/runtime/ResultOrException.java index 870ed2ce5..4961c785d 100644 --- a/sources/scala/runtime/ResultOrException.java +++ b/sources/scala/runtime/ResultOrException.java @@ -10,7 +10,7 @@ package scala.runtime; -/** @meta class [?A] extends scala.Object; +/** @meta class [?A] extends java.lang.Object; */ public class ResultOrException { diff --git a/sources/scala/tools/scalac/ast/parser/Parser.scala b/sources/scala/tools/scalac/ast/parser/Parser.scala index 8689966ea..d4e169fe2 100644 --- a/sources/scala/tools/scalac/ast/parser/Parser.scala +++ b/sources/scala/tools/scalac/ast/parser/Parser.scala @@ -247,9 +247,13 @@ class Parser(unit: Unit) { def scalaBooleanDot(pos: int, name: Name): Tree = make.Select(pos, scalaDot(pos, Names.Boolean), name); + def scalaAnyRefConstr(pos: int): Tree = + make.Apply( + pos, scalaDot(pos, Names.AnyRef.toTypeName()), Tree.EMPTY_ARRAY); + def scalaObjectConstr(pos: int): Tree = make.Apply( - pos, scalaDot(pos, Names.Object.toTypeName()), Tree.EMPTY_ARRAY); + pos, scalaDot(pos, Names.ScalaObject.toTypeName()), Tree.EMPTY_ARRAY); /** Create tree for for-comprehension or * where mapName and flatmapName are chosen @@ -1737,22 +1741,24 @@ class Parser(unit: Unit) { */ def classTemplate(): Tree$Template = { val pos = s.pos; + val parents = new myTreeList(); if (s.token == EXTENDS) { s.nextToken(); - template() - } else if (s.token == WITH) { + parents.append(constr()); + } else { + parents.append(scalaAnyRefConstr(pos)); + } + parents.append(scalaObjectConstr(pos)); + if (s.token == WITH) { s.nextToken(); - val parents = new myTreeList(); - parents.append(scalaObjectConstr(pos)); template(parents) } else if (s.token == LBRACE) { - make.Template( - pos, NewArray.Tree(scalaObjectConstr(pos)), templateBody()); + make.Template(pos, parents.toArray(), templateBody()); } else { if (!(s.token == SEMI || s.token == COMMA || s.token == RBRACE)) syntaxError("`extends' or `{' expected", true); make.Template( - pos, NewArray.Tree(scalaObjectConstr(pos)), Tree.EMPTY_ARRAY); + pos, parents.toArray(), Tree.EMPTY_ARRAY); } } diff --git a/sources/scalac/ast/TreeGen.java b/sources/scalac/ast/TreeGen.java index 72122d2b5..b4c77c6e3 100644 --- a/sources/scalac/ast/TreeGen.java +++ b/sources/scalac/ast/TreeGen.java @@ -1165,7 +1165,7 @@ public class TreeGen implements Kinds, Modifiers, TypeTags { argtypes[i] = params[i].type(); } Type[] parentTypes = { - definitions.OBJECT_TYPE(), + definitions.ANYREF_TYPE(), definitions.FUNCTION_TYPE(argtypes, restype) }; ClassSymbol clazz = new ClassSymbol( pos, Names.ANON_CLASS_NAME.toTypeName(), owner, 0); @@ -1196,7 +1196,7 @@ public class TreeGen implements Kinds, Modifiers, TypeTags { ClassSymbol clazz = new ClassSymbol( pos, Names.ANON_CLASS_NAME.toTypeName(), owner, 0); Type[] parentTypes = { - definitions.OBJECT_TYPE(), + definitions.ANYREF_TYPE(), definitions.PARTIALFUNCTION_TYPE(pattype, restype)}; clazz.setInfo(Type.compoundType(parentTypes, new Scope(), clazz)); clazz.allConstructors().setInfo( diff --git a/sources/scalac/ast/parser/Parser.java b/sources/scalac/ast/parser/Parser.java index 21b554156..a49d241b4 100644 --- a/sources/scalac/ast/parser/Parser.java +++ b/sources/scalac/ast/parser/Parser.java @@ -275,9 +275,14 @@ public class Parser implements Tokens { return make.Select(pos, scalaXmlDot(pos, Names.nobinding), name); } + Tree scalaAnyRefConstr(int pos) { + return make.Apply( + pos, scalaDot(pos, Names.AnyRef.toTypeName()), Tree.EMPTY_ARRAY); + } + Tree scalaObjectConstr(int pos) { return make.Apply( - pos, scalaDot(pos, Names.Object.toTypeName()), Tree.EMPTY_ARRAY); + pos, scalaDot(pos, Names.ScalaObject.toTypeName()), Tree.EMPTY_ARRAY); } /** Create tree for for-comprehension or @@ -1885,22 +1890,25 @@ public class Parser implements Tokens { */ Template classTemplate() { int pos = s.pos; + TreeList parents = new TreeList(); if (s.token == EXTENDS) { s.nextToken(); - return template(); - } else if (s.token == WITH) { + parents.append(constr()); + } else { + parents.append(scalaAnyRefConstr(pos)); + } + parents.append(scalaObjectConstr(pos)); + if (s.token == WITH) { s.nextToken(); - TreeList parents = new TreeList(); - parents.append(scalaObjectConstr(pos)); - return template(parents); + return template(parents); } else if (s.token == LBRACE) { return (Template)make.Template( - pos, new Tree[]{scalaObjectConstr(pos)}, templateBody()); + pos, parents.toArray(), templateBody()); } else { if (!(s.token == SEMI || s.token == COMMA || s.token == RBRACE)) syntaxError("`extends' or `{' expected", true); return (Template)make.Template( - pos, new Tree[]{scalaObjectConstr(pos)}, Tree.EMPTY_ARRAY); + pos, parents.toArray(), Tree.EMPTY_ARRAY); } } diff --git a/sources/scalac/symtab/Definitions.java b/sources/scalac/symtab/Definitions.java index 79db92a58..8c59358a5 100644 --- a/sources/scalac/symtab/Definitions.java +++ b/sources/scalac/symtab/Definitions.java @@ -491,7 +491,7 @@ public class Definitions { DOUBLE_CLASS = getClass(Names.scala_Double); // the scala reference classes - OBJECT_CLASS = getClass(Names.scala_Object); + OBJECT_CLASS = getClass(Names.scala_ScalaObject); STRING_CLASS = newAlias(SCALA_PACKAGE, Names.String, 0); REF_CLASS = getClass(Names.scala_Ref); for (int i = 1; i < TUPLE_COUNT; i++) { diff --git a/sources/scalac/symtab/Type.java b/sources/scalac/symtab/Type.java index e155cd897..f8c4e2ffc 100644 --- a/sources/scalac/symtab/Type.java +++ b/sources/scalac/symtab/Type.java @@ -754,7 +754,8 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { } /** Is this type of the form scala.FunctionN[T_1, ..., T_n, +T] or - * scala.Object with scala.FunctionN[T_1, ..., T_n, +T]? + * scala.AnyRef with scala.FunctionN[T_1, ..., T_n, +T] or + * java.lang.Object with scala.FunctionN[T_1, ..., T_n, +T]? */ public boolean isFunctionType() { switch (this) { @@ -764,7 +765,8 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { case CompoundType(Type[] parents, Scope members): return members.isEmpty() && parents.length == 2 && - parents[0].symbol().fullName() == Names.scala_Object && + (parents[0].symbol().fullName() == Names.java_lang_Object || + parents[0].symbol().fullName() == Names.scala_AnyRef) && parents[1].isFunctionType(); } return false; @@ -850,13 +852,17 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { // take precedence over abstract ones. int i = parts.length; sym = Symbol.NONE; - while (i > 0 && (sym.kind == NONE || (sym.flags & DEFERRED) != 0)) { + while (i > 0) { i--; Symbol sym1 = parts[i].lookupNonPrivate(name); if (sym1.kind != NONE && (sym1.flags & PRIVATE) == 0 && - (sym.kind == NONE || - (sym1.flags & DEFERRED) == 0 || + (sym.kind == NONE + || + (sym.flags & DEFERRED) != 0 && + (sym1.flags & DEFERRED) == 0 + || + (sym.flags & DEFERRED) == (sym1.flags & DEFERRED) && sym1.owner().isSubClass(sym.owner()))) sym = sym1; } diff --git a/sources/scalac/symtab/classfile/CLRPackageParser.java b/sources/scalac/symtab/classfile/CLRPackageParser.java index 291d8eeef..a65614e50 100644 --- a/sources/scalac/symtab/classfile/CLRPackageParser.java +++ b/sources/scalac/symtab/classfile/CLRPackageParser.java @@ -246,7 +246,6 @@ public class CLRPackageParser extends MetadataParser { clazz.allConstructors().setInfo(completer.staticsParser(clazz)); clazz.module().setInfo(completer.staticsParser(clazz)); members.enter(clazz); - // ATTENTION: only if not scala.Object! Scope.Entry e = members.lookupEntry(clazz.module().name); if (e != Scope.Entry.NONE) members.unlink(e); diff --git a/sources/scalac/typechecker/RefCheck.java b/sources/scalac/typechecker/RefCheck.java index 9110c4afc..459e13cb7 100644 --- a/sources/scalac/typechecker/RefCheck.java +++ b/sources/scalac/typechecker/RefCheck.java @@ -726,12 +726,16 @@ public class RefCheck extends Transformer implements Modifiers, Kinds { } private Tree tagMethod(ClassSymbol clazz) { - Symbol tagSym = new TermSymbol( - clazz.pos, Names.tag, clazz, - clazz.isSubClass(defs.OBJECT_CLASS) ? OVERRIDE : 0) - .setInfo(Type.MethodType(Symbol.EMPTY_ARRAY, defs.INT_TYPE())); - clazz.info().members().enter(tagSym); - return gen.DefDef(tagSym, gen.mkIntLit(clazz.pos, clazz.tag())); + Symbol tagSym = new TermSymbol( + clazz.pos, Names.tag, clazz, + clazz.isSubClass(defs.OBJECT_CLASS) ? OVERRIDE : 0) + .setInfo(Type.MethodType(Symbol.EMPTY_ARRAY, defs.INT_TYPE())); + clazz.info().members().enter(tagSym); + return gen.DefDef( + tagSym, + gen.mkIntLit( + clazz.pos, + clazz.isCaseClass() ? clazz.tag() : 0)); } private Tree hashCodeMethod(ClassSymbol clazz) { @@ -772,18 +776,23 @@ public class RefCheck extends Transformer implements Modifiers, Kinds { } // where - private Template addCaseMethods(Template templ, Symbol sym) { - if (sym.kind == CLASS && (sym.flags & CASE) != 0) { - Tree[] body1 = addCaseMethods(templ.body, (ClassSymbol) sym); - return copy.Template(templ, templ.parents, body1); - } - return templ; + private Template addCaseMethods(Template templ, ClassSymbol sym) { + Tree[] body1; + if (sym.isCaseClass()) { + body1 = addCaseMethods(templ.body, sym); + } else { + body1 = new Tree[templ.body.length + 1]; + System.arraycopy(templ.body, 0, body1, 0, templ.body.length); + body1[templ.body.length] = tagMethod(sym); + } + return copy.Template(templ, templ.parents, body1); } private Tree[] addCaseMethods(Tree[] stats, ClassSymbol clazz) { TreeList ts = new TreeList(); - if (!hasImplementation(clazz, Names.toString)) + if (!hasImplementation(clazz, Names.toString)) { ts.append(toStringMethod(clazz)); + } if (!hasImplementation(clazz, Names.equals)) ts.append(equalsMethod(clazz)); if (!hasImplementation(clazz, Names.hashCode)) @@ -934,7 +943,7 @@ public class RefCheck extends Transformer implements Modifiers, Kinds { validateVariance(sym, sym.info(), CoVariance); validateVariance(sym, sym.typeOfThis(), CoVariance); Tree tree1 = super.transform( - copy.ClassDef(tree, tree.symbol(), tparams, vparams, tpe, addCaseMethods(templ, tree.symbol()))); + copy.ClassDef(tree, tree.symbol(), tparams, vparams, tpe, addCaseMethods(templ, (ClassSymbol) tree.symbol()))); enclClass = enclClassPrev; return tree1; diff --git a/sources/scalac/util/Names.java b/sources/scalac/util/Names.java index 3f54938e6..04c1b1e0e 100644 --- a/sources/scalac/util/Names.java +++ b/sources/scalac/util/Names.java @@ -112,6 +112,7 @@ public class Names { public static final Name Object = Name.fromString("Object"); public static final Name PartialFunction = Name.fromString("PartialFunction"); public static final Name Predef = Name.fromString("Predef"); + public static final Name ScalaObject = Name.fromString("ScalaObject"); public static final Name ScalaRunTime = Name.fromString("ScalaRunTime"); public static final Name Seq = Name.fromString("Seq"); public static final Name Short = Name.fromString("Short"); @@ -181,7 +182,7 @@ public class Names { public static final Name scala_Long = Name.fromString("scala.Long"); public static final Name scala_MatchError = Name.fromString("scala.MatchError"); public static final Name scala_Nil = Name.fromString("scala.Nil"); - public static final Name scala_Object = Name.fromString("scala.Object"); + public static final Name scala_ScalaObject = Name.fromString("scala.ScalaObject"); public static final Name scala_PartialFunction = Name.fromString("scala.PartialFunction"); public static final Name scala_Predef = Name.fromString("scala.Predef"); public static final Name scala_Ref = Name.fromString("scala.Ref"); diff --git a/test/files/neg/bug228.check b/test/files/neg/bug228.check index 0dc891bce..a099f9fa0 100644 --- a/test/files/neg/bug228.check +++ b/test/files/neg/bug228.check @@ -1,4 +1,4 @@ -/home/odersky/scala/test/pos/bug228.scala:11: constructor java.lang.reflect.AccessibleObject cannot be accessed in Foo +bug228.scala:11: constructor java.lang.reflect.AccessibleObject cannot be accessed in Foo val o = new AccessibleObject; ^ one error found diff --git a/test/files/pos/A.scala b/test/files/pos/A.scala index 513c8bed4..fc50379d8 100644 --- a/test/files/pos/A.scala +++ b/test/files/pos/A.scala @@ -1,4 +1,4 @@ -trait A extends scala.Object {} +trait A extends java.lang.Object {} object test { diff --git a/test/files/pos/MailBox.scala b/test/files/pos/MailBox.scala index 755be67bf..b96f76681 100644 --- a/test/files/pos/MailBox.scala +++ b/test/files/pos/MailBox.scala @@ -8,7 +8,7 @@ class MailBox with Monitor { var next: LinkedList[a] = null; } - def insert(l: LinkedList[a], x: a): LinkedList[a] { + def insert[a](l: LinkedList[a], x: a): LinkedList[a] = { l.next = new LinkedList[a]; l.next.elem = x; l.next.next = l.next; diff --git a/test/neg/bug228.check b/test/neg/bug228.check index 0dc891bce..a099f9fa0 100644 --- a/test/neg/bug228.check +++ b/test/neg/bug228.check @@ -1,4 +1,4 @@ -/home/odersky/scala/test/pos/bug228.scala:11: constructor java.lang.reflect.AccessibleObject cannot be accessed in Foo +bug228.scala:11: constructor java.lang.reflect.AccessibleObject cannot be accessed in Foo val o = new AccessibleObject; ^ one error found diff --git a/test/pos/A.scala b/test/pos/A.scala index 513c8bed4..fc50379d8 100644 --- a/test/pos/A.scala +++ b/test/pos/A.scala @@ -1,4 +1,4 @@ -trait A extends scala.Object {} +trait A extends java.lang.Object {} object test { diff --git a/test/pos/MailBox.scala b/test/pos/MailBox.scala index 755be67bf..b96f76681 100644 --- a/test/pos/MailBox.scala +++ b/test/pos/MailBox.scala @@ -8,7 +8,7 @@ class MailBox with Monitor { var next: LinkedList[a] = null; } - def insert(l: LinkedList[a], x: a): LinkedList[a] { + def insert[a](l: LinkedList[a], x: a): LinkedList[a] = { l.next = new LinkedList[a]; l.next.elem = x; l.next.next = l.next;