summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosh Suereth <Joshua.Suereth@gmail.com>2012-09-20 10:24:58 -0700
committerJosh Suereth <Joshua.Suereth@gmail.com>2012-09-20 10:24:58 -0700
commit9ec19f34ace7ffe327e8bf54e252cca50d3ac7ff (patch)
treef00fa691a419413bdfd511e210da9b14acb4339c
parent45c0b2428219b6a00514e21529650b32631880b6 (diff)
parentbeb08c206b24e00167a11ea13d1cd998b8e3b067 (diff)
downloadscala-9ec19f34ace7ffe327e8bf54e252cca50d3ac7ff.tar.gz
scala-9ec19f34ace7ffe327e8bf54e252cca50d3ac7ff.tar.bz2
scala-9ec19f34ace7ffe327e8bf54e252cca50d3ac7ff.zip
Merge pull request #1356 from paulp/pullreq-1342
Pullreq 1342
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala32
-rw-r--r--test/files/neg/structural.check18
-rw-r--r--test/files/neg/t0565.check2
-rw-r--r--test/files/neg/t2144.check2
-rw-r--r--test/files/neg/t6336.check7
-rw-r--r--test/files/neg/t6336.scala1
6 files changed, 39 insertions, 23 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 9b93c7a214..fa86ec3b1e 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -1987,32 +1987,44 @@ trait Typers extends Modes with Adaptations with Tags {
* - the self-type of the refinement
* - a type member of the refinement
* - an abstract type declared outside of the refinement.
+ * - an instance of a value class
+ * Furthermore, the result type may not be a value class either
*/
- def checkMethodStructuralCompatible(meth: Symbol): Unit = {
- def fail(msg: String) = unit.error(meth.pos, msg)
+ def checkMethodStructuralCompatible(ddef: DefDef): Unit = {
+ val meth = ddef.symbol
+ def fail(pos: Position, msg: String) = unit.error(pos, msg)
val tp: Type = meth.tpe match {
case mt @ MethodType(_, _) => mt
case NullaryMethodType(restpe) => restpe // TODO_NMT: drop NullaryMethodType from resultType?
case PolyType(_, restpe) => restpe
case _ => NoType
}
- def failStruct(what: String) =
- fail(s"Parameter type in structural refinement may not refer to $what")
- for (paramType <- tp.paramTypes) {
+ def nthParamPos(n: Int) = ddef.vparamss match {
+ case xs :: _ if xs.length > n => xs(n).pos
+ case _ => meth.pos
+ }
+ def failStruct(pos: Position, what: String, where: String = "Parameter") =
+ fail(pos, s"$where type in structural refinement may not refer to $what")
+
+ foreachWithIndex(tp.paramTypes) { (paramType, idx) =>
val sym = paramType.typeSymbol
+ def paramPos = nthParamPos(idx)
if (sym.isAbstractType) {
if (!sym.hasTransOwner(meth.owner))
- failStruct("an abstract type defined outside that refinement")
+ failStruct(paramPos, "an abstract type defined outside that refinement")
else if (!sym.hasTransOwner(meth))
- failStruct("a type member of that refinement")
+ failStruct(paramPos, "a type member of that refinement")
}
if (sym.isDerivedValueClass)
- failStruct("a user-defined value class")
+ failStruct(paramPos, "a user-defined value class")
if (paramType.isInstanceOf[ThisType] && sym == meth.owner)
- failStruct("the type of that refinement (self type)")
+ failStruct(paramPos, "the type of that refinement (self type)")
}
+ if (tp.resultType.typeSymbol.isDerivedValueClass)
+ failStruct(ddef.tpt.pos, "a user-defined value class", where = "Result")
}
+
def typedUseCase(useCase: UseCase) {
def stringParser(str: String): syntaxAnalyzer.Parser = {
val file = new BatchSourceFile(context.unit.source.file, str) {
@@ -2129,7 +2141,7 @@ trait Typers extends Modes with Adaptations with Tags {
}
}
if (meth.isStructuralRefinementMember)
- checkMethodStructuralCompatible(meth)
+ checkMethodStructuralCompatible(ddef)
if (meth.isImplicit && !meth.isSynthetic) meth.info.paramss match {
case List(param) :: _ if !param.isImplicit =>
diff --git a/test/files/neg/structural.check b/test/files/neg/structural.check
index 6ef57db1b4..5b2f352a76 100644
--- a/test/files/neg/structural.check
+++ b/test/files/neg/structural.check
@@ -1,28 +1,28 @@
structural.scala:47: error: Parameter type in structural refinement may not refer to the type of that refinement (self type)
val s1 = new { def f(p: this.type): Unit = () }
- ^
+ ^
structural.scala:10: error: Parameter type in structural refinement may not refer to an abstract type defined outside that refinement
def f1[C <: Object](x: Object{ type D <: Object; def m[E >: Null <: Object](x: A): Object; val x: A }) = x.m[Tata](x.x) //fail
- ^
+ ^
structural.scala:11: error: Parameter type in structural refinement may not refer to an abstract type defined outside that refinement
def f2[C <: Object](x: Object{ type D <: Object; def m[E >: Null <: Object](x: B): Object; val x: B }) = x.m[Tata](x.x) //fail
- ^
+ ^
structural.scala:12: error: Parameter type in structural refinement may not refer to an abstract type defined outside that refinement
def f3[C <: Object](x: Object{ type D <: Object; def m[E >: Null <: Object](x: C): Object; val x: C }) = x.m[Tata](x.x) //fail
- ^
+ ^
structural.scala:13: error: Parameter type in structural refinement may not refer to a type member of that refinement
def f4[C <: Object](x: Object{ type D <: Object; def m[E >: Null <: Object](x: D): Object; val x: D }) = x.m[Tata](x.x) //fail
- ^
+ ^
structural.scala:42: error: Parameter type in structural refinement may not refer to an abstract type defined outside that refinement
type Summable[T] = { def +(v : T) : T }
- ^
+ ^
structural.scala:46: error: Parameter type in structural refinement may not refer to the type of that refinement (self type)
type S1 = { def f(p: this.type): Unit }
- ^
+ ^
structural.scala:49: error: Parameter type in structural refinement may not refer to a type member of that refinement
type S2 = { type T; def f(p: T): Unit }
- ^
+ ^
structural.scala:52: error: Parameter type in structural refinement may not refer to an abstract type defined outside that refinement
def s3[U >: Null <: Object](p: { def f(p: U): Unit; def u: U }) = ()
- ^
+ ^
9 errors found
diff --git a/test/files/neg/t0565.check b/test/files/neg/t0565.check
index c5a64d0e53..98e61a2503 100644
--- a/test/files/neg/t0565.check
+++ b/test/files/neg/t0565.check
@@ -1,4 +1,4 @@
t0565.scala:8: error: Parameter type in structural refinement may not refer to a type member of that refinement
def z (w : T) : T } =
- ^
+ ^
one error found
diff --git a/test/files/neg/t2144.check b/test/files/neg/t2144.check
index 7239f4406e..670e188c2a 100644
--- a/test/files/neg/t2144.check
+++ b/test/files/neg/t2144.check
@@ -1,4 +1,4 @@
t2144.scala:2: error: Parameter type in structural refinement may not refer to an abstract type defined outside that refinement
def foo[A](a: A) = new { def bar(x: A): A = x }
- ^
+ ^
one error found
diff --git a/test/files/neg/t6336.check b/test/files/neg/t6336.check
index f6b35ad232..f70a5f70ab 100644
--- a/test/files/neg/t6336.check
+++ b/test/files/neg/t6336.check
@@ -1,4 +1,7 @@
t6336.scala:3: error: Parameter type in structural refinement may not refer to a user-defined value class
val a = new { def y[T](x: X[T]) = x.i }
- ^
-one error found
+ ^
+t6336.scala:4: error: Result type in structural refinement may not refer to a user-defined value class
+ val b = new { def y[T](x: T): X[T] = new X(2) }
+ ^
+two errors found
diff --git a/test/files/neg/t6336.scala b/test/files/neg/t6336.scala
index a9844ff94f..b1d61f4dd2 100644
--- a/test/files/neg/t6336.scala
+++ b/test/files/neg/t6336.scala
@@ -1,6 +1,7 @@
object D {
def main(args: Array[String]) {
val a = new { def y[T](x: X[T]) = x.i }
+ val b = new { def y[T](x: T): X[T] = new X(2) }
val x = new X(3)
val t = a.y(x)
println(t)