summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2003-04-03 09:20:53 +0000
committerMartin Odersky <odersky@gmail.com>2003-04-03 09:20:53 +0000
commit6ffa9f1636201a142e794554ce27b5276cd846b3 (patch)
treef531c78982561fc1e7e5a08252a47637d8477f38
parente360fb4095273a5bbcddb2757c576cc457614391 (diff)
downloadscala-6ffa9f1636201a142e794554ce27b5276cd846b3.tar.gz
scala-6ffa9f1636201a142e794554ce27b5276cd846b3.tar.bz2
scala-6ffa9f1636201a142e794554ce27b5276cd846b3.zip
*** empty log message ***
-rw-r--r--sources/scalac/typechecker/Analyzer.java5
-rw-r--r--sources/scalac/typechecker/Infer.java36
-rw-r--r--test/files/neg/abstract.check7
-rw-r--r--test/files/neg/abstract.scala9
-rw-r--r--test/files/neg/michel2.check4
-rw-r--r--test/files/neg/michel2.scala1
-rw-r--r--test/neg/abstract.check7
-rw-r--r--test/neg/abstract.scala9
-rw-r--r--test/neg/michel2.check4
-rw-r--r--test/neg/michel2.scala1
10 files changed, 71 insertions, 12 deletions
diff --git a/sources/scalac/typechecker/Analyzer.java b/sources/scalac/typechecker/Analyzer.java
index b0a0d58798..d5cda31ee1 100644
--- a/sources/scalac/typechecker/Analyzer.java
+++ b/sources/scalac/typechecker/Analyzer.java
@@ -1452,7 +1452,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
// if method is polymorphic,
// infer instance, and adapt arguments to instantiated formals
try {
- fn1 = infer.methodInstance(fn1, tparams, restp, argtypes);
+ fn1 = infer.methodInstance(fn1, tparams, restp, argtypes, pt);
} catch (Type.Error ex) {
error(tree.pos, ex.msg);
}
@@ -1619,9 +1619,6 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
tree = error(tree.pos, ex.msg);
}
return adapt(tree, mode, pt);
-// } else if ((mode & EXPRmode) != 0) {
-// // will be instantiated later
-// return tree;
}
break;
diff --git a/sources/scalac/typechecker/Infer.java b/sources/scalac/typechecker/Infer.java
index fcbc88cd64..d0ccddb56d 100644
--- a/sources/scalac/typechecker/Infer.java
+++ b/sources/scalac/typechecker/Infer.java
@@ -510,14 +510,16 @@ public class Infer implements Modifiers, Kinds {
}
}
- /** Return inferred type arguments, given type parameters, formal parameters and
- * argument types.
+ /** Return inferred type arguments, given type parameters, formal parameters,
+ * argument types, result type and expected result type.
* If this is not possible, throw a `NoInstance' exception, or, if
* `needToSucceed' is false alternatively return `null'.
* Undetermined type arguments are represented by `NoType'.
* No check that inferred parameters conform to their bounds is made here.
*/
- private Type[] methTypeArgs(Symbol[] tparams, Symbol[] params, Type[] argtypes,
+ private Type[] methTypeArgs(Symbol[] tparams,
+ Symbol[] params, Type[] argtypes,
+ Type restp, Type pt,
boolean needToSucceed) throws NoInstance {
//System.out.println("methTypeArgs, tparams = " + ArrayApply.toString(tparams) + ", params = " + ArrayApply.toString(params) + ", type(params) = " + ArrayApply.toString(Symbol.type(params)) + ", argtypes = " + ArrayApply.toString(argtypes));//DEBUG
@@ -528,6 +530,21 @@ public class Infer implements Modifiers, Kinds {
throw new NoInstance("parameter lists differ in length");
return null;
}
+
+ // check first whether type variables can be fully defined from
+ // expected result type.
+ if (!isCompatible(restp.subst(tparams, tvars), pt)) {
+ if (needToSucceed)
+ throw new NoInstance("result type " + restp +
+ " is incompatible with expected type " + pt);
+ return null;
+ }
+ for (int i = 0; i < tvars.length; i++) {
+ Type.TypeVar tvar = (Type.TypeVar) tvars[i];
+ if (!isFullyDefined(tvar)) tvar.constr.inst = Type.NoType;
+ }
+
+ // Then define remaining type variables from argument types.
for (int i = 0; i < argtypes.length; i++) {
if (!isCompatible(argtypes[i].subst(tparams, tvars),
formals[i].subst(tparams, tvars))) {
@@ -636,29 +653,32 @@ public class Infer implements Modifiers, Kinds {
/** Instantiate method `tree' of polymorphic type with given `tparams' and
* `restype', so that resulting method type can be applied to
- * arguments with types `argtypes'.
+ * arguments with types `argtypes' and its result type is compatible with `pt'.
*/
public Tree methodInstance(Tree tree,
- Symbol[] tparams, Type restype, Type[] argtypes)
+ Symbol[] tparams, Type restype, Type[] argtypes, Type pt)
throws Type.Error {
switch (restype) {
case PolyType(Symbol[] tparams1, Type restype1):
Symbol[] tparams2 = new Symbol[tparams.length + tparams1.length];
System.arraycopy(tparams, 0, tparams2, 0, tparams.length);
System.arraycopy(tparams1, 0, tparams2, tparams.length, tparams1.length);
- return methodInstance(tree, tparams2, restype1, argtypes);
+ return methodInstance(tree, tparams2, restype1, argtypes, pt);
case MethodType(Symbol[] params, Type restpe):
Type[] argtypes1 = Type.widen(argtypes);
Type[] targs;
try {
- targs = methTypeArgs(tparams, params, argtypes1, true);
+ targs = methTypeArgs(tparams, params, argtypes1, restpe, pt, true);
} catch (NoInstance ex) {
+ throw ex;
+/*
throw new Type.Error(
applyErrorMsg(
"no type parameters for ", tree,
" exist so that it can be applied to arguments ",
argtypes1, Type.AnyType) +
"\n --- because ---\n" + ex.getMessage());
+*/
}
Symbol[] uninstantiated = normalizeArgs(targs, tparams);
checkBounds(tparams, targs, "inferred ");
@@ -730,7 +750,7 @@ public class Infer implements Modifiers, Kinds {
case PolyType(Symbol[] tparams, MethodType(Symbol[] params, Type restpe)):
try {
Type[] targs = methTypeArgs(
- tparams, params, Type.widen(argtypes), false);
+ tparams, params, Type.widen(argtypes), restpe, pt, false);
if (targs != null) {
Symbol[] uninstantiated = normalizeArgs(targs, tparams);
return
diff --git a/test/files/neg/abstract.check b/test/files/neg/abstract.check
new file mode 100644
index 0000000000..11d01ce3d9
--- /dev/null
+++ b/test/files/neg/abstract.check
@@ -0,0 +1,7 @@
+abstract.scala:5: malformed type: A.this.T#T
+ def foo1 = bar().bar();
+ ^
+abstract.scala:7: malformed type: A#T
+ def foo3 = baz().bar();
+ ^
+two errors found
diff --git a/test/files/neg/abstract.scala b/test/files/neg/abstract.scala
new file mode 100644
index 0000000000..41cfc81309
--- /dev/null
+++ b/test/files/neg/abstract.scala
@@ -0,0 +1,9 @@
+trait A {
+ type T <: A;
+ def baz(): A;
+ def bar(): T;
+ def foo1 = bar().bar();
+ def foo2 = bar().baz();
+ def foo3 = baz().bar();
+ def foo4 = baz().baz();
+}
diff --git a/test/files/neg/michel2.check b/test/files/neg/michel2.check
new file mode 100644
index 0000000000..3317c40f61
--- /dev/null
+++ b/test/files/neg/michel2.check
@@ -0,0 +1,4 @@
+michel2.scala:1: Java class may not be used as mixin
+class A() extends java.lang.Object() with java.util.Random() { }
+ ^
+one error found
diff --git a/test/files/neg/michel2.scala b/test/files/neg/michel2.scala
new file mode 100644
index 0000000000..4afbb30852
--- /dev/null
+++ b/test/files/neg/michel2.scala
@@ -0,0 +1 @@
+class A() extends java.lang.Object() with java.util.Random() { }
diff --git a/test/neg/abstract.check b/test/neg/abstract.check
new file mode 100644
index 0000000000..11d01ce3d9
--- /dev/null
+++ b/test/neg/abstract.check
@@ -0,0 +1,7 @@
+abstract.scala:5: malformed type: A.this.T#T
+ def foo1 = bar().bar();
+ ^
+abstract.scala:7: malformed type: A#T
+ def foo3 = baz().bar();
+ ^
+two errors found
diff --git a/test/neg/abstract.scala b/test/neg/abstract.scala
new file mode 100644
index 0000000000..41cfc81309
--- /dev/null
+++ b/test/neg/abstract.scala
@@ -0,0 +1,9 @@
+trait A {
+ type T <: A;
+ def baz(): A;
+ def bar(): T;
+ def foo1 = bar().bar();
+ def foo2 = bar().baz();
+ def foo3 = baz().bar();
+ def foo4 = baz().baz();
+}
diff --git a/test/neg/michel2.check b/test/neg/michel2.check
new file mode 100644
index 0000000000..3317c40f61
--- /dev/null
+++ b/test/neg/michel2.check
@@ -0,0 +1,4 @@
+michel2.scala:1: Java class may not be used as mixin
+class A() extends java.lang.Object() with java.util.Random() { }
+ ^
+one error found
diff --git a/test/neg/michel2.scala b/test/neg/michel2.scala
new file mode 100644
index 0000000000..4afbb30852
--- /dev/null
+++ b/test/neg/michel2.scala
@@ -0,0 +1 @@
+class A() extends java.lang.Object() with java.util.Random() { }