*** empty log message ***
git-svn-id: http://lampsvn.epfl.ch/svn-repos/scala/scala/trunk@3053 5e8d7ff9-d8ef-0310-90f0-a4852d11357a
This commit is contained in:
parent
3fb3ee4ff2
commit
0e50f11a89
|
@ -2207,21 +2207,26 @@ which appear in the same statement sequence as the definition of
|
||||||
A class definition which starts with the reserved word \code{trait}
|
A class definition which starts with the reserved word \code{trait}
|
||||||
instead of \code{class} defines a trait. A trait is a specific
|
instead of \code{class} defines a trait. A trait is a specific
|
||||||
instance of an abstract class, so the \code{abstract} modifier is
|
instance of an abstract class, so the \code{abstract} modifier is
|
||||||
redundant for it. The template of a trait must satisfy the following
|
redundant for it. The trait definition must satisfy the following
|
||||||
four restrictions.
|
four restrictions.
|
||||||
\begin{enumerate}
|
\begin{enumerate}
|
||||||
\item All base classes of the trait are traits.
|
\item There are no value parameters in the trait's primary constructor, nor
|
||||||
\item All parent class constructors of a template
|
are there secondary constructors.
|
||||||
must be primary constructors with empty value
|
\item All mixin base classes of the trait are traits.
|
||||||
|
\item All parent class constructors of the trait
|
||||||
|
are primary constructors with empty value
|
||||||
parameter lists.
|
parameter lists.
|
||||||
\item All non-empty statements in the template are either imports or pure definitions.
|
\item All non-empty statements in the trait's template are either
|
||||||
\item A trait may not have secondary constructors.
|
imports or pure definitions.
|
||||||
\end{enumerate}
|
\end{enumerate}
|
||||||
A {\em pure} definition can be evaluated without any side effect.
|
A {\em pure} definition can be evaluated without any side effect.
|
||||||
Function, type, class, or object definitions are always pure. A value
|
Function, type, class, or object definitions are always pure. A value
|
||||||
definition is pure if its right-hand side expression is pure. Pure
|
definition is pure if its right-hand side expression is pure. A
|
||||||
expressions are paths, literals, and typed expressions
|
secondary constructor definition is pure if its right-hand side
|
||||||
$e: T$ where $e$ is pure.
|
consists only
|
||||||
|
Pure
|
||||||
|
expressions are paths, literals, and typed expressions $e: T$ where
|
||||||
|
$e$ is pure.
|
||||||
|
|
||||||
These restrictions ensure that the evaluation of the mixin constructor
|
These restrictions ensure that the evaluation of the mixin constructor
|
||||||
of a trait has no effect. Therefore, traits may appear several times
|
of a trait has no effect. Therefore, traits may appear several times
|
||||||
|
|
|
@ -481,27 +481,54 @@ class Analyzer(global: scalac_Global, descr: AnalyzerPhase) extends Transformer(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Check that tree represents a pure definition.
|
/** Check that tree represents a legal trait definition.
|
||||||
*/
|
*/
|
||||||
def checkPureDef(tree: Tree, clazz: Symbol): unit = {
|
def checkTraitDef(pos: int, clazz: Symbol, templ: Tree$Template) = {
|
||||||
if (!TreeInfo.isPureDef(tree) && !tree.getType().isError())
|
|
||||||
error(tree.pos, "" + clazz + " may contain only pure definitions");
|
/** Check that type does not have value parameters
|
||||||
|
*/
|
||||||
|
def checkNoParams(tpe: Type): unit = tpe match {
|
||||||
|
case Type$MethodType(vparams, _) =>
|
||||||
|
if (vparams.length > 0)
|
||||||
|
error(pos, "trait may not have value parameters")
|
||||||
|
case Type$PolyType(tparams, restpe) =>
|
||||||
|
checkNoParams(infer.skipViewParams(tparams, restpe))
|
||||||
|
case _ =>
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Check that tree represents a pure constructor.
|
/** Check that tree represents a pure constructor.
|
||||||
*/
|
*/
|
||||||
def checkPureConstr(tree: Tree, clazz: Symbol): unit = {
|
def checkPureConstr(tree: Tree): unit = {
|
||||||
if (!TreeInfo.isPureConstr(tree) && !tree.getType().isError())
|
if (!TreeInfo.isPureConstr(tree) && !tree.getType().isError())
|
||||||
error(tree.pos, "" + clazz + " may invoke only pure superclass constructors");
|
error(tree.pos, "" + clazz + " may invoke only pure superclass constructors");
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Check that tree represents a trait constructor.
|
/** Check that tree refers to a trait
|
||||||
*/
|
*/
|
||||||
def checkTrait(tree: Tree, clazz: Symbol): unit = {
|
def checkTraitRef(tree: Tree): unit = {
|
||||||
if (!tree.getType().symbol().isTrait() && !tree.getType().isError())
|
if (!tree.getType().symbol().isTrait() && !tree.getType().isError())
|
||||||
error(tree.pos, " " + clazz + " may inherit only traits as mixins");
|
error(tree.pos, " " + clazz + " may inherit only traits as mixins");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Check that tree represents a pure definition.
|
||||||
|
*/
|
||||||
|
def checkPureDef(tree: Tree): unit = {
|
||||||
|
if (!TreeInfo.isPureDef(tree) && !tree.getType().isError())
|
||||||
|
error(tree.pos, "" + clazz + " may contain only pure definitions");
|
||||||
|
}
|
||||||
|
|
||||||
|
checkNoParams(clazz.primaryConstructor().getType());
|
||||||
|
var i = 0; while (i < templ.parents.length) {
|
||||||
|
checkPureConstr(templ.parents(i));
|
||||||
|
if (i >= 1) checkTraitRef(templ.parents(i));
|
||||||
|
i = i + 1
|
||||||
|
}
|
||||||
|
var j = 0; while (j < templ.body.length) {
|
||||||
|
checkPureDef(templ.body(j));
|
||||||
|
j = j + 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Check that tree is a stable expression .p
|
/** Check that tree is a stable expression .p
|
||||||
*/
|
*/
|
||||||
def checkStable(tree: Tree): Tree =
|
def checkStable(tree: Tree): Tree =
|
||||||
|
@ -1082,7 +1109,10 @@ class Analyzer(global: scalac_Global, descr: AnalyzerPhase) extends Transformer(
|
||||||
case Tree$ModuleDef(mods, name, _tpe, templ) =>
|
case Tree$ModuleDef(mods, name, _tpe, templ) =>
|
||||||
var tpe = _tpe;
|
var tpe = _tpe;
|
||||||
val clazz: Symbol = sym.moduleClass();
|
val clazz: Symbol = sym.moduleClass();
|
||||||
|
pushContext(
|
||||||
|
tree, clazz.primaryConstructor(), context.scope);
|
||||||
defineTemplate(templ, clazz, new Scope());
|
defineTemplate(templ, clazz, new Scope());
|
||||||
|
popContext();
|
||||||
clazz.setInfo(templ.getType());
|
clazz.setInfo(templ.getType());
|
||||||
tpe = transform(tpe, TYPEmode);
|
tpe = transform(tpe, TYPEmode);
|
||||||
(tree.asInstanceOf[Tree$ModuleDef]).tpe = tpe;
|
(tree.asInstanceOf[Tree$ModuleDef]).tpe = tpe;
|
||||||
|
@ -1390,7 +1420,12 @@ class Analyzer(global: scalac_Global, descr: AnalyzerPhase) extends Transformer(
|
||||||
(infer.isCompatible(tree.getType(), pt) ||
|
(infer.isCompatible(tree.getType(), pt) ||
|
||||||
pt.symbol() == definitions.UNIT_CLASS)) {
|
pt.symbol() == definitions.UNIT_CLASS)) {
|
||||||
checkEtaExpandable(tree.pos, tree.getType());
|
checkEtaExpandable(tree.pos, tree.getType());
|
||||||
|
if (TreeInfo.methPart(tree).symbol() == definitions.ANY_MATCH) {
|
||||||
|
error(tree.pos, "`match' needs to be applied fully");
|
||||||
|
return errorTree(tree)
|
||||||
|
} else {
|
||||||
return transform(desugarize.etaExpand(tree, tree.getType()), mode, pt);
|
return transform(desugarize.etaExpand(tree, tree.getType()), mode, pt);
|
||||||
|
}
|
||||||
} else if ((mode & (CONSTRmode | FUNmode)) == CONSTRmode) {
|
} else if ((mode & (CONSTRmode | FUNmode)) == CONSTRmode) {
|
||||||
error(tree.pos, "missing arguments for class constructor");
|
error(tree.pos, "missing arguments for class constructor");
|
||||||
return errorTermTree(tree);
|
return errorTermTree(tree);
|
||||||
|
@ -1584,7 +1619,28 @@ class Analyzer(global: scalac_Global, descr: AnalyzerPhase) extends Transformer(
|
||||||
while (nextimports != null && nextimports.tree.pos >= tree.pos) {
|
while (nextimports != null && nextimports.tree.pos >= tree.pos) {
|
||||||
nextimports = nextimports.prev;
|
nextimports = nextimports.prev;
|
||||||
}
|
}
|
||||||
while (sym1.kind == NONE && nextimports != null && nextimports.tree.pos > stopPos) {
|
|
||||||
|
if (stopPos > tree.pos) {
|
||||||
|
// set stopPos to beginning of block enclosed in the scope which defines the
|
||||||
|
// referenced symbol.
|
||||||
|
var lastc = Context.NONE;
|
||||||
|
var c = nextcontext;
|
||||||
|
while (c.outer.scope != null && c.outer.scope.lookup(name) == sym) {
|
||||||
|
c.tree match {
|
||||||
|
case Tree$Block(_, _) | Tree$CaseDef(_, _, _) | Tree$ClassDef(_, _, _, _, _, _) | Tree$ModuleDef(_, _, _, _) =>
|
||||||
|
lastc = c;
|
||||||
|
case _ =>
|
||||||
|
}
|
||||||
|
c = c.outer
|
||||||
|
}
|
||||||
|
if (lastc != Context.NONE) {
|
||||||
|
//System.out.println("revising stop to [" + lastc.tree + "]; symbol = " + sym + ", context = " + nextcontext);//debug
|
||||||
|
stopPos = lastc.tree.pos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (sym1.kind == NONE &&
|
||||||
|
nextimports != null && nextimports.tree.pos > stopPos) {
|
||||||
sym1 = nextimports.importedSymbol(name);
|
sym1 = nextimports.importedSymbol(name);
|
||||||
lastimports = nextimports;
|
lastimports = nextimports;
|
||||||
nextimports = nextimports.prev;
|
nextimports = nextimports.prev;
|
||||||
|
@ -1842,17 +1898,6 @@ class Analyzer(global: scalac_Global, descr: AnalyzerPhase) extends Transformer(
|
||||||
popContext();
|
popContext();
|
||||||
*/
|
*/
|
||||||
popContext();
|
popContext();
|
||||||
if (owner.isTrait()) {
|
|
||||||
var i = 0; while (i < parents.length) {
|
|
||||||
checkPureConstr(parents(i), owner);
|
|
||||||
if (i >= 1) checkTrait(parents(i), owner);
|
|
||||||
i = i + 1
|
|
||||||
}
|
|
||||||
var j = 0; while (j < templ.body.length) {
|
|
||||||
checkPureDef(body1(j), owner);
|
|
||||||
j = j + 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
val templ1: Tree$Template = copy.Template(templ, parents, body1);
|
val templ1: Tree$Template = copy.Template(templ, parents, body1);
|
||||||
templ1.setType(owner.getType());
|
templ1.setType(owner.getType());
|
||||||
templ1
|
templ1
|
||||||
|
@ -2098,14 +2143,19 @@ class Analyzer(global: scalac_Global, descr: AnalyzerPhase) extends Transformer(
|
||||||
templ.body, vparams(vparams.length - 1));
|
templ.body, vparams(vparams.length - 1));
|
||||||
|
|
||||||
val templ1: Tree$Template = transformTemplate(templ, sym);
|
val templ1: Tree$Template = transformTemplate(templ, sym);
|
||||||
|
if (sym.isTrait()) checkTraitDef(tree.pos, sym, templ1);
|
||||||
checkNoEscape(tree.pos, sym.info());
|
checkNoEscape(tree.pos, sym.info());
|
||||||
popContext();
|
popContext();
|
||||||
copy.ClassDef(tree, sym, tparams1, vparams1, tpe1, templ1)
|
copy.ClassDef(tree, sym, tparams1, vparams1, tpe1, templ1)
|
||||||
.setType(Type.NoType);
|
.setType(Type.NoType);
|
||||||
|
|
||||||
case Tree$ModuleDef(_, _, tpe, templ) =>
|
case Tree$ModuleDef(_, _, tpe, templ) =>
|
||||||
sym.moduleClass().initialize();
|
val clazz = sym.moduleClass();
|
||||||
|
clazz.initialize();
|
||||||
|
pushContext(
|
||||||
|
tree, clazz.primaryConstructor(), context.scope);
|
||||||
val tpe1: Tree = transform(tpe, TYPEmode);
|
val tpe1: Tree = transform(tpe, TYPEmode);
|
||||||
|
popContext();
|
||||||
val templ1: Tree$Template = transformTemplate(templ, sym.moduleClass());
|
val templ1: Tree$Template = transformTemplate(templ, sym.moduleClass());
|
||||||
if (tpe1 != Tree.Empty && !templ1.getType().isSubType(tpe1.getType()))
|
if (tpe1 != Tree.Empty && !templ1.getType().isSubType(tpe1.getType()))
|
||||||
error(tree.pos, "" + sym + " does not implement " + tpe1.getType());
|
error(tree.pos, "" + sym + " does not implement " + tpe1.getType());
|
||||||
|
@ -2417,6 +2467,7 @@ class Analyzer(global: scalac_Global, descr: AnalyzerPhase) extends Transformer(
|
||||||
val body1: Tree = transform(body, EXPRmode, restype);
|
val body1: Tree = transform(body, EXPRmode, restype);
|
||||||
if (!infer.isFullyDefined(restype))
|
if (!infer.isFullyDefined(restype))
|
||||||
restype = body1.getType().deconst();
|
restype = body1.getType().deconst();
|
||||||
|
restype = checkNoEscape(tree.pos, restype);
|
||||||
popContext();
|
popContext();
|
||||||
gen.mkFunction(tree.pos, vparams1, body1, restype, context.owner);
|
gen.mkFunction(tree.pos, vparams1, body1, restype, context.owner);
|
||||||
|
|
||||||
|
@ -2506,6 +2557,7 @@ class Analyzer(global: scalac_Global, descr: AnalyzerPhase) extends Transformer(
|
||||||
var c = context;
|
var c = context;
|
||||||
while (c != Context.NONE &&
|
while (c != Context.NONE &&
|
||||||
!c.tree.isInstanceOf[Tree$ClassDef] &&
|
!c.tree.isInstanceOf[Tree$ClassDef] &&
|
||||||
|
!c.tree.isInstanceOf[Tree$ModuleDef] &&
|
||||||
!c.tree.isInstanceOf[Tree$Template])
|
!c.tree.isInstanceOf[Tree$Template])
|
||||||
c = c.outer;
|
c = c.outer;
|
||||||
enclClassOrConstructorContext = c
|
enclClassOrConstructorContext = c
|
||||||
|
|
|
@ -77,13 +77,16 @@ public class TreeInfo {
|
||||||
case Tree.Empty:
|
case Tree.Empty:
|
||||||
case ClassDef(_, _, _, _, _, _):
|
case ClassDef(_, _, _, _, _, _):
|
||||||
case ModuleDef(_, _, _, _):
|
case ModuleDef(_, _, _, _):
|
||||||
case DefDef(_, _, _, _, _, _):
|
|
||||||
case AbsTypeDef(_, _, _, _):
|
case AbsTypeDef(_, _, _, _):
|
||||||
case AliasTypeDef(_, _, _, _):
|
case AliasTypeDef(_, _, _, _):
|
||||||
case Import(_, _):
|
case Import(_, _):
|
||||||
return true;
|
return true;
|
||||||
|
case DefDef(_, Name name, _, _, _, _):
|
||||||
|
return name != Names.CONSTRUCTOR;
|
||||||
case ValDef(int mods, _, _, Tree rhs):
|
case ValDef(int mods, _, _, Tree rhs):
|
||||||
return (mods & Modifiers.MUTABLE) == 0 && isPureExpr(rhs);
|
return (mods & Modifiers.MUTABLE) == 0 && isPureExpr(rhs);
|
||||||
|
case DocDef(_, Tree definition):
|
||||||
|
return isPureDef(definition);
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
/home/odersky/scala/test/files/neg/Y.scala:3: `match' needs to be applied fully
|
||||||
|
def f(x: Object): java.lang.Object /* !!! Object */ = x.match;
|
||||||
|
^
|
||||||
|
one error found
|
|
@ -0,0 +1,2 @@
|
||||||
|
object Test extends java.rmi.server.UnicastRemoteObject {
|
||||||
|
}
|
Loading…
Reference in New Issue