From 6ffa9f1636201a142e794554ce27b5276cd846b3 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 3 Apr 2003 09:20:53 +0000 Subject: *** empty log message *** --- sources/scalac/typechecker/Analyzer.java | 5 +---- sources/scalac/typechecker/Infer.java | 36 +++++++++++++++++++++++++------- test/files/neg/abstract.check | 7 +++++++ test/files/neg/abstract.scala | 9 ++++++++ test/files/neg/michel2.check | 4 ++++ test/files/neg/michel2.scala | 1 + test/neg/abstract.check | 7 +++++++ test/neg/abstract.scala | 9 ++++++++ test/neg/michel2.check | 4 ++++ test/neg/michel2.scala | 1 + 10 files changed, 71 insertions(+), 12 deletions(-) create mode 100644 test/files/neg/abstract.check create mode 100644 test/files/neg/abstract.scala create mode 100644 test/files/neg/michel2.check create mode 100644 test/files/neg/michel2.scala create mode 100644 test/neg/abstract.check create mode 100644 test/neg/abstract.scala create mode 100644 test/neg/michel2.check create mode 100644 test/neg/michel2.scala 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() { } -- cgit v1.2.3