*** empty log message ***
git-svn-id: http://lampsvn.epfl.ch/svn-repos/scala/scala/trunk@2378 5e8d7ff9-d8ef-0310-90f0-a4852d11357a
This commit is contained in:
parent
c854155ea6
commit
46a7577aaa
|
@ -304,7 +304,7 @@ referenced entity in $T$.
|
|||
Type ::= Type1 `=>' Type
|
||||
| `(' [Types] `)' `=>' Type
|
||||
| Type1
|
||||
Type1 ::= SimpleType {with SimpleType}
|
||||
Type1 ::= SimpleType {with SimpleType} [Refinement]
|
||||
SimpleType ::= StableId
|
||||
| SimpleType `#' id
|
||||
| Path `.' type
|
||||
|
@ -318,12 +318,14 @@ take type parameters and yield types. A subset of first-order types
|
|||
called {\em value types} represents sets of (first-class) values.
|
||||
Value types are either {\em concrete} or {\em abstract}. Every
|
||||
concrete value type can be represented as a {\em class type}, i.e.\ a
|
||||
type designator (\sref{sec:type-desig}) that refers to a
|
||||
class\footnote{We assume that objects and packages also implicitly
|
||||
define a class (of the same name as the object or package, but
|
||||
inaccessible to user programs).} (\sref{sec:classes}), or as a {\em
|
||||
compound type} (\sref{sec:compound-types}) of class types.
|
||||
\todo{verify whether operands need to be class types}
|
||||
type designator (\sref{sec:type-desig}) that refers to a
|
||||
class\footnote{We assume that objects and packages also
|
||||
implicitly define a class (of the same name as the object or package,
|
||||
but inaccessible to user programs).} (\sref{sec:classes}),
|
||||
or as a {\em compound type} (\sref{sec:compound-types})
|
||||
consisting of class types and possibly
|
||||
also a refinement (\sref{sec:refinements}) that further constrains the
|
||||
types of its members.
|
||||
|
||||
A shorthand exists for denoting function types
|
||||
(\sref{sec:function-types}). Abstract value types are introduced by
|
||||
|
@ -472,14 +474,25 @@ the following types are ill-formed:
|
|||
\label{sec:compound-types}
|
||||
|
||||
\syntax\begin{lstlisting}
|
||||
Type ::= SimpleType {with SimpleType}
|
||||
Type ::= SimpleType {with SimpleType} [Refinement]
|
||||
Refinement ::= `{' [RefineStat {`;' RefineStat}] `}'
|
||||
RefineStat ::= Dcl
|
||||
| type TypeDef {`,' TypeDef}
|
||||
|
|
||||
\end{lstlisting}
|
||||
|
||||
A compound type ~\lstinline@$T_1$ with $\ldots$ with $T_n$ {$R\,$}@~
|
||||
represents objects with members as given in the component types $T_1
|
||||
\commadots T_n$. Each component type $T_i$ must be a class type and
|
||||
the base class sequence generated by types $T_1 \commadots T_n$ must
|
||||
be well-formed (\sref{sec:basetypes-wf}).
|
||||
A compound type ~\lstinline@$T_1$ with $\ldots$ with $T_n$ {$R\,$}@~ represents
|
||||
objects with members as given in the component types $T_1 \commadots
|
||||
T_n$ and the refinement \lstinline@{$R\,$}@. Each component type $T_i$ must be a
|
||||
class type and the base class sequence generated by types $T_1
|
||||
\commadots T_n$ must be well-formed (\sref{sec:basetypes-wf}). A
|
||||
refinement \lstinline@{$R\,$}@ contains declarations and type
|
||||
definitions. Each declaration or definition in a refinement must
|
||||
override a declaration or definition in one of the component types
|
||||
$T_1 \commadots T_n$. The usual rules for overriding (\sref{})
|
||||
apply. If no refinement is given, the empty refinement is implicitly
|
||||
added, i.e. ~\lstinline@$T_1$ with $\ldots$ with $T_n$@~ is a shorthand for
|
||||
~\lstinline@$T_1$ with $\ldots$ with $T_n$ {}@.
|
||||
|
||||
\subsection{Function Types}
|
||||
\label{sec:function-types}
|
||||
|
@ -745,7 +758,10 @@ consisting only of package or object selectors and ending in $O$, then
|
|||
~\lstinline@$O$.this.type $\equiv p$.type@.
|
||||
\item
|
||||
Two compound types are equivalent if their component types are
|
||||
pairwise equivalent.
|
||||
pairwise equivalent and their refinements are equivalent. Two
|
||||
refinements are equivalent if they bind the same names and the
|
||||
modifiers, types and bounds of every declared entity are equivalent in
|
||||
both refinements.
|
||||
\item
|
||||
Two method types are equivalent if they have equivalent result
|
||||
types, both have the same number of parameters, and corresponding
|
||||
|
@ -922,8 +938,9 @@ the expression is typed and evaluated is if it was
|
|||
\end{lstlisting}
|
||||
|
||||
A {\em declaration} introduces names and assigns them types. It can
|
||||
only appear as one of the statements of a class definition
|
||||
(\sref{sec:templates}).
|
||||
appear as one of the statements of a class definition
|
||||
(\sref{sec:templates}) or as part of a refinement in a compound
|
||||
type (\sref{sec:refinements}).
|
||||
|
||||
A {\em definition} introduces names that denote terms or types. It can
|
||||
form part of an object or class definition or it can be local to a
|
||||
|
@ -2703,7 +2720,13 @@ 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$@.
|
||||
\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.
|
||||
|
@ -3375,7 +3398,7 @@ Concretely, we distinguish the following kinds of patterns.
|
|||
A {\em wild-card pattern} \_ matches any value.
|
||||
|
||||
A {\em typed pattern} $\_: T$ matches values of type $T$. The type $T$ may be
|
||||
a class type or a compound type.
|
||||
a class type or a compound type; it may not contain a refinement (\sref{sec:refinements}).
|
||||
This pattern matches any non-null value of type $T$. $T$ must conform to the pattern's expected
|
||||
type. A pattern $x:T$ is treated the same way as $x @ (_:T)$
|
||||
|
||||
|
@ -4238,7 +4261,7 @@ grammar.
|
|||
Type ::= Type1 `=>' Type
|
||||
| `(' [Types] `)' `=>' Type
|
||||
| Type1
|
||||
Type1 ::= SimpleType {with SimpleType}
|
||||
Type1 ::= SimpleType {with SimpleType} [Refinement]
|
||||
SimpleType ::= SimpleType TypeArgs
|
||||
| SimpleType `#' id
|
||||
| StableId
|
||||
|
@ -4246,6 +4269,10 @@ grammar.
|
|||
| `(' Type ')'
|
||||
TypeArgs ::= `[' Types `]'
|
||||
Types ::= Type {`,' Type}
|
||||
Refinement ::= `{' [RefineStat {`;' RefineStat}] `}'
|
||||
RefineStat ::= Dcl
|
||||
| type TypeDef {`,' TypeDef}
|
||||
|
|
||||
|
||||
Exprs ::= Expr {`,' Expr}
|
||||
Expr ::= Bindings `=>' Expr
|
||||
|
|
|
@ -690,7 +690,7 @@ class Parser(unit: Unit) {
|
|||
s.nextToken();
|
||||
ts.append(simpleType());
|
||||
}
|
||||
val rs = /*if (s.token == LBRACE) refinement() else*/ Tree.EMPTY_ARRAY;
|
||||
val rs = if (s.token == LBRACE) refinement() else Tree.EMPTY_ARRAY;
|
||||
make.CompoundType(pos, ts.toArray(), rs)
|
||||
} else {
|
||||
t
|
||||
|
|
|
@ -2283,7 +2283,6 @@ class Analyzer(global: scalac_Global, descr: AnalyzerPhase) extends Transformer(
|
|||
val parentTypes = clazz.info().parents();
|
||||
val refinement: Scope = new Scope();
|
||||
val base: Type = Type.compoundTypeWithOwner(context.enclClass.owner, parentTypes, Scope.EMPTY);
|
||||
/*
|
||||
val it: Scope$SymbolIterator = clazz.members().iterator();
|
||||
while (it.hasNext()) {
|
||||
val sym1: Symbol = it.next();
|
||||
|
@ -2293,7 +2292,6 @@ class Analyzer(global: scalac_Global, descr: AnalyzerPhase) extends Transformer(
|
|||
.isSameAs(sym1.getType()))
|
||||
refinement.enter(sym1);
|
||||
}
|
||||
*/
|
||||
val owntype =
|
||||
if (refinement.isEmpty() && parentTypes.length == 1)
|
||||
parentTypes(0)
|
||||
|
@ -2764,16 +2762,23 @@ class Analyzer(global: scalac_Global, descr: AnalyzerPhase) extends Transformer(
|
|||
|
||||
case Tree$CompoundType(parents, refinements) =>
|
||||
val parents1 = transform(parents, TYPEmode);
|
||||
val ptypes = Tree.typeOf(parents);
|
||||
val ptypes = new Array[Type](parents1.length);
|
||||
{ var i = 0; while (i < parents1.length) {
|
||||
val tp = parents(i).getType();
|
||||
if (i > 0 || tp.unalias().symbol().kind != TYPE)
|
||||
checkClassType(parents(i).pos, tp);
|
||||
ptypes(i) = tp;
|
||||
i = i + 1
|
||||
}}
|
||||
val members: Scope = new Scope();
|
||||
val self: Type = Type.compoundTypeWithOwner(context.enclClass.owner, ptypes, members);
|
||||
val clazz: Symbol = self.symbol();
|
||||
pushContext(tree, clazz, members);
|
||||
var i = 0; while (i < refinements.length) {
|
||||
{ var i = 0; while (i < refinements.length) {
|
||||
val m = enterSym(refinements(i));
|
||||
m.flags = m.flags | OVERRIDE;
|
||||
i = i + 1
|
||||
}
|
||||
}}
|
||||
val refinements1 = transformStatSeq(refinements, Symbol.NONE);
|
||||
popContext();
|
||||
copy.CompoundType(tree, parents1, refinements1)
|
||||
|
|
|
@ -1658,6 +1658,11 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
|
|||
case ThisType(Symbol sym):
|
||||
if (sym == from) return to;
|
||||
else return t;
|
||||
case TypeRef(Type pre, Symbol sym, Type[] args):
|
||||
Type pre1 = apply(pre);
|
||||
Type[] args1 = map(args);
|
||||
if (pre1 == pre && args1 == args) return t;
|
||||
else return typeRef(pre1, pre1.rebind(sym), args1);
|
||||
default:
|
||||
return map(t);
|
||||
}
|
||||
|
@ -2579,9 +2584,36 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
|
|||
}
|
||||
}
|
||||
|
||||
static int recCount = 0;
|
||||
static boolean giveUp = false;
|
||||
static int recLimit = 10;
|
||||
|
||||
public static Type lub(Type[] tps) {
|
||||
if (recCount == recLimit) {
|
||||
giveUp = true;
|
||||
return Global.instance.definitions.ANY_TYPE();
|
||||
} else {
|
||||
recCount++;
|
||||
Type result = lub0(tps);
|
||||
recCount--;
|
||||
if (recCount == 0) {
|
||||
if (giveUp) {
|
||||
giveUp = false;
|
||||
throw new Error("failure to compute least upper bound of types " +
|
||||
ArrayApply.toString(tps, "", " and ", ";\n") +
|
||||
"an approximation is: " + result + ";\n" +
|
||||
"additional type annotations are needed");
|
||||
} else {
|
||||
giveUp = false;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/** Return the least upper bound of non-empty array of types `tps'.
|
||||
*/
|
||||
public static Type lub(Type[] tps) {
|
||||
public static Type lub0(Type[] tps) {
|
||||
//System.out.println("lub" + ArrayApply.toString(tps));//DEBUG
|
||||
|
||||
if (tps.length == 0) return Global.instance.definitions.ALL_TYPE();
|
||||
|
@ -2754,6 +2786,29 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
|
|||
}
|
||||
|
||||
public static Type glb(Type[] tps) {
|
||||
if (recCount == recLimit) {
|
||||
giveUp = true;
|
||||
return Global.instance.definitions.ALL_TYPE();
|
||||
} else {
|
||||
recCount++;
|
||||
Type result = glb0(tps);
|
||||
recCount--;
|
||||
if (recCount == 0) {
|
||||
if (giveUp) {
|
||||
giveUp = false;
|
||||
throw new Error("failure to compute greatest lower bound of types " +
|
||||
ArrayApply.toString(tps, "", " and ", ";\n") +
|
||||
"an approximation is: " + result + ";\n" +
|
||||
"additional type annotations are needed");
|
||||
} else {
|
||||
giveUp = false;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public static Type glb0(Type[] tps) {
|
||||
if (tps.length == 0) return Global.instance.definitions.ANY_TYPE();
|
||||
|
||||
// step one: eliminate redunandant types; return if one one is left
|
||||
|
@ -2769,10 +2824,8 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
|
|||
treftl = new Type.List(tps[i], treftl);
|
||||
break;
|
||||
case CompoundType(Type[] parents, Scope members):
|
||||
/*
|
||||
if (!members.isEmpty())
|
||||
comptl = new Type.List(tps[i], comptl);
|
||||
*/
|
||||
for (int j = 0; j < parents.length; j++)
|
||||
treftl = new Type.List(parents[j], treftl);
|
||||
break;
|
||||
|
@ -2787,7 +2840,7 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
|
|||
Type glbThisType = glbType.narrow();
|
||||
|
||||
// step 3: compute glb of all refinements.
|
||||
/*
|
||||
Scope members = Scope.EMPTY;
|
||||
if (comptl != List.EMPTY) {
|
||||
Type[] comptypes = comptl.toArrayReverse();
|
||||
Scope[] refinements = new Scope[comptypes.length];
|
||||
|
@ -2801,7 +2854,6 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
|
|||
Global.instance.definitions.ALLREF_TYPE(), treftl);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// eliminate redudant typerefs
|
||||
Type[] treftypes = elimRedundant(treftl.toArrayReverse(), false);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
bug44.scala:2: type mismatch;
|
||||
found : scala.Object
|
||||
required: scala.Object { def t: scala.Int }
|
||||
found : java.lang.Object
|
||||
required: java.lang.Object { def t: scala.Int }
|
||||
var x: Object { def t: Int; } = new Object() {
|
||||
^
|
||||
one error found
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
refine.scala:3: type mismatch;
|
||||
found : scala.Object
|
||||
required: scala.Object { def t(): java.lang.String }
|
||||
found : java.lang.Object
|
||||
required: java.lang.Object { def t(): java.lang.String }
|
||||
val x: Object { def t(): String } = new Object {
|
||||
^
|
||||
one error found
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
vincent1.scala:7: type x.type escapes its defining scope as part of scala.Object { type T = x.T }
|
||||
vincent1.scala:7: type x.type escapes its defining scope as part of java.lang.Object with scala.ScalaObject { type T = x.T }
|
||||
class Functor(x: A) { type T = x.T }
|
||||
^
|
||||
vincent1.scala:9: type x.type escapes its defining scope as part of test.B { type T = x.T }
|
||||
|
|
|
@ -2,7 +2,7 @@ package test;
|
|||
|
||||
import scala.concurrent._;
|
||||
|
||||
class MailBox with Monitor {
|
||||
class MailBox {
|
||||
private class LinkedList[a] {
|
||||
var elem: a = _;
|
||||
var next: LinkedList[a] = null;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
bug44.scala:2: type mismatch;
|
||||
found : scala.Object
|
||||
required: scala.Object { def t: scala.Int }
|
||||
found : java.lang.Object
|
||||
required: java.lang.Object { def t: scala.Int }
|
||||
var x: Object { def t: Int; } = new Object() {
|
||||
^
|
||||
one error found
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
refine.scala:3: type mismatch;
|
||||
found : scala.Object
|
||||
required: scala.Object { def t(): java.lang.String }
|
||||
found : java.lang.Object
|
||||
required: java.lang.Object { def t(): java.lang.String }
|
||||
val x: Object { def t(): String } = new Object {
|
||||
^
|
||||
one error found
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
vincent1.scala:7: type x.type escapes its defining scope as part of scala.Object { type T = x.T }
|
||||
vincent1.scala:7: type x.type escapes its defining scope as part of java.lang.Object with scala.ScalaObject { type T = x.T }
|
||||
class Functor(x: A) { type T = x.T }
|
||||
^
|
||||
vincent1.scala:9: type x.type escapes its defining scope as part of test.B { type T = x.T }
|
||||
|
|
|
@ -2,7 +2,7 @@ package test;
|
|||
|
||||
import scala.concurrent._;
|
||||
|
||||
class MailBox with Monitor {
|
||||
class MailBox {
|
||||
private class LinkedList[a] {
|
||||
var elem: a = _;
|
||||
var next: LinkedList[a] = null;
|
||||
|
|
Loading…
Reference in New Issue