diff options
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Namers.scala | 20 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/RefChecks.scala | 6 | ||||
-rwxr-xr-x | test/files/pos/bug1292.scala | 33 | ||||
-rw-r--r-- | test/files/run/byname.check | 24 | ||||
-rw-r--r-- | test/files/run/byname.scala | 84 |
5 files changed, 156 insertions, 11 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala index e82252c2ee..9138b2d412 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala @@ -425,7 +425,7 @@ trait Namers { self: Analyzer => } } - private def widenIfNotFinal(sym: Symbol, tpe: Type): Type = { + private def widenIfNotFinal(sym: Symbol, tpe: Type, pt: Type): Type = { val getter = if (sym.isValue && sym.owner.isClass && (sym hasFlag PRIVATE)) sym.getter(sym.owner) @@ -440,10 +440,12 @@ trait Namers { self: Analyzer => case _ => false } - if (sym.isVariable || - sym.isMethod && !(sym hasFlag ACCESSOR) || - isHidden(tpe)) tpe.widen - else if (!(sym hasFlag FINAL)) tpe.deconst + val tpe1 = tpe.deconst + val tpe2 = tpe1.widen + if ((sym.isVariable || sym.isMethod && !(sym hasFlag ACCESSOR))) + if (tpe2 <:< pt) tpe2 else tpe1 + else if (isHidden(tpe)) tpe2 + else if (!(sym hasFlag FINAL)) tpe1 else tpe } @@ -621,7 +623,7 @@ trait Namers { self: Analyzer => thisMethodType( if (tpt.isEmpty) { val pt = resultPt.substSym(tparamSyms, tparams map (_.symbol)) - tpt.tpe = widenIfNotFinal(meth, typer.computeType(rhs, pt)) + tpt.tpe = widenIfNotFinal(meth, typer.computeType(rhs, pt), pt) tpt.tpe } else typer.typedType(tpt).tpe) } @@ -730,8 +732,10 @@ trait Namers { self: Analyzer => context.error(tpt.pos, "missing parameter type"); ErrorType } else { - tpt.tpe = widenIfNotFinal(sym, - newTyper(typer1.context.make(vdef, sym)).computeType(rhs, WildcardType)) + tpt.tpe = widenIfNotFinal( + sym, + newTyper(typer1.context.make(vdef, sym)).computeType(rhs, WildcardType), + WildcardType) tpt.tpe } } else typer1.typedType(tpt).tpe diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala index 9fd430187e..ef5d092fe4 100644 --- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala +++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala @@ -129,8 +129,7 @@ abstract class RefChecks extends InfoTransform { def overrideTypeError() { if (other.tpe != ErrorType && member.tpe != ErrorType) { - overrideError("has incompatible type "+analyzer.underlying(member).tpe.normalize); - explainTypes(member.tpe, other.tpe); + overrideError("has incompatible type "+analyzer.underlying(member).tpe.normalize) } } @@ -229,7 +228,8 @@ abstract class RefChecks extends InfoTransform { } } else if (other.isTerm) { if (!overridesType(self.memberInfo(member), self.memberInfo(other))) { // 8 - overrideTypeError(); + overrideTypeError() + explainTypes(self.memberInfo(member), self.memberInfo(other)) } } } diff --git a/test/files/pos/bug1292.scala b/test/files/pos/bug1292.scala new file mode 100755 index 0000000000..83a996d530 --- /dev/null +++ b/test/files/pos/bug1292.scala @@ -0,0 +1,33 @@ +trait Foo[T <: Foo[T, Enum], Enum <: Enumeration] { + type StV = Enum#Value + type Meta = MegaFoo[T, Enum] + + type Slog <: Enumeration + + def getSingleton: Meta +} + +trait MegaFoo[T <: Foo[T, Enum], Enum <: Enumeration] extends Foo[T, Enum] { + def doSomething(what: T, misc: StV, dog: Meta#Event) = None + abstract class Event + object Event + + def stateEnumeration: Slog + def se2: Enum +} + +object E extends Enumeration { + val A = Value + val B = Value +} + +class RFoo extends Foo[RFoo, E.type] { + def getSingleton = MegaRFoo + + type Slog = E.type +} + +object MegaRFoo extends RFoo with MegaFoo[RFoo, E.type] { + def stateEnumeration = E + def se2 = E +} diff --git a/test/files/run/byname.check b/test/files/run/byname.check new file mode 100644 index 0000000000..7e49eedec1 --- /dev/null +++ b/test/files/run/byname.check @@ -0,0 +1,24 @@ +test no braces completed properly +test no braces r completed properly +test plain completed properly +test plain r completed properly +test old by name completed properly +test old by name r completed properly +test old by name s completed properly +test reg then by name completed properly +test reg then by name s completed properly +test varargs completed properly +test varargs r completed properly +test all completed properly +test all r completed properly +test all s completed properly +test c00 completed properly +test c00 r completed properly +test c00 rr completed properly +test cbb completed properly +test cbb r completed properly +test cbb rr completed properly +test cvv completed properly +test cvv r completed properly +test cvv rs completed properly +$ diff --git a/test/files/run/byname.scala b/test/files/run/byname.scala new file mode 100644 index 0000000000..af545d5e7d --- /dev/null +++ b/test/files/run/byname.scala @@ -0,0 +1,84 @@ +object Test extends Application { + +def test[A](name: String, expect: A, actual: => A) { + if (expect != actual) throw new AssertionError("test " + name + " failed") + else println("test " + name + " completed properly") +} + +def testNoBraces = 1 +test("no braces", 1, testNoBraces) + +val testNoBracesR = testNoBraces _ +test("no braces r", 1, testNoBracesR()) + +def testPlain(x: String, y: String): String = x + y +test("plain", "ab", testPlain("a", "b")) + +val testPlainR = testPlain _ +test("plain r", "cd", testPlainR("c", "d")) + +def testOldByName(x: => Int) = x + 1 +test("old by name", 3, testOldByName(1 + 1)) + +val testOldByNameR = testOldByName _ +test("old by name r", 3, testOldByNameR(1 + 1)) + +val testOldByNameS: (=> Int) => Int = testOldByName _ +test("old by name s", 3, testOldByNameS(2)) + +def testRegThenByName(x: Int, y: => Int): Int = x + y +test("reg then by name", 7, testRegThenByName(3, 2 * 2)) + +val testRegThenByNameS: (Int, =>Int) => Int = testRegThenByName _ +test("reg then by name s", 8, testRegThenByNameS(2, 12 / 2)) + +def testVarargs(x: Int*) = x.reduceLeft((x: Int, y: Int) => x + y) +test("varargs", 4, testVarargs(1, 2, 1)) + +val testVarargsR = testVarargs _ +test("varargs r", 4, testVarargsR(1, 2, 1)) + +def testAll(x: Int, y: => Int, z: Int*) = x + y + z.size +test("all", 5, testAll(1, 2, 22, 23)) + +val testAllR = testAll _ +test("all r", 7, testAllR(2, 3, 34, 35)) + +val testAllS: (Int, =>Int, Int*) => Int = testAll _ +test("all s", 8, testAllS(1, 5, 78, 89)) + +// test currying + +def testC00()(): Int = 1 +test("c00", 1, testC00()()) + +val testC00R = testC00 _ +test("c00 r", 1, testC00R()()) + +val testC00RR = testC00() _ +test("c00 rr", 1, testC00RR()) + + +def testCBB(a: => Int)(b: => Int) = a + b +test("cbb", 3, testCBB(1)(2)) + +val testCBBR = testCBB _ +test("cbb r", 5, testCBBR(1)(4)) + +val testCBBRR = testCBB(4) _ +test("cbb rr", 6, testCBBRR(2)) + + +def testCVV(a: Int*)(z: String, b: Int*) = a.size + b.size +test("cvv", 3, testCVV(1, 2)("", 8)) + +val testCVVR = testCVV _ +test("cvv r", 3, testCVVR(1)("", 8, 9)) + +val testCVVRS: (String, Int*) => Int = testCVV(2, 3) +test("cvv rs", 4, testCVVRS("", 5, 6)) + +println("$") + +// vim: set ts=4 sw=4 et: +} |