aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2014-04-03 18:12:53 +0200
committerDmitry Petrashko <dmitry.petrashko@gmail.com>2014-04-08 17:02:29 +0200
commitc6af272d6d68c708cb87b12f25e61dd0a9717f09 (patch)
tree872d76c6f0c2c63365d8f40e2dc6ad8429524c01
parentd079c0291289ad9f6517b0b929c4f03ef6b9f082 (diff)
downloaddotty-c6af272d6d68c708cb87b12f25e61dd0a9717f09.tar.gz
dotty-c6af272d6d68c708cb87b12f25e61dd0a9717f09.tar.bz2
dotty-c6af272d6d68c708cb87b12f25e61dd0a9717f09.zip
Option for testing for double bindings
A double binding is if a named type gets assigned two denotations in the same period. This is a side-effect and also a race condition, so it's very bad. I am trying to eliminate all causes of this. But one cause which will likely remain are double defitions in a prgram, if a user writes class C { val x: Int val x: Int } Then it's really hard to avoid setting two meanings of C.this.x! That's why the testing against double bindings is enabled by a -YnoDoubleBindings option. The understanding is that -YnoDoubleBindings should be set only if there are no double def errors anticipated. Otherwise the program might fail with an assertion error before the double def error is reported.
-rw-r--r--src/dotty/tools/dotc/config/ScalaSettings.scala1
-rw-r--r--src/dotty/tools/dotc/core/Types.scala18
-rw-r--r--test/dotc/tests.scala4
3 files changed, 16 insertions, 7 deletions
diff --git a/src/dotty/tools/dotc/config/ScalaSettings.scala b/src/dotty/tools/dotc/config/ScalaSettings.scala
index 144e146c1..aab2942bd 100644
--- a/src/dotty/tools/dotc/config/ScalaSettings.scala
+++ b/src/dotty/tools/dotc/config/ScalaSettings.scala
@@ -163,6 +163,7 @@ class ScalaSettings extends Settings.SettingGroup {
val Ytyperdebug = BooleanSetting("-Ytyper-debug", "Trace all type assignments.")
val Ypatmatdebug = BooleanSetting("-Ypatmat-debug", "Trace pattern matching translation.")
val Yexplainlowlevel = BooleanSetting("-Yexplainlowlevel", "When explaining type errors, show types at a lower level.")
+ val YnoDoubleBindings = BooleanSetting("-YnoDoubleBindings", "Assert no namedtype is bound twice (should be enabled only if program is error-free).")
val optimise = BooleanSetting("-optimise", "Generates faster bytecode by applying optimisations to the program") withAbbreviation "-optimize"
diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala
index 7561abb10..1dba728bb 100644
--- a/src/dotty/tools/dotc/core/Types.scala
+++ b/src/dotty/tools/dotc/core/Types.scala
@@ -1078,8 +1078,10 @@ object Types {
this
}
- private[dotc] final def setDenot(denot: Denotation): Unit = {
- if (Config.checkTermRefs) checkSymAssign(denot.symbol)
+ private[dotc] final def setDenot(denot: Denotation)(implicit ctx: Context): Unit = {
+ if (Config.checkTermRefs)
+ if (ctx.settings.YnoDoubleBindings.value)
+ checkSymAssign(denot.symbol)
lastDenotation = denot
lastSymbol = denot.symbol
}
@@ -1092,8 +1094,14 @@ object Types {
this
}
- private[dotc] final def setSym(sym: Symbol): Unit = {
- if (Config.checkTermRefs) checkSymAssign(sym)
+ private[dotc] final def setSym(sym: Symbol)(implicit ctx: Context): Unit = {
+ if (Config.checkTermRefs)
+ if (ctx.settings.YnoDoubleBindings.value)
+ checkSymAssign(sym)
+ uncheckedSetSym(sym)
+ }
+
+ private[dotc] final def uncheckedSetSym(sym: Symbol): Unit = {
lastDenotation = null
lastSymbol = sym
checkedPeriod = Nowhere
@@ -1238,7 +1246,7 @@ object Types {
trait WithNonMemberSym extends NamedType {
def fixedSym: Symbol
assert(fixedSym ne NoSymbol)
- setSym(fixedSym)
+ uncheckedSetSym(fixedSym)
override def withDenot(denot: Denotation)(implicit ctx: Context): ThisType = {
assert(denot.symbol eq fixedSym)
diff --git a/test/dotc/tests.scala b/test/dotc/tests.scala
index 9665ec206..3228c3474 100644
--- a/test/dotc/tests.scala
+++ b/test/dotc/tests.scala
@@ -14,7 +14,7 @@ class tests extends CompilerTest {
// "-Yshow-suppressed-errors",
"-pagewidth", "160"
)
- val twice = List("#runs", "2")
+ val twice = List("#runs", "2", "-YnoDoubleBindings")
val doErase = List("-Ystop-before:terminal")
val posDir = "./tests/pos/"
@@ -55,7 +55,7 @@ class tests extends CompilerTest {
@Test def neg_typedapply() = compileFile(negDir, "typedapply", xerrors = 4)
@Test def neg_typedidents() = compileFile(negDir, "typedIdents", xerrors = 2)
@Test def neg_assignments() = compileFile(negDir, "assignments", xerrors = 3)
- @Test def neg_typers() = compileFile(negDir, "typers", xerrors = 10)
+ @Test def neg_typers() = compileFile(negDir, "typers", xerrors = 13)
@Test def neg_privates() = compileFile(negDir, "privates", xerrors = 2)
@Test def neg_rootImports = compileFile(negDir, "rootImplicits", xerrors = 2)
@Test def neg_templateParents() = compileFile(negDir, "templateParents", xerrors = 3)