summaryrefslogtreecommitdiff
path: root/sources
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2004-05-13 11:02:45 +0000
committerMartin Odersky <odersky@gmail.com>2004-05-13 11:02:45 +0000
commit8837d66ac4d3e487977ce47c8d63fc189e53e763 (patch)
tree74243fa124212554a8b919793b599a1f482b2320 /sources
parentbb2e5cbb9cb285bd3ecd9b387126de2659224190 (diff)
downloadscala-8837d66ac4d3e487977ce47c8d63fc189e53e763.tar.gz
scala-8837d66ac4d3e487977ce47c8d63fc189e53e763.tar.bz2
scala-8837d66ac4d3e487977ce47c8d63fc189e53e763.zip
*** empty log message ***
Diffstat (limited to 'sources')
-rw-r--r--sources/scala/tools/scalac/typechecker/Analyzer.scala33
-rw-r--r--sources/scala/tools/scalac/typechecker/Context.scala3
-rw-r--r--sources/scala/tools/scalac/typechecker/Infer.scala109
-rwxr-xr-xsources/scala/tools/scalac/typechecker/View.scala4
-rw-r--r--sources/scalac/symtab/ClosureHistory.java2
-rw-r--r--sources/scalac/typechecker/Infer.java3
-rw-r--r--sources/scalac/typechecker/RefCheck.java7
7 files changed, 107 insertions, 54 deletions
diff --git a/sources/scala/tools/scalac/typechecker/Analyzer.scala b/sources/scala/tools/scalac/typechecker/Analyzer.scala
index abda9b26e7..bdba70d823 100644
--- a/sources/scala/tools/scalac/typechecker/Analyzer.scala
+++ b/sources/scala/tools/scalac/typechecker/Analyzer.scala
@@ -622,24 +622,6 @@ class Analyzer(global: scalac_Global, descr: AnalyzerPhase) extends Transformer(
} else vapp
}
- private def checkLegalView(pos: int, tparams: Array[Symbol], vparam: Symbol, restype: Type): boolean = {
- var i = 0;
- while (i < tparams.length && tparams(i) != vparam.getType().symbol())
- i = i + 1;
- if (i < tparams.length) {
- val vb = tparams(i).vuBound();
- if (vb != Global.instance.definitions.ANY_TYPE()) {
- val vb1 = vb.subst(tparams, infer.freshVars(tparams));
- if (restype.isSubType(vb1)) {
- error(pos, "view is potentially self-referential since its result type " + restype +
- " is a subtype of its type parameter view bound " + vb1);
- return false;
- }
- }
- }
- true
- }
-
// Contexts -------------------------------------------------------------------
/** Push new context associated with given tree, owner, and scope on stack.
@@ -1173,16 +1155,16 @@ class Analyzer(global: scalac_Global, descr: AnalyzerPhase) extends Transformer(
if (!sym.isFinal()) restype = restype.deconst();
}
restype = checkNoEscape(tpe.pos, restype);
+ if (name == Names.view &&
+ infer.containsSymbol(tparamSyms, restype.symbol())) {
+ error(tree.pos, "result type of view may not be a type variable");
+ restype = definitions.ANY_TYPE();
+ }
popContext();
+
owntype = makeMethodType(tparamSyms, vparamSyms, restype);
//System.out.println("methtype " + name + ":" + owntype);//DEBUG
- if (name == Names.view &&
- infer.isViewBounded(tparamSyms) &&
- vparamSyms.length == 2 && vparamSyms(1).length == 1 &&
- !checkLegalView(tree.pos, tparamSyms, vparamSyms(1)(0), restype))
- owntype = makeMethodType(tparamSyms, vparamSyms, Type.ErrorType);
-
case Tree$ValDef(mods, name, _tpe, _rhs) =>
var tpe = _tpe;
var rhs = _rhs;
@@ -1361,7 +1343,8 @@ class Analyzer(global: scalac_Global, descr: AnalyzerPhase) extends Transformer(
}
case _ =>
}
- if ((pt != null && pt.isStable() || (mode & QUALmode) != 0) && pre.isStable()) {
+ if ((pt != null && pt.isStable() || (mode & QUALmode) != 0) &&
+ (pre != null) && pre.isStable()) {
var sym: Symbol = tree.symbol();
tree.getType() match {
case Type$OverloadedType(alts, alttypes) =>
diff --git a/sources/scala/tools/scalac/typechecker/Context.scala b/sources/scala/tools/scalac/typechecker/Context.scala
index 9bea4b495a..7c5569532f 100644
--- a/sources/scala/tools/scalac/typechecker/Context.scala
+++ b/sources/scala/tools/scalac/typechecker/Context.scala
@@ -82,8 +82,7 @@ class Context {
def isUnShadowed(view: View) =
view.context == this || !infer.specializes(view.symtype, symtype);
*/
- if (viewCache.forall(v => v.sym != sym) &&
- symtype.resultType() != Type.ErrorType) {
+ if (viewCache.forall(v => v.sym != sym)) {
val v = View(sym, symtype, qual, this);
//System.out.println("VIEW " + sym + ":" + symtype + " " + qual);//DEBUG
viewCache = v :: viewCache;//.filter(isUnShadowed);
diff --git a/sources/scala/tools/scalac/typechecker/Infer.scala b/sources/scala/tools/scalac/typechecker/Infer.scala
index 6825aae1e6..36efbc8a69 100644
--- a/sources/scala/tools/scalac/typechecker/Infer.scala
+++ b/sources/scala/tools/scalac/typechecker/Infer.scala
@@ -263,8 +263,9 @@ class Infer(global: scalac_Global, gen: TreeGen, make: TreeFactory) extends scal
val memberViewCache = new HashMap[Symbol, List[View]];
-// private def memberViews(tp: Type): List[View] = List();
-
+ /** Return all views which are members of one of the objects associated
+ * with the base types of `tp'.
+ */
private def memberViews(tp: Type): List[View] = {
val tpsym = tp.widen().symbol();
memberViewCache.get(tpsym) match {
@@ -281,6 +282,9 @@ class Infer(global: scalac_Global, gen: TreeGen, make: TreeFactory) extends scal
}
}
+ /** Return all views which are member of the companion object of
+ * base class `clazz' of type `tp', empty if no companion object exists.
+ */
private def companionObjViews(tp: Type, clazz: Symbol): List[View] = {
if (clazz.kind == CLASS && !clazz.isModuleClass() && !clazz.isCaseClass()) {
var obj = clazz.owner().info().lookupNonPrivate(clazz.name.toTermName());
@@ -304,15 +308,12 @@ class Infer(global: scalac_Global, gen: TreeGen, make: TreeFactory) extends scal
var i = alttypes.length - 1;
var vs: List[View] = List();
while (i >= 0) {
- if (alttypes(i).resultType() != Type.ErrorType)
- vs = View(alts(i), alttypes(i), qual, Context.NONE) :: vs;
+ vs = View(alts(i), alttypes(i), qual, Context.NONE) :: vs;
i = i - 1
}
vs
case viewtype =>
- if (viewtype.resultType() != Type.ErrorType)
- List(View(viewsym, viewtype, qual, Context.NONE))
- else List()
+ List(View(viewsym, viewtype, qual, Context.NONE))
}
} else List()
} else List()
@@ -320,11 +321,34 @@ class Infer(global: scalac_Global, gen: TreeGen, make: TreeFactory) extends scal
} else List()
}
- private def getViews(tp: Type): List[View] = {
+ /** Return all available views for type `tp'
+ */
+ private def availableViews(tp: Type): List[View] = {
//System.out.println("view for " + tp + " = " + (memberViews(tp) ::: getContext.viewMeths));//DEBUG
memberViews(tp) ::: getContext.viewMeths
}
+ def containsSymbol(syms: Array[Symbol], sym: Symbol): boolean = {
+ var i = 0;
+ while (i < syms.length && syms(i) != sym) i = i + 1;
+ i < syms.length
+ }
+
+ def isContractive(tp: Type): boolean = {
+ tp match {
+ case Type$PolyType(tparams, tp1) =>
+ skipViewParams(tparams, tp1) match {
+ case Type$MethodType(vparams, _) =>
+ vparams.length != 1 ||
+ !containsSymbol(tparams, vparams(0).getType().symbol())
+ case _ => true
+ }
+ case _ => true
+ }
+ }
+
+ /** Construct a tree referring to the view method in `v' at position `pos'.
+ */
def viewExpr(pos: int, v: View): Tree = {
val viewType = checkAccessible(
pos, v.sym, v.symtype, v.qual, v.qual.getType());
@@ -340,7 +364,9 @@ class Infer(global: scalac_Global, gen: TreeGen, make: TreeFactory) extends scal
}
}
- private def viewObj(meth: Tree) = meth.getType() match {
+ /** Construct a function value tree from method reference `meth'.
+ */
+ private def viewObj(meth: Tree): Tree = meth.getType() match {
case Type$MethodType(params: Array[Symbol], _) =>
assert(params.length == 1);
val paramsym = params(0).cloneSymbol(getContext.owner);
@@ -354,6 +380,11 @@ class Infer(global: scalac_Global, gen: TreeGen, make: TreeFactory) extends scal
meth
}
+ /** Construct an implicit view argument for a formal type parameter
+ * with type `vtype'. `targs' is the vector of type arguments
+ * in the current application for which a view argument is needed.
+ * This is needed for error diagnostics only.
+ */
private def viewArg(pos: int, vtype: Type, targs: Array[Type]): Tree = {
val vargs = vtype.typeArgs();
if (vargs(0).isSubType(vargs(1))) {
@@ -361,17 +392,26 @@ class Infer(global: scalac_Global, gen: TreeGen, make: TreeFactory) extends scal
} else {
val v = bestView(vargs(0), vargs(1), Names.EMPTY);
if (v != null) {
- var vmeth = viewExpr(pos, v);
- vmeth.getType() match {
- case Type$PolyType(vtparams, vrestype) =>
- assert(vtparams.length != 0);
- vmeth = exprInstance(vmeth, vtparams, vrestype, vtype);
- case _ =>
+ if (v.locked) {
+ error(pos, "recursive view instantiation of non-contractive " +
+ v.sym + v.sym.locationString() + " with type " +
+ v.sym.getType());
+ gen.mkDefaultValue(pos, vtype)
+ } else {
+ v.locked = !isContractive(v.symtype);
+ var vmeth = viewExpr(pos, v);
+ vmeth.getType() match {
+ case Type$PolyType(vtparams, vrestype) =>
+ assert(vtparams.length != 0);
+ vmeth = exprInstance(vmeth, vtparams, vrestype, vtype);
+ case _ =>
+ }
+ val vobj = viewObj(vmeth);
+ if (!vobj.getType().isSubType(vtype))
+ assert(false, "view argument " + vobj + ":" + vobj.getType() + " is not a subtype of view param type " + vtype);
+ v.locked = false;
+ vobj
}
- val vobj = viewObj(vmeth);
- if (!vobj.getType().isSubType(vtype))
- assert(false, "view argument " + vobj + ":" + vobj.getType() + " is not a subtype of view param type " + vtype);
- vobj
} else {
error(pos,
"type instantiation with [" +
@@ -382,6 +422,14 @@ class Infer(global: scalac_Global, gen: TreeGen, make: TreeFactory) extends scal
}
}
+ /** Augment type application tree with implicit view arguments.
+ * @param tree The type application
+ * @param tparams The formal parameters of the application.
+ * @param restype The result type of the type application (which
+ * must be a method type containing the view parameters,
+ * unless it is an error type.
+ * @param targs The actual type arguments.
+ */
private def passViewArgs(tree: Tree, tparams: Array[Symbol], restype: Type,
targs: Array[Type]): Tree =
restype match {
@@ -398,6 +446,8 @@ class Infer(global: scalac_Global, gen: TreeGen, make: TreeFactory) extends scal
tree
}
+ /** Do type parameters `tparams' contain a view bounded parameter?
+ */
def isViewBounded(tparams: Array[Symbol]) = {
var viewbounded = false;
var j = 0; while (j < tparams.length) {
@@ -407,6 +457,9 @@ class Infer(global: scalac_Global, gen: TreeGen, make: TreeFactory) extends scal
viewbounded
}
+ /** Skip view parameters in type `tp' in the case where `tparams' contains
+ * a view bound.
+ */
def skipViewParams(tparams: Array[Symbol], tp: Type): Type = tp match {
case Type$MethodType(_, restp) if isViewBounded(tparams) =>
restp
@@ -414,6 +467,9 @@ class Infer(global: scalac_Global, gen: TreeGen, make: TreeFactory) extends scal
tp
}
+ /** If tree is a type application, pass implicit view arguments where
+ * necessary.
+ */
def completeTypeApply(tree: Tree): Tree = {
//System.out.println("complete type apply: " + tree + ":" + tree.getType());//DEBUG
tree match {
@@ -742,7 +798,7 @@ class Infer(global: scalac_Global, gen: TreeGen, make: TreeFactory) extends scal
if (tp1.isSubType(pt)) true
else if (regularValue) {
val argtypes = NewArray.Type(tp1);
- var viewMeths = getViews(tp1);
+ var viewMeths = availableViews(tp1);
while (!viewMeths.isEmpty &&
!isApplicable(viewMeths.head.symtype, argtypes, pt, Names.EMPTY, false))
viewMeths = viewMeths.tail;
@@ -1167,8 +1223,13 @@ class Infer(global: scalac_Global, gen: TreeGen, make: TreeFactory) extends scal
def specializes(ftpe1: Type, ftpe2: Type): boolean = ftpe1 match {
case Type$MethodType(params, _) =>
isApplicable(ftpe2, Symbol.getType(params), Type.AnyType)
- case Type$PolyType(_, Type$MethodType(params, _)) =>
- isApplicable(ftpe2, Symbol.getType(params), Type.AnyType);
+ case Type$PolyType(tparams, restype) =>
+ skipViewParams(tparams, restype) match {
+ case Type$MethodType(params, _) =>
+ isApplicable(ftpe2, Symbol.getType(params), Type.AnyType);
+ case _ =>
+ false
+ }
case _ =>
false
}
@@ -1301,7 +1362,7 @@ class Infer(global: scalac_Global, gen: TreeGen, make: TreeFactory) extends scal
*/
def bestView(tp: Type, pt: Type, name: Name): View = {
var best: View = null;
- var viewMeths = getViews(tp);
+ var viewMeths = availableViews(tp);
//System.out.println("best view for " + tp + "/" + pt + "/" + name + " in " + viewMeths);//DEBUG
val argtypes = NewArray.Type(tp);
while (!viewMeths.isEmpty) {
@@ -1311,7 +1372,7 @@ class Infer(global: scalac_Global, gen: TreeGen, make: TreeFactory) extends scal
viewMeths = viewMeths.tail
}
if (best != null) {
- viewMeths = getViews(tp);
+ viewMeths = availableViews(tp);
while (!viewMeths.isEmpty) {
if (viewMeths.head != best &&
isApplicable(viewMeths.head.symtype, argtypes, pt, name, false) &&
diff --git a/sources/scala/tools/scalac/typechecker/View.scala b/sources/scala/tools/scalac/typechecker/View.scala
index ae736c7bc9..a3b64636d5 100755
--- a/sources/scala/tools/scalac/typechecker/View.scala
+++ b/sources/scala/tools/scalac/typechecker/View.scala
@@ -10,6 +10,8 @@ import scalac.ast._;
package scala.tools.scalac.typechecker {
-case class View(sym: Symbol, symtype: Type, qual: Tree, context: Context);
+case class View(sym: Symbol, symtype: Type, qual: Tree, context: Context) {
+ var locked = false;
+}
}
diff --git a/sources/scalac/symtab/ClosureHistory.java b/sources/scalac/symtab/ClosureHistory.java
index c17ad46f90..514e093f29 100644
--- a/sources/scalac/symtab/ClosureHistory.java
+++ b/sources/scalac/symtab/ClosureHistory.java
@@ -54,7 +54,7 @@ public class ClosureHistory extends History {
/** Adds all parents of given type to given parent table. */
private static void addParents(TreeMap/*<Symbol,Type>*/ table, Type type) {
switch (type) {
- case ErrorType:
+ case ErrorType: case NoType:
return;
case TypeRef(_, Symbol symbol, _):
Type.Map map = Type.getThisTypeMap(symbol, type);
diff --git a/sources/scalac/typechecker/Infer.java b/sources/scalac/typechecker/Infer.java
index 8ccca5d586..528ca7b47d 100644
--- a/sources/scalac/typechecker/Infer.java
+++ b/sources/scalac/typechecker/Infer.java
@@ -17,4 +17,7 @@ public abstract class Infer {
*/
public abstract void checkBounds(Symbol[] tparams, Type[] targs, String prefix);
+
+ public abstract Type skipViewParams(Symbol[] tparams, Type tp);
+
}
diff --git a/sources/scalac/typechecker/RefCheck.java b/sources/scalac/typechecker/RefCheck.java
index f65485a33a..a96a21fd0a 100644
--- a/sources/scalac/typechecker/RefCheck.java
+++ b/sources/scalac/typechecker/RefCheck.java
@@ -648,7 +648,12 @@ public class RefCheck extends Transformer implements Modifiers, Kinds {
}
private Tree[] caseFields(ClassSymbol clazz) {
- Symbol[] vparams = clazz.primaryConstructor().type().firstParams();
+ Type ct = clazz.primaryConstructor().type();
+ switch (ct) {
+ case Type.PolyType(Symbol[] tparams, Type restp):
+ ct = infer.skipViewParams(tparams, restp);
+ }
+ Symbol[] vparams = ct.firstParams();
Tree[] fields = new Tree[vparams.length];
for (int i = 0; i < fields.length; i++) {
fields[i] = gen.mkRef(clazz.pos, clazz.thisType(), clazz.caseFieldAccessor(i));