diff options
author | Paul Phillips <paulp@improving.org> | 2011-10-29 19:35:15 +0000 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2011-10-29 19:35:15 +0000 |
commit | 2d3fe5733cbc6bcf06892c8ee3cb19f7987f6b6a (patch) | |
tree | 6e7418bf49e9bf8dbcd05e233cc5b5c5f84497cd | |
parent | 48a26b9c2be3cb5390dafa8a13620c91fab0167d (diff) | |
download | scala-2d3fe5733cbc6bcf06892c8ee3cb19f7987f6b6a.tar.gz scala-2d3fe5733cbc6bcf06892c8ee3cb19f7987f6b6a.tar.bz2 scala-2d3fe5733cbc6bcf06892c8ee3cb19f7987f6b6a.zip |
Fix for crasher in explicitouter.
Closes SI-4970, review by moors.
-rw-r--r-- | src/compiler/scala/reflect/internal/TreeGen.scala | 71 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala | 16 | ||||
-rw-r--r-- | test/files/pos/t4970.scala | 13 |
3 files changed, 60 insertions, 40 deletions
diff --git a/src/compiler/scala/reflect/internal/TreeGen.scala b/src/compiler/scala/reflect/internal/TreeGen.scala index ce7fba6686..fae3975ed5 100644 --- a/src/compiler/scala/reflect/internal/TreeGen.scala +++ b/src/compiler/scala/reflect/internal/TreeGen.scala @@ -64,44 +64,47 @@ abstract class TreeGen { * termSym as the Ident's symbol. In that case, termSym must * not be NoSymbol. */ - def mkAttributedQualifier(tpe: Type, termSym: Symbol): Tree = tpe match { - case NoPrefix => - EmptyTree - case ThisType(clazz) => - if (clazz.isEffectiveRoot) EmptyTree - else mkAttributedThis(clazz) - case SingleType(pre, sym) => - mkApplyIfNeeded(mkAttributedStableRef(pre, sym)) - case TypeRef(pre, sym, args) => - if (sym.isRoot) { - mkAttributedThis(sym) - } else if (sym.isModuleClass) { - mkApplyIfNeeded(mkAttributedRef(pre, sym.sourceModule)) - } else if (sym.isModule || sym.isClass) { - assert(phase.erasedTypes, tpe) - mkAttributedThis(sym) - } else if (sym.isType) { - assert(termSym != NoSymbol, tpe) - mkAttributedIdent(termSym) setType tpe - } else { - mkAttributedRef(pre, sym) - } + def mkAttributedQualifier(tpe: Type, termSym: Symbol): Tree = { + def failMessage = "mkAttributedQualifier(" + tpe + ", " + termSym + ")" + tpe match { + case NoPrefix => + EmptyTree + case ThisType(clazz) => + if (clazz.isEffectiveRoot) EmptyTree + else mkAttributedThis(clazz) + case SingleType(pre, sym) => + mkApplyIfNeeded(mkAttributedStableRef(pre, sym)) + case TypeRef(pre, sym, args) => + if (sym.isRoot) { + mkAttributedThis(sym) + } else if (sym.isModuleClass) { + mkApplyIfNeeded(mkAttributedRef(pre, sym.sourceModule)) + } else if (sym.isModule || sym.isClass) { + assert(phase.erasedTypes, failMessage) + mkAttributedThis(sym) + } else if (sym.isType) { + assert(termSym != NoSymbol, failMessage) + mkAttributedIdent(termSym) setType tpe + } else { + mkAttributedRef(pre, sym) + } - case ConstantType(value) => - Literal(value) setType tpe + case ConstantType(value) => + Literal(value) setType tpe - case AnnotatedType(_, atp, _) => - mkAttributedQualifier(atp) + case AnnotatedType(_, atp, _) => + mkAttributedQualifier(atp) - case RefinedType(parents, _) => - // I am unclear whether this is reachable, but - // the following implementation looks logical -Lex - val firstStable = parents.find(_.isStable) - assert(!firstStable.isEmpty, tpe) - mkAttributedQualifier(firstStable.get) + case RefinedType(parents, _) => + // I am unclear whether this is reachable, but + // the following implementation looks logical -Lex + val firstStable = parents.find(_.isStable) + assert(!firstStable.isEmpty, failMessage + " parents = " + parents) + mkAttributedQualifier(firstStable.get) - case _ => - abort("bad qualifier: " + tpe) + case _ => + abort("bad qualifier received: " + failMessage) + } } /** If this is a reference to a method with an empty * parameter list, wrap it in an apply. diff --git a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala index 1bc283841b..192c4e9b59 100644 --- a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala +++ b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala @@ -346,12 +346,16 @@ abstract class ExplicitOuter extends InfoTransform * @pre mixinClass is an inner class */ def mixinOuterAccessorDef(mixinClass: Symbol): Tree = { - val outerAcc = outerAccessor(mixinClass) overridingSymbol currentClass - assert(outerAcc != NoSymbol) - val path = - if (mixinClass.owner.isTerm) THIS(mixinClass.owner.enclClass) - else gen.mkAttributedQualifier(currentClass.thisType baseType mixinClass prefix) - + val outerAcc = outerAccessor(mixinClass) overridingSymbol currentClass + def mixinPrefix = currentClass.thisType baseType mixinClass prefix; + assert(outerAcc != NoSymbol, "No outer accessor for inner mixin " + mixinClass + " in " + currentClass) + // I added the mixinPrefix.typeArgs.nonEmpty condition to address the + // crash in SI-4970. I feel quite sure this can be improved. + val path = ( + if (mixinClass.owner.isTerm) gen.mkAttributedThis(mixinClass.owner.enclClass) + else if (mixinPrefix.typeArgs.nonEmpty) gen.mkAttributedThis(mixinPrefix.typeSymbol) + else gen.mkAttributedQualifier(mixinPrefix) + ) localTyper typed { (DEF(outerAcc) withPos currentClass.pos) === { // Need to cast for nested outer refs in presence of self-types. See ticket #3274. diff --git a/test/files/pos/t4970.scala b/test/files/pos/t4970.scala new file mode 100644 index 0000000000..f2f284f919 --- /dev/null +++ b/test/files/pos/t4970.scala @@ -0,0 +1,13 @@ +trait OuterClass[V <: OuterClass[V]#InnerClass] { + trait InnerClass {self: V => + def method = () + } +} + +trait SubOuterClass[T <: SubOuterClass[T]#SubInnerClass] extends OuterClass[T] { + class SubInnerClass extends super.InnerClass {self: T => } +} + +trait SubOuterClass2[T <: SubOuterClass2[T]#SubInnerClass2] extends OuterClass[T] { + class SubInnerClass2 extends super.InnerClass {self: InnerClass with T => } +} |