summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosh Suereth <joshua.suereth@gmail.com>2012-11-01 10:44:30 -0400
committerJosh Suereth <joshua.suereth@gmail.com>2012-11-01 10:44:30 -0400
commit79087c79c402ababbb50fa9d1e4e78b0e52189c6 (patch)
tree210f4f0024bffd9a0061285a948079c518342983
parent557fe9e9d2c14f363918e89056233a981dc5ef5c (diff)
parent17497cbc95d2e3cfe52eb2a1ece0d414e9308660 (diff)
downloadscala-79087c79c402ababbb50fa9d1e4e78b0e52189c6.tar.gz
scala-79087c79c402ababbb50fa9d1e4e78b0e52189c6.tar.bz2
scala-79087c79c402ababbb50fa9d1e4e78b0e52189c6.zip
Merge branch '2.10.0-wip' of github.com:scala/scala into 2.10.0-wip
-rw-r--r--src/actors/scala/actors/remote/NetKernel.scala2
-rw-r--r--src/actors/scala/actors/remote/RemoteActor.scala10
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala5
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala5
-rw-r--r--src/compiler/scala/tools/nsc/transform/Mixin.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Duplicators.scala8
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Implicits.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala31
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala25
-rw-r--r--src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSTransform.scala22
-rw-r--r--test/files/jvm/actmig-remote-actor-self.check1
-rw-r--r--test/files/jvm/actmig-remote-actor-self.scala34
-rw-r--r--test/files/pos/t5031_3/Foo_1.scala5
-rw-r--r--test/files/pos/t5031_3/Main_2.scala6
-rw-r--r--test/files/pos/t5031_3/package.scala6
-rw-r--r--test/files/pos/t6575a.scala15
-rw-r--r--test/files/pos/t6575b.scala17
17 files changed, 161 insertions, 35 deletions
diff --git a/src/actors/scala/actors/remote/NetKernel.scala b/src/actors/scala/actors/remote/NetKernel.scala
index c6b2d8b8cd..8338f9a6a6 100644
--- a/src/actors/scala/actors/remote/NetKernel.scala
+++ b/src/actors/scala/actors/remote/NetKernel.scala
@@ -60,7 +60,7 @@ private[remote] class NetKernel(service: Service) {
send(node, name, msg, 'nosession)
def send(node: Node, name: Symbol, msg: AnyRef, session: Symbol) {
- val senderLoc = Locator(service.node, getOrCreateName(Actor.self))
+ val senderLoc = Locator(service.node, getOrCreateName(Actor.self(Scheduler)))
val receiverLoc = Locator(node, name)
namedSend(senderLoc, receiverLoc, msg, session)
}
diff --git a/src/actors/scala/actors/remote/RemoteActor.scala b/src/actors/scala/actors/remote/RemoteActor.scala
index 23cbae8532..571cb67e95 100644
--- a/src/actors/scala/actors/remote/RemoteActor.scala
+++ b/src/actors/scala/actors/remote/RemoteActor.scala
@@ -40,7 +40,7 @@ package remote
*/
object RemoteActor {
- private val kernels = new scala.collection.mutable.HashMap[Actor, NetKernel]
+ private val kernels = new scala.collection.mutable.HashMap[InternalActor, NetKernel]
/* If set to <code>null</code> (default), the default class loader
* of <code>java.io.ObjectInputStream</code> is used for deserializing
@@ -62,7 +62,7 @@ object RemoteActor {
private def createNetKernelOnPort(port: Int): NetKernel = {
val serv = TcpService(port, cl)
val kern = serv.kernel
- val s = Actor.self
+ val s = Actor.self(Scheduler)
kernels += Pair(s, kern)
s.onTerminate {
@@ -86,10 +86,10 @@ object RemoteActor {
* node.
*/
def register(name: Symbol, a: Actor): Unit = synchronized {
- val kernel = kernels.get(Actor.self) match {
+ val kernel = kernels.get(Actor.self(Scheduler)) match {
case None =>
val serv = TcpService(TcpService.generatePort, cl)
- kernels += Pair(Actor.self, serv.kernel)
+ kernels += Pair(Actor.self(Scheduler), serv.kernel)
serv.kernel
case Some(k) =>
k
@@ -97,7 +97,7 @@ object RemoteActor {
kernel.register(name, a)
}
- private def selfKernel = kernels.get(Actor.self) match {
+ private def selfKernel = kernels.get(Actor.self(Scheduler)) match {
case None =>
// establish remotely accessible
// return path (sender)
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala
index f9eeb41e6d..6d7948f0a9 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala
@@ -558,7 +558,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters {
def innerClassSymbolFor(s: Symbol): Symbol =
if (s.isClass) s else if (s.isModule) s.moduleClass else NoSymbol
- /** Return the a name of this symbol that can be used on the Java platform. It removes spaces from names.
+ /** Return the name of this symbol that can be used on the Java platform. It removes spaces from names.
*
* Special handling:
* scala.Nothing erases to scala.runtime.Nothing$
@@ -607,7 +607,8 @@ abstract class GenASM extends SubComponent with BytecodeWriters {
case None =>
reverseJavaName.put(internalName, trackedSym)
case Some(oldsym) =>
- assert((oldsym == trackedSym) || (oldsym == RuntimeNothingClass) || (oldsym == RuntimeNullClass), // In contrast, neither NothingClass nor NullClass show up bytecode-level.
+ assert((oldsym == trackedSym) || (oldsym == RuntimeNothingClass) || (oldsym == RuntimeNullClass) ||
+ (oldsym.isModuleClass && (oldsym.sourceModule == trackedSym.sourceModule)), // In contrast, neither NothingClass nor NullClass show up bytecode-level.
"how can getCommonSuperclass() do its job if different class symbols get the same bytecode-level internal name: " + internalName)
}
}
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
index 8fd8dfaf83..9caafe6912 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
@@ -94,7 +94,10 @@ abstract class ClassfileParser {
pushBusy(root) {
this.in = new AbstractFileReader(file)
this.clazz = if (root.isModule) root.companionClass else root
- this.staticModule = clazz.companionModule
+ // WARNING! do no use clazz.companionModule to find staticModule.
+ // In a situation where root can be defined, but its companionClass not,
+ // this would give incorrect results (see SI-5031 in separate compilation scenario)
+ this.staticModule = if (root.isModule) root else root.companionModule
this.isScala = false
parseHeader
diff --git a/src/compiler/scala/tools/nsc/transform/Mixin.scala b/src/compiler/scala/tools/nsc/transform/Mixin.scala
index 2b0520592b..80900a1a0a 100644
--- a/src/compiler/scala/tools/nsc/transform/Mixin.scala
+++ b/src/compiler/scala/tools/nsc/transform/Mixin.scala
@@ -481,7 +481,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
/** The typer */
private var localTyper: erasure.Typer = _
- private def typedPos(pos: Position)(tree: Tree) = localTyper typed { atPos(pos)(tree) }
+ private def typedPos(pos: Position)(tree: Tree): Tree = localTyper.typedPos(pos)(tree)
private def localTyped(pos: Position, tree: Tree, pt: Type) = localTyper.typed(atPos(pos)(tree), pt)
/** Map lazy values to the fields they should null after initialization. */
diff --git a/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala b/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala
index 97e86d183e..aa507efe5a 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala
@@ -321,7 +321,9 @@ abstract class Duplicators extends Analyzer {
// we use the symbol name instead of the tree name because the symbol may have been
// name mangled, rendering the tree name obsolete
// log(tree)
- val t = super.typed(atPos(tree.pos)(Select(This(newClassOwner), tree.symbol.name)), mode, pt)
+ val t = super.typedPos(tree.pos, mode, pt) {
+ Select(This(newClassOwner), tree.symbol.name)
+ }
// log("typed to: " + t + "; tpe = " + t.tpe + "; " + inspectTpe(t.tpe))
t
@@ -331,7 +333,7 @@ abstract class Duplicators extends Analyzer {
val tree1 = This(newClassOwner)
// log("tree1: " + tree1)
debuglog("mapped " + tree + " to " + tree1)
- super.typed(atPos(tree.pos)(tree1), mode, pt)
+ super.typedPos(tree.pos, mode, pt)(tree1)
case This(_) =>
debuglog("selection on this, plain: " + tree)
@@ -368,7 +370,7 @@ abstract class Duplicators extends Analyzer {
cases
}
- super.typed(atPos(tree.pos)(Match(scrut, cases1)), mode, pt)
+ super.typedPos(tree.pos, mode, pt)(Match(scrut, cases1))
case EmptyTree =>
// no need to do anything, in particular, don't set the type to null, EmptyTree.tpe_= asserts
diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
index 7852ff49e1..99301cebcf 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
@@ -1172,7 +1172,7 @@ trait Implicits {
}
try {
- val tree1 = typed(atPos(pos.focus)(arg))
+ val tree1 = typedPos(pos.focus)(arg)
if (context.hasErrors) processMacroExpansionError(context.errBuffer.head.errPos, context.errBuffer.head.errMsg)
else new SearchResult(tree1, EmptyTreeTypeSubstituter)
} catch {
diff --git a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
index cc3d980cf1..001acc7a80 100644
--- a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
@@ -36,11 +36,31 @@ trait SyntheticMethods extends ast.TreeDSL {
import definitions._
import CODE._
+ private lazy val productSymbols = List(Product_productPrefix, Product_productArity, Product_productElement, Product_iterator, Product_canEqual)
+ private lazy val valueSymbols = List(Any_hashCode, Any_equals)
+ private lazy val caseSymbols = List(Object_hashCode, Object_toString) ::: productSymbols
+ private lazy val caseValueSymbols = Any_toString :: valueSymbols ::: productSymbols
+ private lazy val caseObjectSymbols = Object_equals :: caseSymbols
+ private def symbolsToSynthesize(clazz: Symbol): List[Symbol] = {
+ if (clazz.isCase) {
+ if (clazz.isDerivedValueClass) caseValueSymbols
+ else if (clazz.isModuleClass) caseSymbols
+ else caseObjectSymbols
+ }
+ else if (clazz.isDerivedValueClass) valueSymbols
+ else Nil
+ }
+
/** Add the synthetic methods to case classes.
*/
def addSyntheticMethods(templ: Template, clazz0: Symbol, context: Context): Template = {
-
- if (phase.erasedTypes)
+ val syntheticsOk = (phase.id <= currentRun.typerPhase.id) && {
+ symbolsToSynthesize(clazz0) filter (_ matchingSymbol clazz0.info isSynthetic) match {
+ case Nil => true
+ case syms => log("Not adding synthetic methods: already has " + syms.mkString(", ")) ; false
+ }
+ }
+ if (!syntheticsOk)
return templ
val synthesizer = new ClassMethodSynthesis(
@@ -94,9 +114,9 @@ trait SyntheticMethods extends ast.TreeDSL {
Apply(gen.mkAttributedRef(method), args.toList)
}
- // Any member, including private
+ // Any concrete member, including private
def hasConcreteImpl(name: Name) =
- clazz.info.member(name).alternatives exists (m => !m.isDeferred && !m.isSynthetic)
+ clazz.info.member(name).alternatives exists (m => !m.isDeferred)
def hasOverridingImplementation(meth: Symbol) = {
val sym = clazz.info nonPrivateMember meth.name
@@ -347,8 +367,7 @@ trait SyntheticMethods extends ast.TreeDSL {
(lb ++= templ.body ++= synthesize()).toList
}
- if (phase.id > currentRun.typerPhase.id) templ
- else deriveTemplate(templ)(body =>
+ deriveTemplate(templ)(body =>
if (clazz.isCase) caseTemplateBody()
else synthesize() match {
case Nil => body // avoiding unnecessary copy
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index f82786da35..c5bd92a943 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -1049,7 +1049,9 @@ trait Typers extends Modes with Adaptations with Tags {
case other =>
other
}
- typed(atPos(tree.pos)(Select(qual setPos tree.pos.makeTransparent, nme.apply)), mode, pt)
+ typedPos(tree.pos, mode, pt) {
+ Select(qual setPos tree.pos.makeTransparent, nme.apply)
+ }
}
// begin adapt
@@ -1147,11 +1149,15 @@ trait Typers extends Modes with Adaptations with Tags {
if (sym == UnitClass && tree.tpe <:< AnyClass.tpe) { // (12)
if (settings.warnValueDiscard.value)
context.unit.warning(tree.pos, "discarded non-Unit value")
- return typed(atPos(tree.pos)(Block(List(tree), Literal(Constant()))), mode, pt)
+ return typedPos(tree.pos, mode, pt) {
+ Block(List(tree), Literal(Constant()))
+ }
} else if (isNumericValueClass(sym) && isNumericSubType(tree.tpe, pt)) {
if (settings.warnNumericWiden.value)
context.unit.warning(tree.pos, "implicit numeric widening")
- return typed(atPos(tree.pos)(Select(tree, "to" + sym.name)), mode, pt)
+ return typedPos(tree.pos, mode, pt) {
+ Select(tree, "to" + sym.name)
+ }
}
case AnnotatedType(_, _, _) if canAdaptAnnotations(tree, mode, pt) => // (13)
return typed(adaptAnnotations(tree, mode, pt), mode, pt)
@@ -2590,7 +2596,17 @@ trait Typers extends Modes with Adaptations with Tags {
def translated =
if (members.head eq EmptyTree) setError(tree)
- else typed(atPos(tree.pos)(Block(List(ClassDef(anonClass, NoMods, ListOfNil, ListOfNil, members, tree.pos.focus)), atPos(tree.pos.focus)(New(anonClass.tpe)))), mode, pt)
+ else {
+ val typedBlock = typedPos(tree.pos, mode, pt) {
+ Block(ClassDef(anonClass, NoMods, ListOfNil, ListOfNil, members, tree.pos.focus), atPos(tree.pos.focus)(New(anonClass.tpe)))
+ }
+ // Don't leak implementation details into the type, see SI-6575
+ if (isPartial && !typedBlock.isErrorTyped)
+ typedPos(tree.pos, mode, pt) {
+ Typed(typedBlock, TypeTree(typedBlock.tpe baseType PartialFunctionClass))
+ }
+ else typedBlock
+ }
}
// Function(params, Match(sel, cases)) ==> new <Partial>Function { def apply<OrElse>(params) = `translateMatch('sel match { cases }')` }
@@ -5494,6 +5510,7 @@ trait Typers extends Modes with Adaptations with Tags {
ret
}
+ def typedPos(pos: Position, mode: Int, pt: Type)(tree: Tree) = typed(atPos(pos)(tree), mode, pt)
def typedPos(pos: Position)(tree: Tree) = typed(atPos(pos)(tree))
// TODO: see if this formulation would impose any penalty, since
// it makes for a lot less casting.
diff --git a/src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSTransform.scala b/src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSTransform.scala
index 54a0079f40..4482bf2b7c 100644
--- a/src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSTransform.scala
+++ b/src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSTransform.scala
@@ -193,12 +193,12 @@ abstract class SelectiveCPSTransform extends PluginComponent with
val pos = catches.head.pos
val funSym = currentOwner.newValueParameter(cpsNames.catches, pos).setInfo(appliedType(PartialFunctionClass.tpe, List(ThrowableClass.tpe, targettp)))
- val funDef = localTyper.typed(atPos(pos) {
+ val funDef = localTyper.typedPos(pos) {
ValDef(funSym, Match(EmptyTree, catches1))
- })
- val expr2 = localTyper.typed(atPos(pos) {
+ }
+ val expr2 = localTyper.typedPos(pos) {
Apply(Select(expr1, expr1.tpe.member(cpsNames.flatMapCatch)), List(Ident(funSym)))
- })
+ }
val exSym = currentOwner.newValueParameter(cpsNames.ex, pos).setInfo(ThrowableClass.tpe)
@@ -223,7 +223,7 @@ abstract class SelectiveCPSTransform extends PluginComponent with
val pos = finalizer.pos
val finalizer2 = duplicateTree(finalizer1)
val fun = Function(List(), finalizer2)
- val expr3 = localTyper.typed(atPos(pos) { Apply(Select(expr2, expr2.tpe.member("mapFinally")), List(fun)) })
+ val expr3 = localTyper.typedPos(pos) { Apply(Select(expr2, expr2.tpe.member("mapFinally")), List(fun)) }
val chown = new ChangeOwnerTraverser(currentOwner, fun.symbol)
chown.traverse(finalizer2)
@@ -290,7 +290,7 @@ abstract class SelectiveCPSTransform extends PluginComponent with
val body1 = (new TreeSymSubstituter(List(vd.symbol), List(ctxValSym)))(body)
- val body2 = localTyper.typed(atPos(vd.symbol.pos) { body1 })
+ val body2 = localTyper.typedPos(vd.symbol.pos) { body1 }
// in theory it would be nicer to look for an @cps annotation instead
// of testing for Context
@@ -304,7 +304,7 @@ abstract class SelectiveCPSTransform extends PluginComponent with
def applyCombinatorFun(ctxR: Tree, body: Tree) = {
val arg = currentOwner.newValueParameter(name, ctxR.pos).setInfo(tpe)
val body1 = (new TreeSymSubstituter(List(vd.symbol), List(arg)))(body)
- val fun = localTyper.typed(atPos(vd.symbol.pos) { Function(List(ValDef(arg)), body1) }) // types body as well
+ val fun = localTyper.typedPos(vd.symbol.pos) { Function(List(ValDef(arg)), body1) } // types body as well
arg.owner = fun.symbol
body1.changeOwner(currentOwner -> fun.symbol)
@@ -328,9 +328,9 @@ abstract class SelectiveCPSTransform extends PluginComponent with
debuglog("will use method:"+methodName)
- localTyper.typed(atPos(vd.symbol.pos) {
+ localTyper.typedPos(vd.symbol.pos) {
Apply(Select(ctxR, ctxR.tpe.member(methodName)), List(fun))
- })
+ }
}
def mkBlock(stms: List[Tree], expr: Tree) = if (stms.nonEmpty) Block(stms, expr) else expr
@@ -352,12 +352,12 @@ abstract class SelectiveCPSTransform extends PluginComponent with
def ctxRef = localTyper.typed(Ident(ctxSym))
val argSym = currentOwner.newValue(vd.symbol.name).setInfo(tpe)
val argDef = localTyper.typed(ValDef(argSym, Select(ctxRef, ctxRef.tpe.member(cpsNames.getTrivialValue))))
- val switchExpr = localTyper.typed(atPos(vd.symbol.pos) {
+ val switchExpr = localTyper.typedPos(vd.symbol.pos) {
val body2 = mkBlock(bodyStms, bodyExpr).duplicate // dup before typing!
If(Select(ctxRef, ctxSym.tpe.member(cpsNames.isTrivial)),
applyTrivial(argSym, mkBlock(argDef::bodyStms, bodyExpr)),
applyCombinatorFun(ctxRef, body2))
- })
+ }
(List(ctxDef), switchExpr)
} else {
// ctx.flatMap { <lhs> => ... }
diff --git a/test/files/jvm/actmig-remote-actor-self.check b/test/files/jvm/actmig-remote-actor-self.check
new file mode 100644
index 0000000000..79d23cb337
--- /dev/null
+++ b/test/files/jvm/actmig-remote-actor-self.check
@@ -0,0 +1 @@
+registered
diff --git a/test/files/jvm/actmig-remote-actor-self.scala b/test/files/jvm/actmig-remote-actor-self.scala
new file mode 100644
index 0000000000..2b994f6081
--- /dev/null
+++ b/test/files/jvm/actmig-remote-actor-self.scala
@@ -0,0 +1,34 @@
+/**
+ * NOTE: Code snippets from this test are included in the Actor Migration Guide. In case you change
+ * code in these tests prior to the 2.10.0 release please send the notification to @vjovanov.
+ */
+import scala.actors._
+import scala.actors.migration._
+import scala.actors.remote._
+import scala.actors.remote.RemoteActor._
+import scala.concurrent._
+import scala.concurrent.duration._
+
+object Test {
+ val finished = Promise[Boolean]
+
+ def main(args: Array[String]): Unit = {
+
+ // can fail with class cast exception in alive
+ val myAkkaActor = ActorDSL.actor(new StashingActor {
+ override def preStart() = {
+ alive(42013)
+ println("registered")
+ finished success true
+ context.stop(self)
+ }
+
+ def receive = {
+ case x: Int =>
+ }
+ })
+
+ Await.result(finished.future, Duration.Inf).toString
+ }
+
+}
diff --git a/test/files/pos/t5031_3/Foo_1.scala b/test/files/pos/t5031_3/Foo_1.scala
new file mode 100644
index 0000000000..5934a6ba79
--- /dev/null
+++ b/test/files/pos/t5031_3/Foo_1.scala
@@ -0,0 +1,5 @@
+package foo.bar
+
+object Foo {
+ def bar = 42
+}
diff --git a/test/files/pos/t5031_3/Main_2.scala b/test/files/pos/t5031_3/Main_2.scala
new file mode 100644
index 0000000000..2079460b83
--- /dev/null
+++ b/test/files/pos/t5031_3/Main_2.scala
@@ -0,0 +1,6 @@
+package org.example
+
+object Main extends App {
+ println(foo.bar.Foo.bar)
+}
+
diff --git a/test/files/pos/t5031_3/package.scala b/test/files/pos/t5031_3/package.scala
new file mode 100644
index 0000000000..23fede7d04
--- /dev/null
+++ b/test/files/pos/t5031_3/package.scala
@@ -0,0 +1,6 @@
+package foo
+
+package object bar {
+ type Foo = Int => String
+}
+
diff --git a/test/files/pos/t6575a.scala b/test/files/pos/t6575a.scala
new file mode 100644
index 0000000000..f128714dab
--- /dev/null
+++ b/test/files/pos/t6575a.scala
@@ -0,0 +1,15 @@
+trait X { def foo: PartialFunction[Int, Int] }
+
+trait Y extends X {
+ // Inferred type was AbstractPartialFunction[Int, Int] with Serializable
+ abstract override def foo = { case i => super.foo(i) * 2 }
+}
+trait Z extends X {
+ // ditto
+ abstract override def foo = { case i => super.foo(i) + 3 }
+}
+
+trait Comb extends Y with Z {
+ // ... which led to a type error here.
+ abstract override def foo: PartialFunction[Int, Int] = { case i => super.foo(i) - 2 }
+}
diff --git a/test/files/pos/t6575b.scala b/test/files/pos/t6575b.scala
new file mode 100644
index 0000000000..d3e58b2a16
--- /dev/null
+++ b/test/files/pos/t6575b.scala
@@ -0,0 +1,17 @@
+// inferred types were okay here as Function nodes aren't
+// translated into anoymous subclasses of AbstractFunctionN
+// until after the typer.
+//
+// So this test is just confirmation.
+trait X { def foo: Function1[Int, Int] }
+
+trait Y extends X {
+ abstract override def foo = { case i => super.foo(i) * 2 }
+}
+trait Z extends X {
+ abstract override def foo = { case i => super.foo(i) + 3 }
+}
+
+trait Comb extends Y with Z {
+ abstract override def foo: Function1[Int, Int] = { case i => super.foo(i) - 2 }
+}