diff options
author | Iulian Dragos <jaguarul@gmail.com> | 2006-12-12 11:06:03 +0000 |
---|---|---|
committer | Iulian Dragos <jaguarul@gmail.com> | 2006-12-12 11:06:03 +0000 |
commit | 9551ed8f5854ddad14a759ae7c5268b2883155b8 (patch) | |
tree | 0bb6d77d016f17a69bb19007ff3a99b3b8ca51b2 /src | |
parent | 5916f8929a40b3409a9e7cc41257126d278ec92a (diff) | |
download | scala-9551ed8f5854ddad14a759ae7c5268b2883155b8.tar.gz scala-9551ed8f5854ddad14a759ae7c5268b2883155b8.tar.bz2 scala-9551ed8f5854ddad14a759ae7c5268b2883155b8.zip |
Fixed bug 853, protected accessors crash with p...
Fixed bug 853, protected accessors crash with path dependent types.
Diffstat (limited to 'src')
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala | 29 |
1 files changed, 25 insertions, 4 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala index e41da55549..51ed171076 100644 --- a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala +++ b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala @@ -187,9 +187,12 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT val hasArgs = sym.tpe.paramTypes != Nil if (protAcc == NoSymbol) { val argTypes = tree.tpe // transform(sym.tpe) + // if the result type depends on the this type of an enclosing class, the accessor + // has to take an object of exactly this type, otherwise it's more general + val objType = if (isThisType(argTypes.finalResultType)) clazz.thisType else clazz.typeOfThis protAcc = clazz.newMethod(tree.pos, nme.protName(sym.originalName)) - .setInfo(MethodType(List(clazz.typeOfThis),argTypes)) + .setInfo(MethodType(List(objType),argTypes)) clazz.info.decls.enter(protAcc); val code = DefDef(protAcc, vparamss => { val obj = vparamss.head.head @@ -220,14 +223,17 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT */ private def makeArg(v: Symbol, obj: Symbol, expectedTpe: Type): Tree = { val res = Ident(v) - val sym = v.tpe.symbol + val sym = obj.tpe.symbol + var ownerClass: Symbol = NoSymbol val isDependentType = expectedTpe match { - case TypeRef(ThisType(outerSym), _, _) if (obj.isSubClass(outerSym)) => true + case TypeRef(path, _, _) => + ownerClass = thisTypeOfPath(path) + if (sym.isSubClass(ownerClass)) true else false case _ => false } if (isDependentType) { - val preciseTpe = typeRef(singleType(NoPrefix, obj), v.tpe.symbol, List()) + val preciseTpe = expectedTpe.asSeenFrom(singleType(NoPrefix, obj), ownerClass) //typeRef(singleType(NoPrefix, obj), v.tpe.symbol, List()) TypeApply(Select(res, definitions.Any_asInstanceOf), List(TypeTree(preciseTpe))) } @@ -235,6 +241,13 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT res } + /** For a path-dependent type, return the this type. */ + private def thisTypeOfPath(path: Type): Symbol = path match { + case ThisType(outerSym) => outerSym + case SingleType(rest, _) => thisTypeOfPath(rest) + case _ => NoSymbol + } + /** Add an accessor for field, if needed, and return a selection tree for it . * The result is not typed. */ @@ -311,5 +324,13 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT } else hostForAccessorOf(sym, referencingClass.owner.enclClass) } + + /** Is 'tpe' the type of a member of an enclosing class? */ + private def isThisType(tpe: Type): Boolean = tpe match { + case ThisType(sym) => (sym.isClass && !sym.isPackageClass) + case TypeRef(pref, _, _) => isThisType(pref) + case SingleType(pref, _) => isThisType(pref) + case _ => false + } } } |