diff options
author | Josh Suereth <Joshua.Suereth@gmail.com> | 2012-09-20 10:24:58 -0700 |
---|---|---|
committer | Josh Suereth <Joshua.Suereth@gmail.com> | 2012-09-20 10:24:58 -0700 |
commit | 9ec19f34ace7ffe327e8bf54e252cca50d3ac7ff (patch) | |
tree | f00fa691a419413bdfd511e210da9b14acb4339c /src/compiler | |
parent | 45c0b2428219b6a00514e21529650b32631880b6 (diff) | |
parent | beb08c206b24e00167a11ea13d1cd998b8e3b067 (diff) | |
download | scala-9ec19f34ace7ffe327e8bf54e252cca50d3ac7ff.tar.gz scala-9ec19f34ace7ffe327e8bf54e252cca50d3ac7ff.tar.bz2 scala-9ec19f34ace7ffe327e8bf54e252cca50d3ac7ff.zip |
Merge pull request #1356 from paulp/pullreq-1342
Pullreq 1342
Diffstat (limited to 'src/compiler')
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Typers.scala | 32 |
1 files changed, 22 insertions, 10 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 => |