From fada1ef6b315326ac0329d9e78951cfc95ad0eb0 Mon Sep 17 00:00:00 2001 From: Adriaan Moors Date: Thu, 16 May 2013 14:58:09 -0700 Subject: SI-6815 untangle isStable and hasVolatileType `Symbol::isStable` is now independent of `Symbol::hasVolatileType`, so that we can allow stable identifiers that are volatile in ident patterns. This split is validated by SI-6815 and the old logic in RefChecks, which seems to assume this independence, and thus I don't think ever worked: ``` if (member.isStable && !otherTp.isVolatile) { if (memberTp.isVolatile) overrideError("has a volatile type; cannot override a member with non-volatile type") ``` Introduces `admitsTypeSelection` and `isStableIdentifierPattern` in treeInfo, and uses them instead of duplicating that logic all over the place. Since volatility only matters in the context of type application, `isStableIdentifierPattern` is used to check patterns (resulting in `==` checks) and imports. --- test/files/neg/t6815.check | 5 +++++ test/files/neg/t6815.scala | 17 +++++++++++++++++ test/files/neg/volatile_no_override.check | 5 +++++ test/files/neg/volatile_no_override.scala | 14 ++++++++++++++ test/files/pos/t6815.scala | 17 +++++++++++++++++ test/files/pos/t6815_import.scala | 16 ++++++++++++++++ 6 files changed, 74 insertions(+) create mode 100644 test/files/neg/t6815.check create mode 100644 test/files/neg/t6815.scala create mode 100644 test/files/neg/volatile_no_override.check create mode 100644 test/files/neg/volatile_no_override.scala create mode 100644 test/files/pos/t6815.scala create mode 100644 test/files/pos/t6815_import.scala (limited to 'test') diff --git a/test/files/neg/t6815.check b/test/files/neg/t6815.check new file mode 100644 index 0000000000..fae3819be1 --- /dev/null +++ b/test/files/neg/t6815.check @@ -0,0 +1,5 @@ +t6815.scala:15: error: stable identifier required, but Test.this.u.emptyValDef found. + Note that value emptyValDef is not stable because its type, Test.u.ValDef, is volatile. + case _: u.emptyValDef.T => // and, unlike in pos/t6185.scala, we shouldn't allow this. + ^ +one error found diff --git a/test/files/neg/t6815.scala b/test/files/neg/t6815.scala new file mode 100644 index 0000000000..ff973a7437 --- /dev/null +++ b/test/files/neg/t6815.scala @@ -0,0 +1,17 @@ +trait U { + trait ValOrDefDefApi { + def name: Any + } + type ValOrDefDef <: ValOrDefDefApi + type ValDef <: ValOrDefDef with ValDefApi { type T } + trait ValDefApi extends ValOrDefDefApi { this: ValDef => } + val emptyValDef: ValDef // the result type is volatile +} + +object Test { + val u: U = ??? + + (null: Any) match { + case _: u.emptyValDef.T => // and, unlike in pos/t6185.scala, we shouldn't allow this. + } +} diff --git a/test/files/neg/volatile_no_override.check b/test/files/neg/volatile_no_override.check new file mode 100644 index 0000000000..a9a60ab697 --- /dev/null +++ b/test/files/neg/volatile_no_override.check @@ -0,0 +1,5 @@ +volatile_no_override.scala:13: error: overriding value x in class A of type Volatile.this.D; + value x has a volatile type; cannot override a member with non-volatile type + val x: A with D = null + ^ +one error found diff --git a/test/files/neg/volatile_no_override.scala b/test/files/neg/volatile_no_override.scala new file mode 100644 index 0000000000..9fad082a90 --- /dev/null +++ b/test/files/neg/volatile_no_override.scala @@ -0,0 +1,14 @@ +class B +class C(x: String) extends B + +abstract class A { + class D { type T >: C <: B } + val x: D + var y: x.T = new C("abc") +} + +class Volatile extends A { + type A >: Null + // test (1.4), pt 2 in RefChecks + val x: A with D = null +} diff --git a/test/files/pos/t6815.scala b/test/files/pos/t6815.scala new file mode 100644 index 0000000000..9244b3d353 --- /dev/null +++ b/test/files/pos/t6815.scala @@ -0,0 +1,17 @@ +trait U { + trait ValOrDefDefApi { + def name: Any + } + type ValOrDefDef <: ValOrDefDefApi + type ValDef <: ValOrDefDef with ValDefApi + trait ValDefApi extends ValOrDefDefApi { this: ValDef => } + val emptyValDef: ValDef // the result type is volatile +} + +object Test { + val u: U = ??? + + u.emptyValDef match { + case u.emptyValDef => // but we shouldn't let that stop us from treating it as a stable identifier pattern. + } +} diff --git a/test/files/pos/t6815_import.scala b/test/files/pos/t6815_import.scala new file mode 100644 index 0000000000..56f4358d59 --- /dev/null +++ b/test/files/pos/t6815_import.scala @@ -0,0 +1,16 @@ +trait U { + trait ValOrDefDefApi { + def name: Any + } + type ValOrDefDef <: ValOrDefDefApi + type ValDef <: ValOrDefDef with ValDefApi + trait ValDefApi extends ValOrDefDefApi { this: ValDef => } + val emptyValDef: ValDef // the result type is volatile +} + +object Test { + val u: U = ??? + + // but we shouldn't let that stop us from treating it as a stable identifier for import + import u.emptyValDef.name +} -- cgit v1.2.3