diff options
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Typers.scala | 14 | ||||
-rw-r--r-- | test/files/pos/annotated-original/C_2.scala | 7 | ||||
-rw-r--r-- | test/files/pos/annotated-original/M_1.scala | 7 | ||||
-rw-r--r-- | test/files/run/annotatedRetyping.check | 6 | ||||
-rw-r--r-- | test/files/run/annotatedRetyping.scala | 62 |
5 files changed, 87 insertions, 9 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 478312116a..cff3f4f0fa 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -4153,15 +4153,11 @@ trait Typers extends Modes with Adaptations with Tags { def resultingTypeTree(tpe: Type) = { // we need symbol-ful originals for reification // hence we go the extra mile to hand-craft tis guy - val original = - if (arg1.isType) - arg1 match { - case tt @ TypeTree() => Annotated(ann, tt.original) - // this clause is needed to correctly compile stuff like "new C @D" or "@(inline @getter)" - case _ => Annotated(ann, arg1) - } - else - tree + val original = arg1 match { + case tt @ TypeTree() => Annotated(ann, tt.original) + // this clause is needed to correctly compile stuff like "new C @D" or "@(inline @getter)" + case _ => Annotated(ann, arg1) + } original setType ann.tpe TypeTree(tpe) setOriginal original setPos tree.pos.focus } diff --git a/test/files/pos/annotated-original/C_2.scala b/test/files/pos/annotated-original/C_2.scala new file mode 100644 index 0000000000..36a09ffe0c --- /dev/null +++ b/test/files/pos/annotated-original/C_2.scala @@ -0,0 +1,7 @@ +object Bug { + M.m { + def s = "" + M.m(s): @unchecked // error: macro has not been expanded. + ??? + } +} diff --git a/test/files/pos/annotated-original/M_1.scala b/test/files/pos/annotated-original/M_1.scala new file mode 100644 index 0000000000..01654e02cf --- /dev/null +++ b/test/files/pos/annotated-original/M_1.scala @@ -0,0 +1,7 @@ +import language.experimental.macros +import reflect.macros.Context + +object M { + def impl(c: Context)(a: c.Expr[Any]) = c.Expr[Any](c.resetLocalAttrs(a.tree)) + def m(a: Any) = macro impl +} diff --git a/test/files/run/annotatedRetyping.check b/test/files/run/annotatedRetyping.check new file mode 100644 index 0000000000..b296a80526 --- /dev/null +++ b/test/files/run/annotatedRetyping.check @@ -0,0 +1,6 @@ +typing List(1, 2).map(((x) => { + val another = scala.Tuple2(t.nt, t.tr): @testAnn match { + case scala.Tuple2(_, _) => 1 + }; + x +})) diff --git a/test/files/run/annotatedRetyping.scala b/test/files/run/annotatedRetyping.scala new file mode 100644 index 0000000000..cf1b0f27b5 --- /dev/null +++ b/test/files/run/annotatedRetyping.scala @@ -0,0 +1,62 @@ +import scala.tools.partest._ +import scala.tools.nsc._ + +object Test extends DirectTest { + + override def extraSettings: String = "-usejavacp" + + def code = """ + class testAnn extends annotation.Annotation + + object t { + def nt = 1 + def tr = "a" + } + + class Test { + List(1,2).map(x => { + val another = ((t.nt, t.tr): @testAnn) match { case (_, _) => 1 } + x + }) + } + """.trim + + + // point of this test: type-check the "Annotated" tree twice. first time the analyzer plugin types it, + // second time the typer. + + // bug was that typedAnnotated assigned a type to the Annotated tree. The second type check would consider + // the tree as alreadyTyped, which is not cool, the Annotated needs to be transformed into a Typed tree. + + def show() { + val global = newCompiler() + import global._ + import analyzer._ + import collection.{mutable => m} + + object analyzerPlugin extends AnalyzerPlugin { + val templates: m.Map[Symbol, (Template, Typer)] = m.Map() + override def pluginsTypeSig(tpe: Type, typer: Typer, defTree: Tree, pt: Type): Type = { + defTree match { + case impl: Template => + templates += typer.context.owner -> (impl, typer) + + case dd: DefDef if dd.symbol.isPrimaryConstructor && templates.contains(dd.symbol.owner) => + val (impl, templTyper) = templates(dd.symbol.owner) + for (stat <- impl.body.filterNot(_.isDef)) { + println("typing "+ stat) + val statsOwner = impl.symbol orElse templTyper.context.owner.newLocalDummy(impl.pos) + val tpr = analyzer.newTyper(templTyper.context.make(stat, statsOwner)) + tpr.typed(stat) + } + + case _ => + } + tpe + } + } + + addAnalyzerPlugin(analyzerPlugin) + compileString(global)(code) + } +} |