*** 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}
|
||||
instead of \code{class} defines a trait. A trait is a specific
|
||||
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.
|
||||
\begin{enumerate}
|
||||
\item All base classes of the trait are traits.
|
||||
\item All parent class constructors of a template
|
||||
must be primary constructors with empty value
|
||||
\item There are no value parameters in the trait's primary constructor, nor
|
||||
are there secondary constructors.
|
||||
\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.
|
||||
\item All non-empty statements in the template are either imports or pure definitions.
|
||||
\item A trait may not have secondary constructors.
|
||||
\item All non-empty statements in the trait's template are either
|
||||
imports or pure definitions.
|
||||
\end{enumerate}
|
||||
A {\em pure} definition can be evaluated without any side effect.
|
||||
Function, type, class, or object definitions are always pure. A value
|
||||
definition is pure if its right-hand side expression is pure. Pure
|
||||
expressions are paths, literals, and typed expressions
|
||||
$e: T$ where $e$ is pure.
|
||||
definition is pure if its right-hand side expression is pure. A
|
||||
secondary constructor definition is pure if its right-hand side
|
||||
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
|
||||
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 = {
|
||||
if (!TreeInfo.isPureDef(tree) && !tree.getType().isError())
|
||||
error(tree.pos, "" + clazz + " may contain only pure definitions");
|
||||
def checkTraitDef(pos: int, clazz: Symbol, templ: Tree$Template) = {
|
||||
|
||||
/** 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.
|
||||
*/
|
||||
def checkPureConstr(tree: Tree, clazz: Symbol): unit = {
|
||||
def checkPureConstr(tree: Tree): unit = {
|
||||
if (!TreeInfo.isPureConstr(tree) && !tree.getType().isError())
|
||||
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())
|
||||
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
|
||||
*/
|
||||
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) =>
|
||||
var tpe = _tpe;
|
||||
val clazz: Symbol = sym.moduleClass();
|
||||
pushContext(
|
||||
tree, clazz.primaryConstructor(), context.scope);
|
||||
defineTemplate(templ, clazz, new Scope());
|
||||
popContext();
|
||||
clazz.setInfo(templ.getType());
|
||||
tpe = transform(tpe, TYPEmode);
|
||||
(tree.asInstanceOf[Tree$ModuleDef]).tpe = tpe;
|
||||
|
@ -1390,7 +1420,12 @@ class Analyzer(global: scalac_Global, descr: AnalyzerPhase) extends Transformer(
|
|||
(infer.isCompatible(tree.getType(), pt) ||
|
||||
pt.symbol() == definitions.UNIT_CLASS)) {
|
||||
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);
|
||||
}
|
||||
} else if ((mode & (CONSTRmode | FUNmode)) == CONSTRmode) {
|
||||
error(tree.pos, "missing arguments for class constructor");
|
||||
return errorTermTree(tree);
|
||||
|
@ -1584,7 +1619,28 @@ class Analyzer(global: scalac_Global, descr: AnalyzerPhase) extends Transformer(
|
|||
while (nextimports != null && nextimports.tree.pos >= tree.pos) {
|
||||
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);
|
||||
lastimports = nextimports;
|
||||
nextimports = nextimports.prev;
|
||||
|
@ -1842,17 +1898,6 @@ class Analyzer(global: scalac_Global, descr: AnalyzerPhase) extends Transformer(
|
|||
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);
|
||||
templ1.setType(owner.getType());
|
||||
templ1
|
||||
|
@ -2098,14 +2143,19 @@ class Analyzer(global: scalac_Global, descr: AnalyzerPhase) extends Transformer(
|
|||
templ.body, vparams(vparams.length - 1));
|
||||
|
||||
val templ1: Tree$Template = transformTemplate(templ, sym);
|
||||
if (sym.isTrait()) checkTraitDef(tree.pos, sym, templ1);
|
||||
checkNoEscape(tree.pos, sym.info());
|
||||
popContext();
|
||||
copy.ClassDef(tree, sym, tparams1, vparams1, tpe1, templ1)
|
||||
.setType(Type.NoType);
|
||||
|
||||
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);
|
||||
popContext();
|
||||
val templ1: Tree$Template = transformTemplate(templ, sym.moduleClass());
|
||||
if (tpe1 != Tree.Empty && !templ1.getType().isSubType(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);
|
||||
if (!infer.isFullyDefined(restype))
|
||||
restype = body1.getType().deconst();
|
||||
restype = checkNoEscape(tree.pos, restype);
|
||||
popContext();
|
||||
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;
|
||||
while (c != Context.NONE &&
|
||||
!c.tree.isInstanceOf[Tree$ClassDef] &&
|
||||
!c.tree.isInstanceOf[Tree$ModuleDef] &&
|
||||
!c.tree.isInstanceOf[Tree$Template])
|
||||
c = c.outer;
|
||||
enclClassOrConstructorContext = c
|
||||
|
|
|
@ -77,13 +77,16 @@ public class TreeInfo {
|
|||
case Tree.Empty:
|
||||
case ClassDef(_, _, _, _, _, _):
|
||||
case ModuleDef(_, _, _, _):
|
||||
case DefDef(_, _, _, _, _, _):
|
||||
case AbsTypeDef(_, _, _, _):
|
||||
case AliasTypeDef(_, _, _, _):
|
||||
case Import(_, _):
|
||||
return true;
|
||||
case DefDef(_, Name name, _, _, _, _):
|
||||
return name != Names.CONSTRUCTOR;
|
||||
case ValDef(int mods, _, _, Tree rhs):
|
||||
return (mods & Modifiers.MUTABLE) == 0 && isPureExpr(rhs);
|
||||
case DocDef(_, Tree definition):
|
||||
return isPureDef(definition);
|
||||
default:
|
||||
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