From 9b046d09520c79538e1468b15cccaf8a616e6462 Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Mon, 15 Jun 2009 10:13:11 +0000 Subject: - fixed #2057 - Symbol.annotations now first calls .initialize --- src/compiler/scala/tools/nsc/symtab/Symbols.scala | 9 +++++++-- .../scala/tools/nsc/typechecker/Namers.scala | 4 +++- .../tools/nsc/typechecker/NamesDefaults.scala | 22 ++++++---------------- .../scala/tools/nsc/typechecker/Typers.scala | 10 +++++----- test/files/run/names-defaults.scala | 7 +++++++ 5 files changed, 28 insertions(+), 24 deletions(-) diff --git a/src/compiler/scala/tools/nsc/symtab/Symbols.scala b/src/compiler/scala/tools/nsc/symtab/Symbols.scala index eb3313a71c..44b70a602c 100644 --- a/src/compiler/scala/tools/nsc/symtab/Symbols.scala +++ b/src/compiler/scala/tools/nsc/symtab/Symbols.scala @@ -96,11 +96,16 @@ trait Symbols { private var rawannots: List[AnnotationInfoBase] = Nil + /* Used in namer to check wether annotations were already assigned or not */ + def rawAnnotations:List[AnnotationInfoBase] = rawannots + /** After the typer phase (before, look at the definition's Modifiers), contains * the annotations attached to member a definition (class, method, type, field). */ def annotations: List[AnnotationInfo] = { - val annots1 = rawannots map { + // .initialize: the type completer of the symbol parses the annotations, + // see "def typeSig" in Namers + val annots1 = initialize.rawannots map { case LazyAnnotationInfo(annot) => annot() case a @ AnnotationInfo(_, _, _) => a } filter { a => !a.atp.isError } @@ -114,7 +119,7 @@ trait Symbols { } def addAnnotation(annot: AnnotationInfo): this.type = - setAnnotations(annot :: this.annotations) + setAnnotations(annot :: this.rawannots) /** Does this symbol have an annotation of the given class? */ def hasAnnotation(cls: Symbol) = annotations exists { _.atp.typeSymbol == cls } diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala index 5f490592f5..20061515c8 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala @@ -1060,7 +1060,9 @@ trait Namers { self: Analyzer => // they were added only in typer, depending on the compilation order, they would // be visible or not val annotated = if (sym.isModule) sym.moduleClass else sym - if (annotated.annotations.isEmpty) tree match { + // typeSig might be called multiple times, e.g. on a ValDef: val, getter, setter + // parse the annotations only once. + if (annotated.rawAnnotations.isEmpty) tree match { case defn: MemberDef => val ainfos = defn.mods.annotations filter { _ != null } map { ann => // need to be lazy, #1782 diff --git a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala index 5ccc22f4dd..b104bed2c7 100644 --- a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala +++ b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala @@ -165,29 +165,19 @@ trait NamesDefaults { self: Analyzer => // constructor calls case Select(New(TypeTree()), _) if isConstr => - val module = baseFun.symbol.owner.linkedModuleOfClass - val defaultQual = if (module == NoSymbol) None - - else Some(gen.mkAttributedRef(module)) - blockWithoutQualifier(baseFun1, defaultQual) + blockWithoutQualifier(baseFun1, None) case Select(New(Ident(_)), _) if isConstr => blockWithoutQualifier(baseFun1, None) case Select(nev @ New(sel @ Select(qual, typeName)), constr) if isConstr => + // #2057 val module = baseFun.symbol.owner.linkedModuleOfClass val defaultQual = if (module == NoSymbol) None - else Some(gen.mkAttributedRef(module)) - if (treeInfo.isPureExpr(qual)) { - blockWithoutQualifier(baseFun1, defaultQual) - } else { - val fun: Symbol => Tree = - sym => treeCopy.Select(baseFun1, - treeCopy.New(nev, - treeCopy.Select(sel, gen.mkAttributedRef(sym), typeName)), - constr) - blockWithQualifier(qual, fun, sym => defaultQual) - } + else Some(gen.mkAttributedSelect(qual.duplicate, module)) + // in `new q.C()', q is always stable + assert(treeInfo.isPureExpr(qual), qual) + blockWithoutQualifier(baseFun1, defaultQual) // other method calls diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 2e8032d10a..2bd8ae2041 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -1255,7 +1255,7 @@ trait Typers { self: Analyzer => error(getter.pos, getter+" is defined twice") // todo: potentially dangerous not to duplicate the trees and clone the symbols / types. - getter.setAnnotations(value.initialize.annotations) + getter.setAnnotations(value.annotations) if (value.hasFlag(LAZY)) List(stat) else { @@ -2340,12 +2340,12 @@ trait Typers { self: Analyzer => if (typedFun.isErroneous) annotationError else if (annType.typeSymbol isNonBottomSubClass ClassfileAnnotationClass) { - // annotation to be saved as java annotation + // annotation to be saved as java classfile annotation val isJava = typedFun.symbol.owner.hasFlag(JAVA) if (!annType.typeSymbol.isNonBottomSubClass(annClass)) { error(tpt.pos, "expected annotation of type "+ annClass.tpe +", found "+ annType) } else if (argss.length > 1) { - error(ann.pos, "multiple argument lists on java annotation") + error(ann.pos, "multiple argument lists on classfile annotation") } else { val args = if (argss.head.length == 1 && !isNamed(argss.head.head)) @@ -2372,7 +2372,7 @@ trait Typers { self: Analyzer => (sym.name, annArg) } case arg => - error(arg.pos, "java annotation arguments have to be supplied as named arguments") + error(arg.pos, "classfile annotation arguments have to be supplied as named arguments") (nme.ERROR, None) } @@ -2386,7 +2386,7 @@ trait Typers { self: Analyzer => else AnnotationInfo(annType, List(), nvPairs map {p => (p._1, p._2.get)}) } } else if (requireJava) { - error(ann.pos, "nested java annotations must be defined in java; found: "+ annType) + error(ann.pos, "nested classfile annotations must be defined in java; found: "+ annType) } else { val typedAnn = if (selfsym == NoSymbol) { typed(ann, mode, annClass.tpe) diff --git a/test/files/run/names-defaults.scala b/test/files/run/names-defaults.scala index 482c4f2f7b..c016a98e1a 100644 --- a/test/files/run/names-defaults.scala +++ b/test/files/run/names-defaults.scala @@ -181,6 +181,13 @@ object Test extends Application { println(b11.copy()()) + + // bug #2057 + class O { class I(x: Int = 1) } + class U extends O { val f = new I() } + + + // DEFINITIONS def test1(a: Int, b: String) = println(a +": "+ b) def test2(u: Int, v: Int)(k: String, l: Int) = println(l +": "+ k +", "+ (u + v)) -- cgit v1.2.3