summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Namers.scala20
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala6
-rwxr-xr-xtest/files/pos/bug1292.scala33
-rw-r--r--test/files/run/byname.check24
-rw-r--r--test/files/run/byname.scala84
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:
+}