-
Notifications
You must be signed in to change notification settings - Fork 3.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
More accurate outer checks in patterns
Avoids eliding outer checks that matter (run/t11534b.scala) and avoids emitting checks that don't (pos/t11534.scala) which avoids compiler warnings when the tested class doesn't have an outer field. The latter stops the annoying unchecked warning that appeared since a recent refactoring made `TermName` a final class.
- Loading branch information
Showing
5 changed files
with
243 additions
and
18 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
// scalac: -Werror | ||
object Test1 { | ||
val g: scala.tools.nsc.Global = ??? | ||
import g._ | ||
def test(sym: Symbol) = sym.name match { | ||
case _: TermName => | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
object Test { | ||
case class O(i: Int) { | ||
class A | ||
class B extends A { | ||
def bOuter = O.this | ||
} | ||
trait C { | ||
def cOuter = O.this | ||
} | ||
class D extends o2.B with C | ||
} | ||
val o1 = new O(1); | ||
val o2 = new O(2); | ||
def pat1(a: Test.o1.C) = a match { | ||
case b: Test.o1.B => | ||
assert(b.bOuter eq Test.o1, | ||
s"expected ${o1} as outer of value conforming to pattern `b: Test.o1.B`, but got ${b.bOuter}") | ||
case _ => | ||
|
||
} | ||
def main(args: Array[String]): Unit = { | ||
pat1(new o1.D) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
// scalac: -unchecked | ||
import scala.util.Try | ||
|
||
object Test { | ||
class O(val i: Int) { | ||
class A { | ||
val aOuter = i | ||
} | ||
|
||
class B1 extends A { | ||
val b1Outer = i | ||
} | ||
} | ||
class M(i: Int) extends O(i) { | ||
class B2 extends m2.A { | ||
val b2Outer = i | ||
} | ||
|
||
def pat1(a: M.this.A) = a match { | ||
case b: M.this.B1 => // can elide outer check, (a : m1.A) && (a : O#B1) implies (a : m1.B1) | ||
assertOuter(m1.i, b.b1Outer) | ||
true | ||
case _ => | ||
false | ||
} | ||
def pat2(a: m2.A) = a match { | ||
case b: M.this.B2 => // needs runtime outer check | ||
assertOuter(m1.i, b.b2Outer) | ||
true | ||
case _ => | ||
false | ||
} | ||
def pat3(a: M.this.B1) = a match { | ||
case b: M.this.A => // can elide outer check, (a : m1.B1) && (a : O#A) implies (a : m1.B1) | ||
assertOuter(m1.i, b.aOuter) | ||
true | ||
case _ => | ||
false | ||
} | ||
def pat4(a: M.this.B2) = a match { | ||
case b: m2.A => // can elide outer check, (a : m1.B2) implies (a : m2.A) | ||
assertOuter(m2.i, b.aOuter) | ||
true | ||
case _ => | ||
false | ||
} | ||
} | ||
|
||
val m1 = new M(1); | ||
val m2 = new M(2); | ||
|
||
def pat1(a: m1.A) = a match { | ||
case b: m1.B1 => // can elide outer check, (a : m1.A) && (a : O#B1) implies (a : m1.B1) | ||
assertOuter(m1.i, b.b1Outer) | ||
true | ||
case _ => | ||
false | ||
} | ||
def pat2(a: m2.A) = a match { | ||
case b: m1.B2 => // needs runtime outer check | ||
assertOuter(m1.i, b.b2Outer) | ||
true | ||
case _ => | ||
false | ||
} | ||
def pat3(a: m1.B1) = a match { | ||
case b: m1.A => // can elide outer check, (a : m1.B1) && (a : O#A) implies (a : m1.B1) | ||
assertOuter(m1.i, b.aOuter) | ||
true | ||
case _ => | ||
false | ||
} | ||
def pat4(a: m1.B2) = a match { | ||
case b: m2.A => // can elide outer check, (a : m1.B2) implies (a : m2.A) | ||
assertOuter(m2.i, b.aOuter) | ||
true | ||
case _ => | ||
false | ||
} | ||
|
||
def pat5(a: M#B2) = a match { | ||
case b: m2.A => // can elide outer check, (a : A#B2) implies (a : m2.A) | ||
assertOuter(m2.i, b.aOuter) | ||
true | ||
case _ => | ||
false | ||
} | ||
def assertOuter(expected: Int, actual: Int): Unit = { | ||
if (expected != actual) throw WrongOuter(expected, actual) | ||
} | ||
case class WrongOuter(expected: Int, actual: Int) extends RuntimeException(s"expected: $expected, actual: $actual") | ||
|
||
def main(args: Array[String]): Unit = { | ||
assert(pat1(new m1.B1)) | ||
assert(m1.pat1(new m1.B1)) | ||
assert(Try(pat1((new m2.B1).asInstanceOf[m1.B1])).failed.get == WrongOuter(m1.i, m2.i)) | ||
assert(Try(m1.pat1((new m2.B1).asInstanceOf[m1.B1])).failed.get == WrongOuter(m1.i, m2.i)) | ||
|
||
assert(!pat2(new m2.B2)) | ||
assert(!m1.pat2(new m2.B2)) | ||
assert(pat2(new m1.B2)) | ||
assert(m1.pat2(new m1.B2)) | ||
|
||
assert(pat3(new m1.B1)) | ||
assert(m1.pat3(new m1.B1)) | ||
assert(Try(pat3((new m2.B1).asInstanceOf[m1.B1])).failed.get == WrongOuter(m1.i, m2.i)) | ||
assert(Try(m1.pat3((new m2.B1).asInstanceOf[m1.B1])).failed.get == WrongOuter(m1.i, m2.i)) | ||
|
||
assert(pat4(new m1.B2)) | ||
assert(m1.pat4(new m1.B2)) | ||
assert(pat4((new m2.B2).asInstanceOf[m1.B2])) | ||
assert(m1.pat4((new m2.B2).asInstanceOf[m1.B2])) | ||
|
||
assert(pat5(new m1.B2)) | ||
assert(pat5(new m2.B2)) | ||
} | ||
} |