*** 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:
odersky 2004-01-15 16:17:59 +00:00
parent c854155ea6
commit 46a7577aaa
12 changed files with 126 additions and 42 deletions

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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 }

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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 }

View File

@ -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;