From abb557620b8c24a351f8ab66c9eb075ed5c1314e Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 4 Jul 2018 21:44:35 +0200 Subject: [PATCH 1/2] Make vals with constant rhs have constant types In Scala-2, val's get a constant type only if they are declared `final`. This is a horrible wart, of which I was ashamed from the beginning. In Dotty, we definitely do not want to continue with this tradition. So far, we keep the constant type if the `val` is labeled `inline`. But `inline` clashes with `inline` annotations and its unclear whether we want to keep it. So I tried to see what breaks if we simply say that `val`'s without a declared type and a constant rhs get a constant type. No additional modifier needed. Turns out, a number of small tests break, but they all seem to test this specific behavior. So it should be easy to change the tests. The main benefit of the change is: - we do not have to introduce another modifier for inlined vals - it's shorter and clearer - we can always get back the old behavior using an explicit type annotation. As a next step one could try to avoid widening all singleton types, not just constant types as in this PR. I have not tried it, since it has no relevance on the question how to retire final vals. Note that the situations in Scala-2 and Dotty are different because Dotty widens at different points. So it could well be that the change is not as easy in Scala-2. --- compiler/src/dotty/tools/dotc/typer/Namer.scala | 6 +----- tests/run/i4559.scala | 2 +- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/typer/Namer.scala b/compiler/src/dotty/tools/dotc/typer/Namer.scala index 342061d48471..88867b8dca1e 100644 --- a/compiler/src/dotty/tools/dotc/typer/Namer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Namer.scala @@ -1115,15 +1115,11 @@ class Namer { typer: Typer => WildcardType } getOrElse WildcardType - // println(s"final inherited for $sym: ${inherited.toString}") !!! - // println(s"owner = ${sym.owner}, decls = ${sym.owner.info.decls.show}") - def isInline = sym.is(FinalOrInlineOrTransparent, butNot = Method | Mutable) - // Widen rhs type and eliminate `|' but keep ConstantTypes if // definition is inline (i.e. final in Scala2) and keep module singleton types // instead of widening to the underlying module class types. def widenRhs(tp: Type): Type = tp.widenTermRefExpr match { - case ctp: ConstantType if isInline => ctp + case ctp: ConstantType if !sym.is(Method | Mutable) => ctp case ref: TypeRef if ref.symbol.is(ModuleClass) => tp case _ => tp.widen.widenUnion } diff --git a/tests/run/i4559.scala b/tests/run/i4559.scala index d9b5cb2d8c8a..cae0493b42a2 100644 --- a/tests/run/i4559.scala +++ b/tests/run/i4559.scala @@ -1,6 +1,6 @@ trait A { println(s"super[A] init") - lazy val x = { println("super[A].x()"); 123 } + lazy val x: Int = { println("super[A].x()"); 123 } } class B extends A { From 76d68d60c9a447736815f7e6d7c50727b29d615c Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 4 Jul 2018 22:11:21 +0200 Subject: [PATCH 2/2] Update comment --- compiler/src/dotty/tools/dotc/typer/Namer.scala | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/typer/Namer.scala b/compiler/src/dotty/tools/dotc/typer/Namer.scala index 88867b8dca1e..6f5f70117a1b 100644 --- a/compiler/src/dotty/tools/dotc/typer/Namer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Namer.scala @@ -1115,9 +1115,8 @@ class Namer { typer: Typer => WildcardType } getOrElse WildcardType - // Widen rhs type and eliminate `|' but keep ConstantTypes if - // definition is inline (i.e. final in Scala2) and keep module singleton types - // instead of widening to the underlying module class types. + // Widen rhs type and eliminate `|' but keep ConstantTypes and module singleton + // types instead of widening to the underlying module class types. def widenRhs(tp: Type): Type = tp.widenTermRefExpr match { case ctp: ConstantType if !sym.is(Method | Mutable) => ctp case ref: TypeRef if ref.symbol.is(ModuleClass) => tp