summaryrefslogtreecommitdiff
path: root/sources/scalac
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2003-06-24 16:05:41 +0000
committerMartin Odersky <odersky@gmail.com>2003-06-24 16:05:41 +0000
commita424426552bd2f25b76765f4f03cff92ee048fe9 (patch)
treee47df6d0a7a4995d2d7ac76a8963742a51e08d95 /sources/scalac
parent1f97bdd390266f51d12b0757e61babc0e36207ae (diff)
downloadscala-a424426552bd2f25b76765f4f03cff92ee048fe9.tar.gz
scala-a424426552bd2f25b76765f4f03cff92ee048fe9.tar.bz2
scala-a424426552bd2f25b76765f4f03cff92ee048fe9.zip
*** empty log message ***
Diffstat (limited to 'sources/scalac')
-rw-r--r--sources/scalac/ast/parser/Parser.java191
-rw-r--r--sources/scalac/ast/parser/Scanner.java53
-rw-r--r--sources/scalac/ast/parser/Tokens.java2
-rw-r--r--sources/scalac/symtab/SymbolTablePrinter.java5
-rw-r--r--sources/scalac/symtab/Type.java5
-rw-r--r--sources/scalac/typechecker/Analyzer.java2
-rw-r--r--sources/scalac/typechecker/RefCheck.java27
7 files changed, 151 insertions, 134 deletions
diff --git a/sources/scalac/ast/parser/Parser.java b/sources/scalac/ast/parser/Parser.java
index ceb25b4140..eb5d31426c 100644
--- a/sources/scalac/ast/parser/Parser.java
+++ b/sources/scalac/ast/parser/Parser.java
@@ -121,7 +121,7 @@ public class Parser implements Tokens {
|| (s.token == OVERRIDE);
}
- boolean isLocalClassModifier() {
+ boolean isLocalModifier() {
return (s.token == ABSTRACT)
|| (s.token == FINAL);
}
@@ -400,8 +400,8 @@ public class Parser implements Tokens {
}
}
- /** StableRef ::= StableId
- * | [Ident `.'] this
+ /** StableRef ::= StableId
+ * | [Ident `.'] this
* SimpleType ::= StableRef [`.' type]
*/
Tree stableRef(boolean thisOK, boolean typeOK) {
@@ -412,7 +412,9 @@ public class Parser implements Tokens {
t = selectors(accept(DOT), t, typeOK);
} else if (s.token == SUPER) {
t = make.Super(s.skipToken(), Tree.Empty);
- t = selectors(accept(DOT), t, typeOK);
+ t = make.Select(accept(DOT), t, ident());
+ if (s.token == DOT)
+ t = selectors(s.skipToken(), t, typeOK);
} else {
t = make.Ident(s.pos, ident());
if (s.token == DOT) {
@@ -422,6 +424,12 @@ public class Parser implements Tokens {
t = make.This(pos, convertToTypeId(t));
if (!thisOK || s.token == DOT)
t = selectors(accept(DOT), t, typeOK);
+ } else if (s.token == SUPER) {
+ s.nextToken();
+ t = make.Super(pos, convertToTypeId(t));
+ t = make.Select(accept(DOT), t, ident());
+ if (s.token == DOT)
+ t = selectors(s.skipToken(), t, typeOK);
} else {
t = selectors(pos, t, typeOK);
}
@@ -443,7 +451,9 @@ public class Parser implements Tokens {
}
}
- /** StableId ::= [[Ident `.'] this `.' | super] {Id `.'} Id
+ /** StableId ::= Id
+ * | StableRef `.' Id
+ * | [Ident '.'] super `.' Id
*/
Tree stableId() {
return stableRef(false, false);
@@ -663,8 +673,8 @@ public class Parser implements Tokens {
/** Expr ::= Bindings `=>' Expr
* | if `(' Expr `)' Expr [[`;'] else Expr]
- * | for `(' Enumerators `)' [do | yield] Expr
- * | Designator `=' Expr
+ * | for `(' Enumerators `)' (do | yield) Expr
+ * | [SimpleExpr `.'] Id `=' Expr
* | SimpleExpr ArgumentExprs `=' Expr
* | PostfixExpr [`:' Type1 | as Type1 | is Type1]
* Bindings ::= Id [`:' Type1]
@@ -757,7 +767,7 @@ public class Parser implements Tokens {
return reduceStack(true, base, top, 0, true);
}
- /** PrefixExpr ::= [op] SimpleExpr
+ /** PrefixExpr ::= [`-' | `+' | `~' | `!'] SimpleExpr
*/
Tree prefixExpr() {
Tree t;
@@ -774,18 +784,14 @@ public class Parser implements Tokens {
return t;
}
- /* SimpleExpr ::= SimpleExpr1
- * | SimpleExpr ArgumentExprs
- * | new Template
- * | BlockExpr
- * | `(' [Expr] `)'
- *
- * SimpleExpr1 ::= literal
- * | null
+ /* SimpleExpr ::= literal
* | StableRef
- * | super `.' Id
+ * | `(' [Expr] `)'
+ * | BlockExpr
+ * | new Template
* | SimpleExpr `.' Id
* | SimpleExpr TypeArgs
+ * | SimpleExpr ArgumentExprs
*/
Tree simpleExpr() {
Tree t;
@@ -804,11 +810,8 @@ public class Parser implements Tokens {
break;
case IDENTIFIER:
case THIS:
- t = stableRef(true, false);
- break;
case SUPER:
- int pos = s.skipToken();
- t = make.Select(accept(DOT), make.Super(pos, Tree.Empty), ident());
+ t = stableRef(true, false);
break;
case LPAREN:
int pos = s.skipToken();
@@ -824,7 +827,8 @@ public class Parser implements Tokens {
ts.append(exprs());
accept(RPAREN);
if (s.token == ARROW) {
- t = make.Function(pos, convertToParams(ts.toArray()), Tree.Empty);
+ t = make.Function(
+ pos, convertToParams(ts.toArray()), Tree.Empty);
} else {
t = syntaxError(commapos, "`)' expected", false);
}
@@ -903,21 +907,26 @@ public class Parser implements Tokens {
return res;
}
- /** BlockConstr ::= `{' Block `}'
+ /** ConstrExpr ::= Constr
+ * | `{' {BlockStat `;'} Constr `}'
*/
- Tree blockConstr() {
- int pos = accept(LBRACE);
- Tree res = block(pos);
- switch (res) {
- case Block(Tree[] stats):
- if (stats.length > 0)
- stats[stats.length - 1] = applyConstr(
- convertToConstr(stats[stats.length - 1]));
- else
- syntaxError(res.pos, "class constructor expected", false);
+ Tree constrExpr() {
+ if (s.token == LBRACE) {
+ int pos = s.skipToken();
+ Tree res = block(pos);
+ switch (res) {
+ case Block(Tree[] stats):
+ if (stats.length > 0)
+ stats[stats.length - 1] = applyConstr(
+ convertToConstr(stats[stats.length - 1]));
+ else
+ syntaxError(res.pos, "class constructor expected", false);
+ }
+ accept(RBRACE);
+ return res;
+ } else {
+ return constr();
}
- accept(RBRACE);
- return res;
}
/** Block ::= BlockStatSeq
@@ -928,20 +937,17 @@ public class Parser implements Tokens {
else return make.Block(pos, stats);
}
- /** CaseClause ::= case Pattern [if `(' Expr `)'] `=>' Block
+ /** CaseClause ::= case Pattern [if PostfixExpr] `=>' Block
*/
Tree caseClause() {
int pos = accept(CASE);
- Tree pat = pattern_valid();
+ Tree pat = validPattern();
Tree guard = Tree.Empty;
if (s.token == IF) {
s.nextToken();
- accept(LPAREN);
- guard = expr();
- accept(RPAREN);
+ guard = postfixExpr();
}
- accept(ARROW);
- return make.CaseDef(pos, pat, guard, block(s.pos));
+ return make.CaseDef(pos, pat, guard, block(accept(ARROW)));
}
/** Enumerators ::= Generator {`;' Enumerator}
@@ -963,7 +969,7 @@ public class Parser implements Tokens {
*/
Tree generator() {
int pos = accept(VAL);
- Tree pat = pattern_valid();
+ Tree pat = validPattern();
accept(LARROW);
Tree rhs = expr();
if (!TreeInfo.isVarPattern(pat))
@@ -987,8 +993,7 @@ public class Parser implements Tokens {
/** Pattern ( see pattern() ) which is checked for validity
*/
-
- Tree pattern_valid() {
+ Tree validPattern() {
int pos = s.pos;
Tree pat = pattern();
@@ -1096,10 +1101,9 @@ public class Parser implements Tokens {
/** SimplePattern ::= varid [ '@' SimplePattern ]
* | `_'
* | literal
- * | null
- * | StableId {ArgumentPatterns}
+ * | StableId [ArgumentPatterns]
* | `(' Patterns `)'
- * | ((nothing))
+ * | ((nothing)) //???
*/
Tree simplePattern() {
switch (s.token) {
@@ -1209,8 +1213,8 @@ public class Parser implements Tokens {
}
}
- /** LocalClassModifiers ::= {LocalClassModifier}
- * LocalClassModifier ::= final
+ /** LocalModifiers ::= {LocalModifier}
+ * LocalModifier ::= final
* | private
*/
int localClassModifiers() {
@@ -1341,22 +1345,22 @@ public class Parser implements Tokens {
//////// DEFS ////////////////////////////////////////////////////////////////
- /** Import ::= import ImportRef {`,' ImportRef}
+ /** Import ::= import ImportExpr {`,' ImportExpr}
*/
Tree[] importClause() {
accept(IMPORT);
TreeList ts = new TreeList();
- ts.append(importRef());
+ ts.append(importExpr());
while (s.token == COMMA) {
s.nextToken();
- ts.append(importRef());
+ ts.append(importExpr());
}
return ts.toArray();
}
/** ImportRef ::= StableId `.' (Id | `_' | ImportSelectors)
*/
- Tree importRef() {
+ Tree importExpr() {
Tree t;
int startpos = s.pos;
int pos;
@@ -1409,7 +1413,7 @@ public class Parser implements Tokens {
return (Name[])names.toArray(new Name[]{});
}
- /** ImportSelector ::= Id [`=>' [Id | `_']]
+ /** ImportSelector ::= Id [`=>' Id | `=>' `_']
*/
boolean importSelector(LinkedList/*<Name>*/ names) {
if (s.token == USCORE) {
@@ -1439,11 +1443,11 @@ public class Parser implements Tokens {
* | def FunDef {`,' FunDef}
* | constr ConstrDef {`,' ConstrDef}
* | type TypeDef {`,' TypeDef}
- * | TopDef
- * Dcl ::= val ValSig {`,' ValSig}
- * | var ValSig {`,' ValSig}
- * | def FunSig {`,' FunSig}
- * | constr ConstrSig {`,' ConstrSig}
+ * | ClsDef
+ * Dcl ::= val ValDcl {`,' ValDcl}
+ * | var ValDcl {`,' ValDcl}
+ * | def FunDcl {`,' FunDcl}
+ * | constr ConstrDcl {`,' ConstrDcl}
* | type TypeDcl {`,' TypeDcl}
*/
Tree[] defOrDcl(int mods) {
@@ -1452,42 +1456,42 @@ public class Parser implements Tokens {
case VAL:
do {
s.nextToken();
- ts.append(patDefOrSig(mods));
+ ts.append(patDefOrDcl(mods));
} while (s.token == COMMA);
return ts.toArray();
case VAR:
do {
s.nextToken();
- ts.append(varDefOrSig(mods));
+ ts.append(varDefOrDcl(mods));
} while (s.token == COMMA);
return ts.toArray();
case DEF:
do {
s.nextToken();
- ts.append(funDefOrSig(mods));
+ ts.append(funDefOrDcl(mods));
} while (s.token == COMMA);
return ts.toArray();
case CONSTR:
do {
s.nextToken();
- ts.append(constrDefOrSig(mods));
+ ts.append(constrDefOrDcl(mods));
} while (s.token == COMMA);
return ts.toArray();
case TYPE:
do {
s.nextToken();
- ts.append(typeDefOrSig(mods));
+ ts.append(typeDefOrDcl(mods));
} while (s.token == COMMA);
return ts.toArray();
default:
- return topDef(mods);
+ return clsDef(mods);
}
}
- /** TopDef ::= ([case] class | trait) ClassDef {`,' ClassDef}
- * | [case] object ModuleDef {`,' ModuleDef}
+ /** ClsDef ::= ([case] class | trait) ClassDef {`,' ClassDef}
+ * | [case] object ObjectDef {`,' ObjectDef}
*/
- Tree[] topDef(int mods) {
+ Tree[] clsDef(int mods) {
TreeList ts = new TreeList();
switch (s.token) {
case CLASS:
@@ -1504,7 +1508,7 @@ public class Parser implements Tokens {
case CASEOBJECT:
do {
s.nextToken();
- ts.append(moduleDef(mods));
+ ts.append(objectDef(mods));
} while (s.token == COMMA);
return ts.toArray();
default:
@@ -1513,9 +1517,9 @@ public class Parser implements Tokens {
}
/** PatDef ::= Pattern `=' Expr
- * ValSig ::= Id `:' Type
+ * ValDcl ::= Id `:' Type
*/
- Tree patDefOrSig(int mods) {
+ Tree patDefOrDcl(int mods) {
int pos = s.pos;
Tree pat = pattern();
Tree tp;
@@ -1541,9 +1545,9 @@ public class Parser implements Tokens {
/** VarDef ::= Id [`:' Type] `=' Expr
* | Id `:' Type `=' `_'
- * VarSig ::= Id `:' Type
+ * VarDcl ::= Id `:' Type
*/
- Tree varDefOrSig(int mods) {
+ Tree varDefOrDcl(int mods) {
int pos = s.pos;
Name name = ident();
Tree type = typedOpt();
@@ -1564,9 +1568,9 @@ public class Parser implements Tokens {
}
/** FunDef ::= Id [FunTypeParamClause] {ParamClauses} [`:' Type] `=' Expr
- * FunSig ::= Id [FunTypeParamClause] {ParamClauses} `:' Type
+ * FunDcl ::= Id [FunTypeParamClause] {ParamClauses} `:' Type
*/
- Tree funDefOrSig(int mods) {
+ Tree funDefOrDcl(int mods) {
int pos = s.pos;
Name name = ident();
TypeDef[] tparams = typeParamClauseOpt(false);
@@ -1580,9 +1584,9 @@ public class Parser implements Tokens {
tparams, vparams, restype, Tree.Empty);
}
- /* ConstrDef ::= Id [FunTypeParamClause] [ParamClause] [`:' Type] `=' (Constr | BlockConstr)
+ /* ConstrDef ::= Id [FunTypeParamClause] [ParamClause] [`:' Type] `=' ConstrExpr
*/
- Tree constrDefOrSig(int mods) {
+ Tree constrDefOrDcl(int mods) {
int pos = s.pos;
Name name = ident().toConstrName();
TypeDef[] tparams = typeParamClauseOpt(false);
@@ -1590,8 +1594,8 @@ public class Parser implements Tokens {
Tree restype = typedOpt();
if (s.token == EQUALS || restype == Tree.Empty) {
accept(EQUALS);
- return make.DefDef(pos, mods, name, tparams, vparams,
- restype, (s.token == LBRACE) ? blockConstr() : constr());
+ return make.DefDef(
+ pos, mods, name, tparams, vparams, restype, constrExpr());
} else
return make.DefDef(pos, mods | Modifiers.DEFERRED, name,
tparams, vparams, restype, Tree.Empty);
@@ -1600,7 +1604,7 @@ public class Parser implements Tokens {
/** TypeDef ::= Id `=' Type
* TypeDcl ::= Id TypeBounds
*/
- Tree typeDefOrSig(int mods) {
+ Tree typeDefOrDcl(int mods) {
int pos = s.pos;
Name name = ident().toTypeName();
switch (s.token) {
@@ -1618,7 +1622,7 @@ public class Parser implements Tokens {
}
}
- /** ClassDef ::= Id [TypeParamClause] [`:' SimpleType] ClassTemplate
+ /** ClassDef ::= Id [TypeParamClause] [ParamClause] [`:' SimpleType] ClassTemplate
*/
Tree classDef(int mods) {
int pos = s.pos;
@@ -1630,25 +1634,29 @@ public class Parser implements Tokens {
simpleTypedOpt(), classTemplate());
}
- /** ModuleDef ::= Id [`:' SimpleType] ClassTemplate
+ /** ObjectDef ::= Id [`:' SimpleType] ClassTemplate
*/
- Tree moduleDef(int mods) {
- return make.ModuleDef(
+ Tree objectDef(int mods) {
+ return make.ObjectDef(
s.pos, mods, ident(), simpleTypedOpt(), classTemplate());
}
- /** ClassTemplate ::= [`extends' Constr] {`with' Constr} [TemplateBody]
+ /** ClassTemplate ::= `extends' Template
+ * | TemplateBody
+ * |
*/
Template classTemplate() {
int pos = s.pos;
if (s.token == EXTENDS) {
s.nextToken();
return template();
+/*
} else if (s.token == WITH) {
s.nextToken();
TreeList parents = new TreeList();
parents.append(scalaObjectConstr(pos));
return template(parents);
+*/
} else if (s.token == LBRACE) {
return (Template)make.Template(
pos, new Tree[]{scalaObjectConstr(pos)}, templateBody());
@@ -1724,7 +1732,7 @@ public class Parser implements Tokens {
}
/** TopStatSeq ::= [TopStat {`;' TopStat}]
- * TopStat ::= Modifiers TopDef
+ * TopStat ::= Modifiers ClsDef
* | Packaging
* | Import
* |
@@ -1742,7 +1750,7 @@ public class Parser implements Tokens {
s.token == OBJECT ||
s.token == CASEOBJECT ||
isModifier()) {
- stats.append(topDef(modifiers()));
+ stats.append(clsDef(modifiers()));
} else if (s.token != SEMI) {
syntaxError("illegal start of class or object definition", true);
}
@@ -1756,7 +1764,6 @@ public class Parser implements Tokens {
* | Modifiers Def
* | Modifiers Dcl
* | Expr
- * % | val this `:' Type
* |
*/
Tree[] templateStatSeq() {
@@ -1797,7 +1804,7 @@ public class Parser implements Tokens {
/** BlockStatSeq ::= { BlockStat `;' } [Expr]
* BlockStat ::= Import
* | Def
- * | LocalClassModifiers TopDef
+ * | LocalModifiers ClsDef
* | Expr
* |
*/
@@ -1815,8 +1822,8 @@ public class Parser implements Tokens {
if (s.token == RBRACE) {
stats.append(make.Block(s.pos, Tree.EMPTY_ARRAY));
}
- } else if (isLocalClassModifier()) {
- stats.append(topDef(localClassModifiers()));
+ } else if (isLocalModifier()) {
+ stats.append(clsDef(localClassModifiers()));
accept(SEMI);
if (s.token == RBRACE) {
stats.append(make.Block(s.pos, Tree.EMPTY_ARRAY));
diff --git a/sources/scalac/ast/parser/Scanner.java b/sources/scalac/ast/parser/Scanner.java
index c2eb82a27e..e2a95d3dbf 100644
--- a/sources/scalac/ast/parser/Scanner.java
+++ b/sources/scalac/ast/parser/Scanner.java
@@ -117,7 +117,7 @@ public class Scanner extends TokenData {
case COMMA: case SEMI: case DOT:
case COLON: case EQUALS: case ARROW:
case LARROW: case SUBTYPE: case SUPERTYPE:
- case HASH: case AS: case IS:
+ case HASH: case AT: case AS: case IS:
case RPAREN: case RBRACKET: case RBRACE:
break;
default:
@@ -791,33 +791,37 @@ public class Scanner extends TokenData {
}
protected void initKeywords() {
- enterKeyword("if", IF);
- enterKeyword("for", FOR);
- enterKeyword("else", ELSE);
- enterKeyword("this", THIS);
- enterKeyword("null", NULL);
- enterKeyword("new", NEW);
- enterKeyword("with", WITH);
- enterKeyword("super", SUPER);
- enterKeyword("case", CASE);
- enterKeyword("val", VAL);
enterKeyword("abstract", ABSTRACT);
- enterKeyword("final", FINAL);
- enterKeyword("private", PRIVATE);
- enterKeyword("protected", PROTECTED);
- enterKeyword("override", OVERRIDE);
- enterKeyword("var", VAR);
+ enterKeyword("as", AS);
+ enterKeyword("case", CASE);
+ enterKeyword("class", CLASS);
+ enterKeyword("constr", CONSTR);
enterKeyword("def", DEF);
- enterKeyword("type", TYPE);
+ enterKeyword("do", DO);
+ enterKeyword("else", ELSE);
enterKeyword("extends", EXTENDS);
- enterKeyword("object", OBJECT);
- enterKeyword("module", OBJECT1);
- enterKeyword("class",CLASS);
- enterKeyword("constr",CONSTR);
+ enterKeyword("final", FINAL);
+ enterKeyword("false", FALSE);
+ enterKeyword("for", FOR);
+ enterKeyword("if", IF);
+ enterKeyword("is", IS);
enterKeyword("import", IMPORT);
+ enterKeyword("new", NEW);
+ enterKeyword("null", NULL);
+ enterKeyword("object", OBJECT);
+ enterKeyword("override", OVERRIDE);
enterKeyword("package", PACKAGE);
+ enterKeyword("private", PRIVATE);
+ enterKeyword("protected", PROTECTED);
+ enterKeyword("super", SUPER);
+ enterKeyword("this", THIS);
+ enterKeyword("trait", TRAIT);
enterKeyword("true", TRUE);
- enterKeyword("false", FALSE);
+ enterKeyword("type", TYPE);
+ enterKeyword("val", VAL);
+ enterKeyword("var", VAR);
+ enterKeyword("with", WITH);
+ enterKeyword("yield", YIELD);
enterKeyword(".", DOT);
enterKeyword("_", USCORE);
enterKeyword(":", COLON);
@@ -826,12 +830,7 @@ public class Scanner extends TokenData {
enterKeyword("<-", LARROW);
enterKeyword("<:", SUBTYPE);
enterKeyword(">:", SUPERTYPE);
- enterKeyword("yield", YIELD);
- enterKeyword("do", DO);
enterKeyword("#", HASH);
- enterKeyword("trait", TRAIT);
- enterKeyword("as", AS);
- enterKeyword("is", IS);
enterKeyword("@", AT);
}
}
diff --git a/sources/scalac/ast/parser/Tokens.java b/sources/scalac/ast/parser/Tokens.java
index b19455fa13..cad7a2da8b 100644
--- a/sources/scalac/ast/parser/Tokens.java
+++ b/sources/scalac/ast/parser/Tokens.java
@@ -61,8 +61,6 @@ public interface Tokens {
DO = 51,
TRAIT = 52,
- OBJECT1 = 53, // todo: elim
-
/* special symbols */
COMMA = 61,
SEMI = 62,
diff --git a/sources/scalac/symtab/SymbolTablePrinter.java b/sources/scalac/symtab/SymbolTablePrinter.java
index bb54020050..e934073e94 100644
--- a/sources/scalac/symtab/SymbolTablePrinter.java
+++ b/sources/scalac/symtab/SymbolTablePrinter.java
@@ -250,7 +250,7 @@ public class SymbolTablePrinter {
case Kinds.NONE:
return null;
case Kinds.CLASS:
- if (symbol.isTrait()) return "trait";
+ if (symbol.isTrait()) return "trait";
if (symbol.isModuleClass() && global.debug) return "object class";
return "class";
case Kinds.TYPE:
@@ -261,7 +261,8 @@ public class SymbolTablePrinter {
if (symbol.isModule()) return "object";
if (symbol.isConstructor()) return "constructor";
if (symbol.isInitializedMethod())
- if (global.debug || !symbol.isStable()) return "method";
+ if (global.debug || (symbol.flags & Modifiers.STABLE) == 0)
+ return "method";
return "value";
default:
throw Debug.abort("unknown kind " + symbol.kind);
diff --git a/sources/scalac/symtab/Type.java b/sources/scalac/symtab/Type.java
index 37bbfaf417..328ef7bacf 100644
--- a/sources/scalac/symtab/Type.java
+++ b/sources/scalac/symtab/Type.java
@@ -5,7 +5,8 @@
**
** $Id$
\* */
-//todo: implement rule single
+//todo: T {} == T
+
package scalac.symtab;
@@ -1267,7 +1268,7 @@ public class Type implements Modifiers, Kinds, TypeTags {
case TypeRef(Type pre1, Symbol sym1, Type[] args1):
switch (this) {
case TypeRef(Type pre, Symbol sym, Type[] args):
- if (sym == sym1 && pre.isSameAs(pre1) &&
+ if (sym.name == sym1.name && pre.isSubType(pre1) &&
isSubArgs(args, args1, sym.typeParams())
||
sym.kind == TYPE && pre.memberInfo(sym).isSubType(that))
diff --git a/sources/scalac/typechecker/Analyzer.java b/sources/scalac/typechecker/Analyzer.java
index bbac26f18e..03377ef78c 100644
--- a/sources/scalac/typechecker/Analyzer.java
+++ b/sources/scalac/typechecker/Analyzer.java
@@ -13,6 +13,8 @@
// type members.
// todo: use mangled name or drop.
// todo: emit warnings for unchecked.
+// todo: qualified super.
+// todo: pattern definitions with 0 or 1 bound variable.
package scalac.typechecker;
diff --git a/sources/scalac/typechecker/RefCheck.java b/sources/scalac/typechecker/RefCheck.java
index 5b2f449cbd..11486c645b 100644
--- a/sources/scalac/typechecker/RefCheck.java
+++ b/sources/scalac/typechecker/RefCheck.java
@@ -216,19 +216,23 @@ public class RefCheck extends Transformer implements Modifiers, Kinds {
* 2. Check that later type instances in the base-type sequence
* of a class are subtypes of earlier type instances of the same trait.
* 3. Check that case classes do not inherit from case classes.
+ * 4. Check that at most one base type is a case-class.
*/
void validateBaseTypes(Symbol clazz) {
validateBaseTypes(clazz, clazz.type().parents(),
- new Type[clazz.closure().length], 0);
+ new Type[clazz.closure().length], clazz, 0);
}
//where
- void validateBaseTypes(Symbol clazz, Type[] tps, Type[] seen, int start) {
+ void validateBaseTypes(Symbol clazz, Type[] tps, Type[] seen,
+ Symbol caseSeen, int start) {
for (int i = tps.length - 1; i >= start; i--) {
- validateBaseTypes(clazz, tps[i].unalias(), seen, i == 0 ? 0 : 1);
+ validateBaseTypes(
+ clazz, tps[i].unalias(), seen, caseSeen, i == 0 ? 0 : 1);
}
}
- void validateBaseTypes(Symbol clazz, Type tp, Type[] seen, int start) {
+ void validateBaseTypes(Symbol clazz, Type tp, Type[] seen,
+ Symbol caseSeen, int start) {
Symbol baseclazz = tp.symbol();
if (baseclazz.kind == CLASS) {
int index = clazz.closurePos(baseclazz);
@@ -250,12 +254,16 @@ public class RefCheck extends Transformer implements Modifiers, Kinds {
}
}
// check that case classes do not inherit from case classes
- if (clazz.isCaseClass() && baseclazz.isCaseClass())
- unit.error(clazz.pos, "illegal inheritance;\n " + "case " + clazz +
- " inherits from other case " + baseclazz);
+ if (baseclazz.isCaseClass())
+ if (caseSeen.isCaseClass())
+ unit.error(
+ clazz.pos, "illegal combination of case " +
+ caseSeen + "and case " + baseClazz + " in one object");
+ else
+ caseSeen = baseclazz;
seen[index] = tp;
- validateBaseTypes(clazz, tp.parents(), seen, start);
+ validateBaseTypes(clazz, tp.parents(), seen, caseSeen, start);
}
}
@@ -796,9 +804,10 @@ public class RefCheck extends Transformer implements Modifiers, Kinds {
if (sym.isLocal() && !sym.isModule() && index <= maxindex[level]) {
if (Global.instance.debug)
System.out.println(refsym[level] + ":" + refsym[level].type());
+ String kind == ((sym.flags & MUTABLE) != 0) ? "variable" : "value";
unit.error(
refpos[level],
- "forward reference extends over definition of value " +
+ "forward reference extends over definition of " + kind + " " +
normalize(name));
}
return tree1;