summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/reference/ScalaReference.tex55
-rw-r--r--sources/meta/scalac/checkers/MetaCheckTreeNodes.java4
-rw-r--r--sources/scalac/symtab/Type.java48
-rw-r--r--sources/scalac/typechecker/Analyzer.java25
-rw-r--r--sources/scalac/typechecker/RefCheck.java123
5 files changed, 125 insertions, 130 deletions
diff --git a/doc/reference/ScalaReference.tex b/doc/reference/ScalaReference.tex
index 5d44c69411..1167828aad 100644
--- a/doc/reference/ScalaReference.tex
+++ b/doc/reference/ScalaReference.tex
@@ -546,6 +546,7 @@ empty : [a >: All <: Any] List[a]
union : [a >: All <: Comparable[a]] (x: Set[a], xs: Set[a]) Set[a] .
\end{lstlisting}
+\comment{
\subsection{Overloaded Types}
\label{sec:overloaded-types}
\newcommand{\overload}{\la\mbox{\sf and}\ra}
@@ -581,6 +582,7 @@ def f(x: T): T = $\ldots$;
val f = 0
\end{lstlisting}
define a function \code{f} which has type ~\lstinline@(x: T)T $\overload$ Int@.
+}
\section{Base Classes and Member Definitions}
\label{sec:base-classes}
@@ -1351,14 +1353,12 @@ determined from the type of the function body.
An overloaded definition is a set of $n > 1$ value or function
definitions in the same statement sequence that define the same name,
-binding it to types ~\lstinline@$T_1 \commadots T_n$@, respectively. The
-individual definitions are called {\em alternatives}. Alternatives
-always need to specify the type of the defined entity completely. All
-alternatives must have the same modifiers. It is an error if the types
-of two alternatives $T_i$ and $T_j$ have the same
-erasure (\sref{sec:erasure}). An overloaded definition defines a
-single entity, of type $T_1 \overload \ldots \overload T_n$
-(\sref{sec:overloaded-types}).
+binding it to types ~\lstinline@$T_1 \commadots T_n$@, respectively.
+The individual definitions are called {\em alternatives}. Overloaded
+definitions may only appear in the statement sequence of a template.
+Alternatives always need to specify the type of the defined entity
+completely. It is an error if the types of two alternatives $T_i$ and
+$T_j$ have the same erasure (\sref{sec:erasure}).
\todo{Say something about bridge methods.}
%This must be a well-formed
@@ -2100,7 +2100,7 @@ trait Ord[t <: Ord[t]]: t {
\end{lstlisting}
An object definition defines a single object of a new class. Its
-most general is
+most general form is
~\lstinline@object $m$: $s$ extends $t$@. Here,
\begin{itemize}
\item[]
@@ -2603,15 +2603,15 @@ new $sc$ with $mc_1$ with $\ldots$ with $mc_n$ {$stats\,$}
\end{lstlisting}
where $n \geq 0$, $sc$ as well as $mc_1 \commadots mc_n$ are
constructor invocations (of types $S, T_1 \commadots T_n$, say) and
-$stats$ is a statement sequence containing initializer statements
-and member definitions (\sref{sec:members}). The type of such an
-instance creation expression is then the compound type
-\lstinline@$S$ with $T_1$ with $\ldots$ with $T_n$ {$R\,$}@, where \lstinline@{$R\,$}@ is a
-refinement (\sref{sec:compound-types}) which declares exactly those
-members of $stats$ that override a member of $S$ or
-$T_1 \commadots T_n$. For this type to be well-formed, $R$
-may not reference types defined in $stats$ which do not
-themselves form part of $R$.
+$stats$ is a statement sequence containing initializer statements and
+member definitions (\sref{sec:members}). The type of such an instance
+creation expression is then the compound type \lstinline@$S$ with
+$T_1$ with $\ldots$ with $T_n$ {$R\,$}@, where \lstinline@{$R\,$}@ is
+a refinement (\sref{sec:compound-types}) which declares exactly those
+members of $stats$ that override a member of $S$ or $T_1 \commadots
+T_n$. \todo{what about methods and overloaded defs?} For this type to
+be well-formed, $R$ may not reference types defined in $stats$ which
+do not themselves form part of $R$.
The instance creation expression is evaluated by creating a fresh
object, which is initialized by evaluating the expression template.
@@ -3161,16 +3161,15 @@ by expression $e$. The scope of each formal parameter
$x_i$ is $e$.
If the expected type of the anonymous function is of the form
-~\lstinline@scala.Function$n$[$S_1 \commadots S_n$, $R\,$]@, the expected type
-of $e$ is $R$ and the type $T_i$ of any of the
-parameters $x_i$ can be omitted, in which case
-~\lstinline@$T_i$ = $S_i$@~ is assumed. If the expected type of the anonymous
-function is some other type, all formal parameter types must be
-explicitly given, and the expected type of $e$ is missing. The
-type of the anonymous function is
-~\lstinline@scala.Function$n$[$S_1 \commadots S_n$, $T\,$]@, where $T$ is
-the type of $e$. $T$ must be equivalent to a type which does
-not refer to any of the formal parameters $x_i$.
+~\lstinline@scala.Function$n$[$S_1 \commadots S_n$, $R\,$]@, the
+expected type of $e$ is $R$ and the type $T_i$ of any of the
+parameters $x_i$ can be omitted, in which case ~\lstinline@$T_i$ =
+$S_i$@~ is assumed. If the expected type of the anonymous function is
+some other type, all formal parameter types must be explicitly given,
+and the expected type of $e$ is missing. The type of the anonymous
+function is ~\lstinline@scala.Function$n$[$S_1 \commadots S_n$,
+$T\,$]@, where $T$ is the type of $e$. $T$ must be equivalent to a
+type which does not refer to any of the formal parameters $x_i$.
The anonymous function is evaluated as the instance creation expression
\begin{lstlisting}
diff --git a/sources/meta/scalac/checkers/MetaCheckTreeNodes.java b/sources/meta/scalac/checkers/MetaCheckTreeNodes.java
index d18d012d20..11ad75d77a 100644
--- a/sources/meta/scalac/checkers/MetaCheckTreeNodes.java
+++ b/sources/meta/scalac/checkers/MetaCheckTreeNodes.java
@@ -78,8 +78,8 @@ public class MetaCheckTreeNodes extends AbstractTreeCaseExpander {
case TreeType.Name(TreeKind kind):
if (kind != TreeKind.Any && kind != TreeKind.Test) {
- writer.println("assert " + (kind == TreeKind.Type ? "" : "!")+
- name +".isTypeName() :").indent();
+ writer.println("assert " + name + ".is" + kind + "Name() :")
+ .indent();
printWrongKind(node, name, kind);
writer.println(";").undent();
}
diff --git a/sources/scalac/symtab/Type.java b/sources/scalac/symtab/Type.java
index e3526f8830..03bee60328 100644
--- a/sources/scalac/symtab/Type.java
+++ b/sources/scalac/symtab/Type.java
@@ -1727,36 +1727,23 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
return result;
}
- public boolean specializes0(Symbol sym1) {
- Symbol sym = lookup(sym1.name);
- switch (sym.info()) {
- case NoType:
- return false;
- case OverloadedType(Symbol[] alts, Type[] alttypes):
- for (int i = 0; i < alts.length; i++) {
- if (specializes0(alts[i], sym1)) return true;
- }
- return false;
- default:
- return specializes0(sym, sym1);
- }
- }
-
- private boolean specializes0(Symbol sym, Symbol sym1) {
+ private boolean specializes0(Symbol sym1) {
Type self = narrow();
Symbol[] tparams = symbol().typeParams();
Type[] targs = typeArgs();
+ Symbol sym = lookup(sym1.name);
return
- sym == sym1
- ||
- (sym.kind == sym1.kind || sym1.kind == TYPE) &&
- self.memberInfo(sym).subst(tparams, targs)
- .isSubType(sym1.info().substThis(sym1.owner(), self)) &&
- sym1.loBound().substThis(sym1.owner(), self)
- .isSubType(self.memberLoBound(sym).subst(tparams, targs))
- ||
- (sym.kind == TYPE && sym1.kind == ALIAS &&
- sym1.info().unalias().isSameAs(sym.type()));
+ sym.kind != NONE &&
+ (sym == sym1
+ ||
+ (sym.kind == sym1.kind || sym1.kind == TYPE) &&
+ self.memberInfo(sym).subst(tparams, targs)
+ .isSubType(sym1.info().substThis(sym1.owner(), self)) &&
+ sym1.loBound().substThis(sym1.owner(), self)
+ .isSubType(self.memberLoBound(sym).subst(tparams, targs))
+ ||
+ (sym.kind == TYPE && sym1.kind == ALIAS &&
+ sym1.info().unalias().isSameAs(sym.type())));
}
/** Is this type the same as that type?
@@ -2163,7 +2150,7 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
if (tps[i] == ErrorType) {
return new Type[]{ErrorType};
} else {
- assert tps[i].isObjectType() : tps[i];
+ assert tps[i].isObjectType(): tps[i];
for (int j = 0; j < i && !redundant[i]; j++) {
if (!redundant[j]) {
if (tps[i].isSubType(tps[j])) {
@@ -2197,6 +2184,9 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
if (tps.length == 0) return Global.instance.definitions.ALL_TYPE;
+ //If all types are method types with same parameters,
+ //compute lub of their result types.
+
// remove types that are subtypes of some other type.
tps = elimRedundant(tps, true);
if (tps.length == 1) return tps[0];
@@ -2231,8 +2221,6 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
while (j < tps.length) {
rsyms[j] = tps[j].lookupNonPrivate(name);
if (rsyms[j] == sym) break;
- if (rsyms[j].isMethod()) break; // since methods cannot
- // appear in refinements.
rtps[j] = memberTp(tps[j], rsyms[j])
.substThis(tps[j].symbol(), lubThisType);
rlbs[j] = tps[j].memberLoBound(rsyms[j])
@@ -2311,7 +2299,7 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
if (!members.isEmpty())
comptl = new Type.List(tps[i], comptl);
for (int j = 0; j < parents.length; j++)
- treftl = new Type.List(parents[i], treftl);
+ treftl = new Type.List(parents[j], treftl);
break;
case ThisType(_):
case SingleType(_, _):
diff --git a/sources/scalac/typechecker/Analyzer.java b/sources/scalac/typechecker/Analyzer.java
index fc53218f5e..99629712a9 100644
--- a/sources/scalac/typechecker/Analyzer.java
+++ b/sources/scalac/typechecker/Analyzer.java
@@ -1117,7 +1117,10 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
} catch (Type.Error ex) {
reportTypeError(tree.pos, ex);
tree.type = Type.ErrorType;
- if (tree.hasSymbol() && tree.symbol() == null) tree.setSymbol(Symbol.ERROR);
+ if (tree.hasSymbol()) {
+ if (tree.symbol() != null) tree.symbol().setInfo(Type.ErrorType);
+ else tree.setSymbol(Symbol.ERROR);
+ }
}
this.unit = savedUnit;
@@ -1235,7 +1238,8 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
if (clazz.isCaseClass()) {
// set type to instantiated case class constructor
- tree.type = clazz.primaryConstructor().type();
+ tree.type = tree.type.prefix().memberType(
+ clazz.primaryConstructor());
switch (tree.type) {
case PolyType(Symbol[] tparams, Type restp):
try {
@@ -2031,7 +2035,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
return error(tree.pos, "method with return needs result type");
} else {
Symbol enclFun = context.owner.enclMethod();
- if (enclFun.kind == VAL) {
+ if (enclFun.kind == VAL && !enclFun.isConstructor()) {
Tree expr1 = transform(
expr, EXPRmode, enclFun.type().resultType());
return copy.Return(tree, expr1)
@@ -2178,7 +2182,12 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
assert tsym.isType() : tsym;
switch (fn1.type.unalias()) {
case TypeRef(Type pre, Symbol c, Type[] argtypes):
- if (c.kind == CLASS) {
+ if (c.kind != CLASS) {
+ error(tree.pos,
+ tsym + " is not a class; cannot be instantiated");
+ } else if (!pre.isStable()) {
+ error(tree.pos, pre + " is not a legal prefix for a constructor");
+ } else {
c.initialize();
Symbol constr = c.allConstructors();
Tree fn0 = fn1;
@@ -2206,9 +2215,6 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
}
//System.out.println(TreeInfo.methSymbol(fn1) + ":" + tp + " --> " + fn1.type + " of " + fn1);//DEBUG
selfcc = TreeInfo.isSelfConstrCall(fn0);
- } else {
- error(tree.pos,
- tsym + " is not a class; cannot be instantiated");
}
break;
default:
@@ -2475,7 +2481,10 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
} catch (Type.Error ex) {
reportTypeError(tree.pos, ex);
tree.type = Type.ErrorType;
- if (tree.hasSymbol() && tree.symbol() == null) tree.setSymbol(Symbol.ERROR);
+ if (tree.hasSymbol()) {
+ if (tree.symbol() != null) tree.symbol().setInfo(Type.ErrorType);
+ else tree.setSymbol(Symbol.ERROR);
+ }
return tree;
}
}
diff --git a/sources/scalac/typechecker/RefCheck.java b/sources/scalac/typechecker/RefCheck.java
index d3a603642a..b2e394458a 100644
--- a/sources/scalac/typechecker/RefCheck.java
+++ b/sources/scalac/typechecker/RefCheck.java
@@ -58,54 +58,76 @@ public class RefCheck extends Transformer implements Modifiers, Kinds {
// Override checking ------------------------------------------------------------
/** 1. Check all members of class `clazz' for overriding conditions.
- * 2. Check that only abstract classes have deferred members
+ * 2. Check that only abstract classes have deferred members*
* 3. Check that every member with an `override' modifier
* overrides a concrete member.
*/
void checkAllOverrides(int pos, Symbol clazz) {
Type[] closure = clazz.closure();
- HashMap/*<Symbol,Symbol>*/ overrides = null;
+ HashMap/*<Symbol,Symbol>*/ overrides = new HashMap();
for (int i = 0; i < closure.length; i++) {
for (Scope.SymbolIterator it = closure[i].members().iterator(true);
it.hasNext();) {
- Symbol other = it.next();
- Symbol member = ((other.flags & PRIVATE) != 0) ? other
- : clazz.info().lookup(other.name);
- if (member.owner() == other.owner())
- member = other;
- else if (member.type() instanceof Type.OverloadedType)
- member = findOverriding(pos, clazz, member, other);
- if (member.kind != NONE && member != other)
- checkOverride(pos, clazz, member, other);
- if (clazz.kind == CLASS && (clazz.flags & ABSTRACTCLASS) == 0) {
- if ((member.flags & DEFERRED) != 0) {
- abstractClassError(
- clazz,
- member + member.locationString() + " is not defined" +
- (((member.flags & MUTABLE) == 0) ? ""
- : "\n(Note that variables need to be initialized to be defined)"));
- } else if ((member.flags & OVERRIDE) != 0) {
- if (overrides == null)
- overrides = new HashMap();
- if ((other.flags & DEFERRED) == 0 ||
- overrides.get(member) == null)
- overrides.put(member, other);
- }
- }
+ checkOverride(pos, clazz, it.next(), overrides);
}
}
- if (overrides != null) {
- for (Iterator/*<Symbol>*/ it = overrides.keySet().iterator();
- it.hasNext();) {
- Symbol member = (Symbol) it.next();
- Symbol other = (Symbol) overrides.get(member);
- if ((other.flags & DEFERRED) != 0) {
- abstractClassError(
- clazz, member + member.locationString() +
- " is marked `override' and overrides only abstract members" + other + other.locationString());
+ for (Iterator/*<Symbol>*/ it = overrides.keySet().iterator();
+ it.hasNext();) {
+ Symbol member = (Symbol) it.next();
+ Symbol other = (Symbol) overrides.get(member);
+ if ((other.flags & DEFERRED) != 0) {
+ abstractClassError(
+ clazz, member + member.locationString() +
+ " is marked `override' and overrides only abstract members" + other + other.locationString());
+ }
+ }
+ }
+
+ void checkOverride(int pos, Symbol clazz, Symbol other,
+ HashMap/*<Symbol,Symbol>*/ overrides) {
+ Symbol member = other;
+ if ((other.flags & PRIVATE) == 0) {
+ Symbol member1 = clazz.info().lookup(other.name);
+ if (member1.kind != NONE && member1.owner() != other.owner()) {
+ switch (member1.info()) {
+ case OverloadedType(Symbol[] alts, _):
+ Type self = clazz.thisType();
+ Type otherinfo = normalizedInfo(self, other);
+ for (int i = 0; i < alts.length; i++) {
+ if (normalizedInfo(self, alts[i]).isSubType(otherinfo)) {
+ if (member == other)
+ member = alts[i];
+ else
+ unit.error(
+ pos,
+ "ambiguous override: both " +
+ member + ":" + normalizedInfo(self, member) +
+ "\n and " + alts[i] + ":" + normalizedInfo(self, alts[i]) +
+ "\n override " + other + ":" + otherinfo +
+ other.locationString());
+ }
+ }
+ break;
+ default:
+ member = member1;
}
}
}
+ if (member != other) {
+ checkOverride(pos, clazz, member, other);
+ }
+ if (clazz.kind == CLASS && (clazz.flags & ABSTRACTCLASS) == 0) {
+ if ((member.flags & DEFERRED) != 0) {
+ abstractClassError(
+ clazz,
+ member + member.locationString() + " is not defined" +
+ (((member.flags & MUTABLE) == 0) ? ""
+ : "\n(Note that variables need to be initialized to be defined)"));
+ } else if ((member.flags & OVERRIDE) != 0 &&
+ ((other.flags & DEFERRED) == 0 ||
+ overrides.get(member) == null))
+ overrides.put(member, other);
+ }
}
//where
private void abstractClassError(Symbol clazz, String msg) {
@@ -116,32 +138,6 @@ public class RefCheck extends Transformer implements Modifiers, Kinds {
clazz.flags |= ABSTRACTCLASS;
}
- Symbol findOverriding(int pos, Symbol clazz, Symbol members, Symbol other) {
- Type self = clazz.thisType();
- Symbol member = members;
- Type memberinfo = normalizedInfo(self, member);
- Type otherinfo = normalizedInfo(self, other);
- switch (memberinfo) {
- case OverloadedType(Symbol[] alts, Type[] alttypes):
- for (int i = 0; i < alts.length; i++) {
- if (alttypes[i].isSubType(otherinfo)) {
- if (member == members) {
- member = alts[i];
- memberinfo = alttypes[i];
- } else {
- unit.error(
- pos,
- "ambiguous override: both " +
- member + ":" + memberinfo +
- "\n and " + alts[i] + ":" + alttypes[i] +
- "\n override " + other + ":" + otherinfo +
- other.locationString());
- }
- }
- }
- }
- return member;
- }
/** Check that all conditions for overriding `other' by `member' are met.
* That is for overriding member M and overridden member O:
@@ -232,7 +228,10 @@ public class RefCheck extends Transformer implements Modifiers, Kinds {
Type normalizedInfo(Type site, Symbol sym) {
Type tp = site.memberInfo(sym);
- if (sym.kind == VAL && (sym.flags & STABLE) != 0) tp = tp.resultType();
+ switch (tp) {
+ case PolyType(Symbol[] tparams, Type restp):
+ if (tparams.length == 0) return restp;
+ }
return tp;
}