From 6c92dd970abfe81be07aa24ac761807a76dd8ea4 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Fri, 23 Jun 2017 17:38:54 +0200 Subject: [PATCH 1/4] Fix #2795: Fix `is` test on Names The previous logic would have UniqueNames shadow everything else. So if one starts with a UniqueName(prefix, sep, number), and then does a qualified name, one gets a unique name or a qualified name. the resulting name should still be recognized as a qualified name, however. The change in this commit achieves that. --- compiler/src/dotty/tools/dotc/core/NameKinds.scala | 6 ++++-- compiler/src/dotty/tools/dotc/core/Names.scala | 12 ++++++++++-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/NameKinds.scala b/compiler/src/dotty/tools/dotc/core/NameKinds.scala index 396ef6f821e7..430a36fda1c0 100644 --- a/compiler/src/dotty/tools/dotc/core/NameKinds.scala +++ b/compiler/src/dotty/tools/dotc/core/NameKinds.scala @@ -42,10 +42,11 @@ object NameKinds { override def toString = infoString } - /** Does this kind define logically a new name? Tested by the `rewrite` and `collect` - * combinators of names. + /** Does this kind define logically a new name (respectively qualified name)? + * Tested by the `rewrite` and `collect` combinators of class `Name`. */ def definesNewName = false + def definesQualifiedName = false /** Unmangle simple name `name` into a name of this kind, or return * original name if this is not possible. @@ -142,6 +143,7 @@ object NameKinds { } override def definesNewName = true + override def definesQualifiedName = true def mkString(underlying: TermName, info: ThisInfo) = s"$underlying$separator${info.name}" diff --git a/compiler/src/dotty/tools/dotc/core/Names.scala b/compiler/src/dotty/tools/dotc/core/Names.scala index 9d6b03cf5afc..7dcbfdbf6128 100644 --- a/compiler/src/dotty/tools/dotc/core/Names.scala +++ b/compiler/src/dotty/tools/dotc/core/Names.scala @@ -233,9 +233,17 @@ object Names { } } + /** Is it impossible that trees of kind `kind` qualify as + * derived trees of kind `shadowed`? + */ + private def shadows(kind: NameKind, shadowed: NameKind): Boolean = + kind.tag < shadowed.tag || + kind.definesQualifiedName || + kind.definesNewName && !shadowed.definesQualifiedName + override def exclude(kind: NameKind): TermName = { val thisKind = this.info.kind - if (thisKind.tag < kind.tag || thisKind.definesNewName) this + if (shadows(thisKind, kind)) this else if (thisKind.tag > kind.tag) rewrap(underlying.exclude(kind)) else underlying } @@ -243,7 +251,7 @@ object Names { override def is(kind: NameKind): Boolean = { val thisKind = this.info.kind thisKind == kind || - !thisKind.definesNewName && thisKind.tag > kind.tag && underlying.is(kind) + !shadows(thisKind, kind) && underlying.is(kind) } @sharable // because it's just a cache for performance From 760f631f70230215a29816dece599ea35d90608e Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Fri, 23 Jun 2017 17:39:24 +0200 Subject: [PATCH 2/4] Test --- tests/run/i2795.scala | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 tests/run/i2795.scala diff --git a/tests/run/i2795.scala b/tests/run/i2795.scala new file mode 100644 index 000000000000..154fc160df25 --- /dev/null +++ b/tests/run/i2795.scala @@ -0,0 +1,9 @@ +import reflect.ClassTag + +trait Foo[T: ClassTag]() { + def foo(x: T) = Array(x) +} +class Bar extends Foo[Int]() +object Test extends App { + (new Bar).foo(3) +} \ No newline at end of file From ca096d930dce658352bb485aa80ea80869a1580a Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Fri, 23 Jun 2017 17:40:34 +0200 Subject: [PATCH 3/4] New debug option: -Yshow-tree-ids When enabled, we print trees with their uniqueIds. This was useful in diagnosing the issue, because that way we could find out when a tree that was missing in one version was created in the other. --- compiler/src/dotty/tools/dotc/config/ScalaSettings.scala | 1 + compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala | 2 ++ 2 files changed, 3 insertions(+) diff --git a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala index a91ece4da07f..3a3cb512cc6b 100644 --- a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala +++ b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala @@ -99,6 +99,7 @@ class ScalaSettings extends Settings.SettingGroup { val YdumpSbtInc = BooleanSetting("-Ydump-sbt-inc", "For every compiled foo.scala, output the API representation and dependencies used for sbt incremental compilation in foo.inc, implies -Yforce-sbt-phases.") val YcheckAllPatmat = BooleanSetting("-Ycheck-all-patmat", "Check exhaustivity and redundancy of all pattern matching (used for testing the algorithm)") val YretainTrees = BooleanSetting("-Yretain-trees", "Retain trees for top-level classes, accessible from ClassSymbol#tree") + val YshowTreeIds = BooleanSetting("-Yshow-tree-ids", "Uniquely tag all tree nodes in debugging output.") /** Area-specific debug output */ val Yexplainlowlevel = BooleanSetting("-Yexplain-lowlevel", "When explaining type errors, show types at a lower level.") diff --git a/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala b/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala index 5b2cbc5718cb..6cfec7f16c1d 100644 --- a/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala +++ b/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala @@ -617,6 +617,8 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) { val clsStr = ""//if (tree.isType) tree.getClass.toString else "" txt = (txt ~ "@" ~ pos.toString ~ clsStr).close } + if (ctx.settings.YshowTreeIds.value) + txt = (txt ~ "#" ~ tree.uniqueId.toString).close tree match { case Block(_, _) | Template(_, _, _, _) => txt case _ => txt.close From 1a9d59457a837adbc6216e16a74627f9b64ad376 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Fri, 23 Jun 2017 18:21:35 +0200 Subject: [PATCH 4/4] Fix comment --- compiler/src/dotty/tools/dotc/core/Names.scala | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/Names.scala b/compiler/src/dotty/tools/dotc/core/Names.scala index 7dcbfdbf6128..d379653aa372 100644 --- a/compiler/src/dotty/tools/dotc/core/Names.scala +++ b/compiler/src/dotty/tools/dotc/core/Names.scala @@ -233,9 +233,7 @@ object Names { } } - /** Is it impossible that trees of kind `kind` qualify as - * derived trees of kind `shadowed`? - */ + /** Is it impossible that names of kind `kind` also qualify as names of kind `shadowed`? */ private def shadows(kind: NameKind, shadowed: NameKind): Boolean = kind.tag < shadowed.tag || kind.definesQualifiedName ||