From 1dc3279afed7355f7f33cbabc693a4d5603aaf74 Mon Sep 17 00:00:00 2001 From: Liu Fengyun Date: Fri, 1 Mar 2019 12:10:47 +0100 Subject: [PATCH 1/7] Fix #5001: add test --- .../i5001.scala} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename tests/{pending/fuzzy/AE-3b3b6b8b578c2152ae06a6647f65684de4d4605d.scala => pos/i5001.scala} (100%) diff --git a/tests/pending/fuzzy/AE-3b3b6b8b578c2152ae06a6647f65684de4d4605d.scala b/tests/pos/i5001.scala similarity index 100% rename from tests/pending/fuzzy/AE-3b3b6b8b578c2152ae06a6647f65684de4d4605d.scala rename to tests/pos/i5001.scala From 18e1a35d133583817dd5b586bac0d9040ce0155d Mon Sep 17 00:00:00 2001 From: Liu Fengyun Date: Fri, 1 Mar 2019 12:28:55 +0100 Subject: [PATCH 2/7] Fix #4820: add test The code no longer type checks after #5027. --- tests/neg/i4820.scala | 2 ++ tests/neg/i4820b.scala | 5 +++++ tests/neg/i4820c.scala | 2 ++ 3 files changed, 9 insertions(+) create mode 100644 tests/neg/i4820.scala create mode 100644 tests/neg/i4820b.scala create mode 100644 tests/neg/i4820c.scala diff --git a/tests/neg/i4820.scala b/tests/neg/i4820.scala new file mode 100644 index 000000000000..e19183b17b14 --- /dev/null +++ b/tests/neg/i4820.scala @@ -0,0 +1,2 @@ +class Foo[A] +class Bar[A] extends Foo // error diff --git a/tests/neg/i4820b.scala b/tests/neg/i4820b.scala new file mode 100644 index 000000000000..4a7b3da3fb1b --- /dev/null +++ b/tests/neg/i4820b.scala @@ -0,0 +1,5 @@ +trait SetOps[A, +C <: SetOps[A, C]] { + def concat(that: Iterable[A]): C = ??? +} + +class Set1[A] extends SetOps // error: should be SetOps[A, Set1[A]] diff --git a/tests/neg/i4820c.scala b/tests/neg/i4820c.scala new file mode 100644 index 000000000000..6956b23363b5 --- /dev/null +++ b/tests/neg/i4820c.scala @@ -0,0 +1,2 @@ +trait Foo[A] +class Bar[A] extends Foo // error \ No newline at end of file From 9a07924901d310d02f82a91241cd6acf3632ab13 Mon Sep 17 00:00:00 2001 From: Liu Fengyun Date: Fri, 1 Mar 2019 22:25:57 +0100 Subject: [PATCH 3/7] Disallow Any as base class --- compiler/src/dotty/tools/dotc/core/Definitions.scala | 6 +++--- tests/neg/i5001.scala | 1 + tests/pos/i5001.scala | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) create mode 100755 tests/neg/i5001.scala diff --git a/compiler/src/dotty/tools/dotc/core/Definitions.scala b/compiler/src/dotty/tools/dotc/core/Definitions.scala index e78e2f438978..29208283c5d7 100644 --- a/compiler/src/dotty/tools/dotc/core/Definitions.scala +++ b/compiler/src/dotty/tools/dotc/core/Definitions.scala @@ -184,8 +184,8 @@ class Definitions { arr } - private def completeClass(cls: ClassSymbol): ClassSymbol = { - ensureConstructor(cls, EmptyScope) + private def completeClass(cls: ClassSymbol, ensureCtor: Boolean = true): ClassSymbol = { + if (ensureCtor) ensureConstructor(cls, EmptyScope) if (cls.linkedClass.exists) cls.linkedClass.info = NoType cls } @@ -262,7 +262,7 @@ class Definitions { * def getClass: java.lang.Class[T] = ??? * } */ - lazy val AnyClass: ClassSymbol = completeClass(enterCompleteClassSymbol(ScalaPackageClass, tpnme.Any, Abstract, Nil)) + lazy val AnyClass: ClassSymbol = completeClass(enterCompleteClassSymbol(ScalaPackageClass, tpnme.Any, Abstract, Nil), ensureCtor = false) def AnyType: TypeRef = AnyClass.typeRef lazy val AnyValClass: ClassSymbol = completeClass(enterCompleteClassSymbol(ScalaPackageClass, tpnme.AnyVal, Abstract, List(AnyClass.typeRef))) def AnyValType: TypeRef = AnyValClass.typeRef diff --git a/tests/neg/i5001.scala b/tests/neg/i5001.scala new file mode 100755 index 000000000000..80fe724c14d4 --- /dev/null +++ b/tests/neg/i5001.scala @@ -0,0 +1 @@ +case class i1() extends Any // error: Any does not have a constructor diff --git a/tests/pos/i5001.scala b/tests/pos/i5001.scala index adc3bbcea6a6..6221ab083e9b 100755 --- a/tests/pos/i5001.scala +++ b/tests/pos/i5001.scala @@ -1 +1 @@ -case class i1() extends Any +case class i1() extends AnyRef From f09cae9dc8db5d02bc22d4afe94a45aa9a0e47a9 Mon Sep 17 00:00:00 2001 From: Liu Fengyun Date: Fri, 1 Mar 2019 23:55:10 +0100 Subject: [PATCH 4/7] Any does not qualify for parent class --- compiler/src/dotty/tools/dotc/typer/Typer.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index c5c98812bf53..696ba088bb9f 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -515,7 +515,7 @@ class Typer extends Namer case templ: untpd.Template => import untpd._ var templ1 = templ - def isEligible(tp: Type) = tp.exists && !tp.typeSymbol.is(Final) + def isEligible(tp: Type) = tp.exists && !tp.typeSymbol.is(Final) && tp.classSymbol != defn.AnyClass if (templ1.parents.isEmpty && isFullyDefined(pt, ForceDegree.noBottom) && isEligible(pt.underlyingClassRef(refinementOK = false))) From d76ccc12d69e4a1e6b5dd593932b8a8764a5dedd Mon Sep 17 00:00:00 2001 From: Liu Fengyun Date: Mon, 4 Mar 2019 11:01:49 +0100 Subject: [PATCH 5/7] Fix tasty decompile --- library/src/scala/tasty/reflect/Printers.scala | 1 + tests/pos/i0306.decompiled | 4 +++- tests/pos/simpleRefinement.decompiled | 3 ++- tests/run/t4300.decompiled | 3 ++- 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/library/src/scala/tasty/reflect/Printers.scala b/library/src/scala/tasty/reflect/Printers.scala index ce3128c8b07b..b4f087b9e367 100644 --- a/library/src/scala/tasty/reflect/Printers.scala +++ b/library/src/scala/tasty/reflect/Printers.scala @@ -1003,6 +1003,7 @@ trait Printers case Term.Select(qual, _) => rec(qual) case Term.Apply(fn, _) => rec(fn) case Term.TypeApply(fn, _) => rec(fn) + case Term.Typed(_, _) => this += doubleLineBreak() case _ => this += lineBreak() } next match { diff --git a/tests/pos/i0306.decompiled b/tests/pos/i0306.decompiled index 957bdd2c10c7..bfc2f03c76ab 100644 --- a/tests/pos/i0306.decompiled +++ b/tests/pos/i0306.decompiled @@ -4,10 +4,12 @@ object bar { val y: scala.collection.Seq[_ >: scala.Nothing <: scala.Any] = bar.x match { case x: bar.C[u] => def xx: u = xx + ((xx: u): scala.collection.Seq[_ >: scala.Nothing <: scala.Any]) } val z: java.lang.String = { def xx: scala.Predef.String = xx + (xx: java.lang.String) } -} +} \ No newline at end of file diff --git a/tests/pos/simpleRefinement.decompiled b/tests/pos/simpleRefinement.decompiled index 118eac58a535..1183bec1dba4 100644 --- a/tests/pos/simpleRefinement.decompiled +++ b/tests/pos/simpleRefinement.decompiled @@ -32,6 +32,7 @@ class Foo() { def w[T]: scala.Predef.String = "a" def w2[T](a: scala.Null)(b: scala.Null): scala.Null = null } + (new $anon(): Bar { type S >: scala.Int <: scala.Int type T >: scala.Function1[scala.Int, scala.Int] <: scala.Function1[scala.Int, scala.Int] @@ -44,4 +45,4 @@ class Foo() { def w2[T >: scala.Nothing <: scala.Any](a: scala.Null)(b: scala.Null): scala.Null }) } -} +} \ No newline at end of file diff --git a/tests/run/t4300.decompiled b/tests/run/t4300.decompiled index 9cb4932bcc7f..af603042de1a 100644 --- a/tests/run/t4300.decompiled +++ b/tests/run/t4300.decompiled @@ -17,9 +17,10 @@ object Test { { final class $anon() extends b.C + (new $anon(): b.C) }.c() b.g() b.h() } -} +} \ No newline at end of file From 0f50d77c2dbb78e7a99f3e0f65e27ee6736f63e2 Mon Sep 17 00:00:00 2001 From: Liu Fengyun Date: Mon, 4 Mar 2019 13:45:16 +0100 Subject: [PATCH 6/7] Add blank line before (x: T) in decompilation --- tests/run-with-compiler/i3876-c.check | 1 + tests/run-with-compiler/quote-nested-3.check | 1 + tests/run-with-compiler/quote-nested-4.check | 1 + tests/run-with-compiler/quote-owners-2.check | 3 +++ tests/run-with-compiler/quote-owners.check | 1 + tests/run-with-compiler/quote-unrolled-foreach.check | 2 ++ tests/run-with-compiler/shonan-hmm-simple.check | 1 + tests/run-with-compiler/shonan-hmm.check | 4 ++++ 8 files changed, 14 insertions(+) diff --git a/tests/run-with-compiler/i3876-c.check b/tests/run-with-compiler/i3876-c.check index 54c77aeb94e6..bd419b41bf11 100644 --- a/tests/run-with-compiler/i3876-c.check +++ b/tests/run-with-compiler/i3876-c.check @@ -4,6 +4,7 @@ val f: scala.Function1[scala.Int, scala.Int] { def apply(x: scala.Int): scala.Int } = ((x: scala.Int) => x.+(x)) + (f: scala.Function1[scala.Int, scala.Int] { def apply(x: scala.Int): scala.Int }).apply(x$1) diff --git a/tests/run-with-compiler/quote-nested-3.check b/tests/run-with-compiler/quote-nested-3.check index a441ab9cc3e3..63bdda5c6c4c 100644 --- a/tests/run-with-compiler/quote-nested-3.check +++ b/tests/run-with-compiler/quote-nested-3.check @@ -2,5 +2,6 @@ type T = scala.Predef.String val x: java.lang.String = "foo" val z: T = x + (x: java.lang.String) } diff --git a/tests/run-with-compiler/quote-nested-4.check b/tests/run-with-compiler/quote-nested-4.check index 39c62c260cb5..46beeacd5b66 100644 --- a/tests/run-with-compiler/quote-nested-4.check +++ b/tests/run-with-compiler/quote-nested-4.check @@ -1,4 +1,5 @@ { val t: scala.quoted.Type[scala.Predef.String] = scala.quoted.Type.apply[scala.Predef.String] + (t: scala.quoted.Type[scala.Predef.String]) } diff --git a/tests/run-with-compiler/quote-owners-2.check b/tests/run-with-compiler/quote-owners-2.check index 651841382003..1b03b435c991 100644 --- a/tests/run-with-compiler/quote-owners-2.check +++ b/tests/run-with-compiler/quote-owners-2.check @@ -4,9 +4,12 @@ val a: immutable.List[scala.Int] = { type T = scala.List[scala.Int] val b: T = scala.Nil.::[scala.Int](3) + (b: collection.immutable.List[scala.Int]) } + (a.head: scala.Int) } + (ff: scala.Int) } diff --git a/tests/run-with-compiler/quote-owners.check b/tests/run-with-compiler/quote-owners.check index db594bbb1c80..99aa010dd142 100644 --- a/tests/run-with-compiler/quote-owners.check +++ b/tests/run-with-compiler/quote-owners.check @@ -4,5 +4,6 @@ val a: scala.Int = 9 a.+(0) } + (ff: scala.Int) } diff --git a/tests/run-with-compiler/quote-unrolled-foreach.check b/tests/run-with-compiler/quote-unrolled-foreach.check index a97a6f1d93fe..3e923884848e 100644 --- a/tests/run-with-compiler/quote-unrolled-foreach.check +++ b/tests/run-with-compiler/quote-unrolled-foreach.check @@ -69,6 +69,7 @@ array.update(1, 2) array.update(2, 3) array.update(3, 4) + (array: scala.Array[scala.Int]) } @@ -79,6 +80,7 @@ array.update(1, 3) array.update(2, 4) array.update(3, 5) + (array: scala.Array[scala.Int]) } val size: scala.Int = arr1.length diff --git a/tests/run-with-compiler/shonan-hmm-simple.check b/tests/run-with-compiler/shonan-hmm-simple.check index 420f66c28728..da437646482d 100644 --- a/tests/run-with-compiler/shonan-hmm-simple.check +++ b/tests/run-with-compiler/shonan-hmm-simple.check @@ -13,6 +13,7 @@ Complex(4,3) sum = sum.+(arr1.apply(i).*(arr2.apply(i))) i = i.+(1) } + (sum: scala.Int) }) 10 diff --git a/tests/run-with-compiler/shonan-hmm.check b/tests/run-with-compiler/shonan-hmm.check index 29b8c12e99ec..f39b702f17ce 100644 --- a/tests/run-with-compiler/shonan-hmm.check +++ b/tests/run-with-compiler/shonan-hmm.check @@ -25,6 +25,7 @@ List(25, 30, 20, 43, 44) sum = sum.+(v.apply(i$2).*(a.apply(i).apply(i$2))) i$2 = i$2.+(1) } + (sum: scala.Int) }) i = i.+(1) @@ -232,6 +233,7 @@ List(25, 30, 20, 43, 44) sum = sum.+(v.apply(i).*(arr.apply(3).apply(i))) i = i.+(1) } + (sum: scala.Int) }) vout.update(4, v.apply(2).*(3).+(v.apply(4).*(7))) @@ -261,6 +263,7 @@ List(25, 30, 20, 43, 44) }.apply(i))) i = i.+(1) } + (sum: scala.Int) }) vout.update(4, v.apply(2).*(3).+(v.apply(4).*(7))) @@ -291,6 +294,7 @@ List(25, 30, 20, 43, 44) sum = sum.+(v.apply(i).*(row.apply(i))) i = i.+(1) } + (sum: scala.Int) }) vout.update(4, v.apply(2).*(3).+(v.apply(4).*(7))) From 3224f33e3947b5d6d9f56179e406bbf9b6e1dd2e Mon Sep 17 00:00:00 2001 From: Liu Fengyun Date: Mon, 4 Mar 2019 17:26:13 +0100 Subject: [PATCH 7/7] Fix parent class for anonymous class `Any` can be parent class of traits, in that case we should choose `AnyRef`. --- compiler/src/dotty/tools/dotc/ast/tpd.scala | 5 ++++- compiler/src/dotty/tools/dotc/typer/Typer.scala | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/ast/tpd.scala b/compiler/src/dotty/tools/dotc/ast/tpd.scala index 8b6fcfe03dad..f36b6d8ec42b 100644 --- a/compiler/src/dotty/tools/dotc/ast/tpd.scala +++ b/compiler/src/dotty/tools/dotc/ast/tpd.scala @@ -308,7 +308,10 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { def AnonClass(parents: List[Type], fns: List[TermSymbol], methNames: List[TermName])(implicit ctx: Context): Block = { val owner = fns.head.owner val parents1 = - if (parents.head.classSymbol.is(Trait)) parents.head.parents.head :: parents + if (parents.head.classSymbol.is(Trait)) { + val head = parents.head.parents.head + if (head.isRef(defn.AnyClass)) defn.AnyRefType :: parents else head :: parents + } else parents val cls = ctx.newNormalizedClassSymbol(owner, tpnme.ANON_CLASS, Synthetic | Final, parents1, coord = fns.map(_.span).reduceLeft(_ union _)) diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 696ba088bb9f..7a099b501159 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -515,7 +515,7 @@ class Typer extends Namer case templ: untpd.Template => import untpd._ var templ1 = templ - def isEligible(tp: Type) = tp.exists && !tp.typeSymbol.is(Final) && tp.classSymbol != defn.AnyClass + def isEligible(tp: Type) = tp.exists && !tp.typeSymbol.is(Final) && !tp.isRef(defn.AnyClass) if (templ1.parents.isEmpty && isFullyDefined(pt, ForceDegree.noBottom) && isEligible(pt.underlyingClassRef(refinementOK = false)))