From 75da0358fd7866f3dccdfcf4fbeae9af8ccc69f3 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Mon, 30 May 2016 09:20:21 +0200 Subject: Fix #657: Add scala.Dynamic support. --- tests/neg/dynamicApplyDynamicTest1.scala | 7 +++++++ tests/neg/dynamicApplyDynamicTest2.scala | 7 +++++++ tests/neg/dynamicApplyDynamicTest3.scala | 7 +++++++ tests/neg/dynamicApplyDynamicTest4.scala | 10 ++++++++++ tests/neg/dynamicApplyDynamicTest5.scala | 9 +++++++++ tests/neg/dynamicApplyDynamicTest6.scala | 9 +++++++++ tests/neg/dynamicApplyDynamicTest7.scala | 9 +++++++++ tests/neg/dynamicApplyDynamicTest8.scala | 9 +++++++++ tests/neg/dynamicApplyDynamicTest9.scala | 9 +++++++++ tests/neg/dynamicApplyNamedDynamicTest1.scala | 7 +++++++ tests/neg/dynamicApplyNamedDynamicTest2.scala | 10 ++++++++++ tests/neg/dynamicApplyNamedDynamicTest3.scala | 7 +++++++ tests/neg/dynamicApplyNamedDynamicTest4.scala | 7 +++++++ tests/neg/dynamicApplyNamedDynamicTest5.scala | 9 +++++++++ tests/neg/dynamicApplyNamedDynamicTest6.scala | 9 +++++++++ tests/neg/dynamicApplyNamedDynamicTest7.scala | 9 +++++++++ tests/neg/dynamicApplyNamedDynamicTest8.scala | 9 +++++++++ tests/neg/dynamicDynamicImplicitsTest1.scala | 13 +++++++++++++ tests/neg/dynamicDynamicImplicitsTest2.scala | 13 +++++++++++++ tests/neg/dynamicDynamicImplicitsTest3.scala | 13 +++++++++++++ tests/neg/dynamicSelectDynamicTest1.scala | 10 ++++++++++ tests/neg/dynamicSelectDynamicTest2.scala | 7 +++++++ tests/neg/dynamicSelectDynamicTest3.scala | 7 +++++++ tests/neg/dynamicSelectDynamicTest4.scala | 11 +++++++++++ tests/neg/dynamicSelectDynamicTest5.scala | 7 +++++++ tests/neg/dynamicSelectDynamicTest6.scala | 11 +++++++++++ tests/neg/dynamicSelectDynamicTest7.scala | 9 +++++++++ tests/neg/dynamicUpdateDynamicTest1.scala | 7 +++++++ tests/neg/dynamicUpdateDynamicTest2.scala | 9 +++++++++ tests/neg/dynamicUpdateDynamicTest3.scala | 9 +++++++++ tests/neg/dynamicUpdateDynamicTest4.scala | 9 +++++++++ 31 files changed, 278 insertions(+) create mode 100644 tests/neg/dynamicApplyDynamicTest1.scala create mode 100644 tests/neg/dynamicApplyDynamicTest2.scala create mode 100644 tests/neg/dynamicApplyDynamicTest3.scala create mode 100644 tests/neg/dynamicApplyDynamicTest4.scala create mode 100644 tests/neg/dynamicApplyDynamicTest5.scala create mode 100644 tests/neg/dynamicApplyDynamicTest6.scala create mode 100644 tests/neg/dynamicApplyDynamicTest7.scala create mode 100644 tests/neg/dynamicApplyDynamicTest8.scala create mode 100644 tests/neg/dynamicApplyDynamicTest9.scala create mode 100644 tests/neg/dynamicApplyNamedDynamicTest1.scala create mode 100644 tests/neg/dynamicApplyNamedDynamicTest2.scala create mode 100644 tests/neg/dynamicApplyNamedDynamicTest3.scala create mode 100644 tests/neg/dynamicApplyNamedDynamicTest4.scala create mode 100644 tests/neg/dynamicApplyNamedDynamicTest5.scala create mode 100644 tests/neg/dynamicApplyNamedDynamicTest6.scala create mode 100644 tests/neg/dynamicApplyNamedDynamicTest7.scala create mode 100644 tests/neg/dynamicApplyNamedDynamicTest8.scala create mode 100644 tests/neg/dynamicDynamicImplicitsTest1.scala create mode 100644 tests/neg/dynamicDynamicImplicitsTest2.scala create mode 100644 tests/neg/dynamicDynamicImplicitsTest3.scala create mode 100644 tests/neg/dynamicSelectDynamicTest1.scala create mode 100644 tests/neg/dynamicSelectDynamicTest2.scala create mode 100644 tests/neg/dynamicSelectDynamicTest3.scala create mode 100644 tests/neg/dynamicSelectDynamicTest4.scala create mode 100644 tests/neg/dynamicSelectDynamicTest5.scala create mode 100644 tests/neg/dynamicSelectDynamicTest6.scala create mode 100644 tests/neg/dynamicSelectDynamicTest7.scala create mode 100644 tests/neg/dynamicUpdateDynamicTest1.scala create mode 100644 tests/neg/dynamicUpdateDynamicTest2.scala create mode 100644 tests/neg/dynamicUpdateDynamicTest3.scala create mode 100644 tests/neg/dynamicUpdateDynamicTest4.scala (limited to 'tests/neg') diff --git a/tests/neg/dynamicApplyDynamicTest1.scala b/tests/neg/dynamicApplyDynamicTest1.scala new file mode 100644 index 000000000..90f4493eb --- /dev/null +++ b/tests/neg/dynamicApplyDynamicTest1.scala @@ -0,0 +1,7 @@ +import scala.language.dynamics + +class Foo extends scala.Dynamic + +object DynamicTest { + new Foo().bazApply() // error +} diff --git a/tests/neg/dynamicApplyDynamicTest2.scala b/tests/neg/dynamicApplyDynamicTest2.scala new file mode 100644 index 000000000..aa0e44405 --- /dev/null +++ b/tests/neg/dynamicApplyDynamicTest2.scala @@ -0,0 +1,7 @@ +import scala.language.dynamics + +class Foo extends scala.Dynamic + +object DynamicTest { + new Foo().bazApply("abc", 1) // error +} diff --git a/tests/neg/dynamicApplyDynamicTest3.scala b/tests/neg/dynamicApplyDynamicTest3.scala new file mode 100644 index 000000000..61d3c9677 --- /dev/null +++ b/tests/neg/dynamicApplyDynamicTest3.scala @@ -0,0 +1,7 @@ +import scala.language.dynamics + +class Foo extends scala.Dynamic + +object DynamicTest { + new Foo().bazApply _ // error // error +} diff --git a/tests/neg/dynamicApplyDynamicTest4.scala b/tests/neg/dynamicApplyDynamicTest4.scala new file mode 100644 index 000000000..4573bd08d --- /dev/null +++ b/tests/neg/dynamicApplyDynamicTest4.scala @@ -0,0 +1,10 @@ +import scala.language.dynamics + +class Foo extends scala.Dynamic { + def selectDynamic(name: String): String = ??? + def applyDynamicNamed(name: String)(args: Any*): String = ??? +} + +object DynamicTest { + new Foo().bazApply() // error +} diff --git a/tests/neg/dynamicApplyDynamicTest5.scala b/tests/neg/dynamicApplyDynamicTest5.scala new file mode 100644 index 000000000..d1d9cdd69 --- /dev/null +++ b/tests/neg/dynamicApplyDynamicTest5.scala @@ -0,0 +1,9 @@ +import scala.language.dynamics + +class Foo extends scala.Dynamic { + def applyDynamic(name: String)(args: String*): String = ??? +} + +object DynamicTest { + new Foo().bazApply(1, 2, 3) // error // error // error +} diff --git a/tests/neg/dynamicApplyDynamicTest6.scala b/tests/neg/dynamicApplyDynamicTest6.scala new file mode 100644 index 000000000..865858ff3 --- /dev/null +++ b/tests/neg/dynamicApplyDynamicTest6.scala @@ -0,0 +1,9 @@ +import scala.language.dynamics + +class Foo extends scala.Dynamic { + def applyDynamic(name: String)(args: String*): String = ??? +} + +object DynamicTest { + def test: Int = new Foo().bazApply() // error +} diff --git a/tests/neg/dynamicApplyDynamicTest7.scala b/tests/neg/dynamicApplyDynamicTest7.scala new file mode 100644 index 000000000..7985dd09e --- /dev/null +++ b/tests/neg/dynamicApplyDynamicTest7.scala @@ -0,0 +1,9 @@ +import scala.language.dynamics + +class Foo extends scala.Dynamic { + def applyDynamic(name: Int)(args: String*): String = ??? +} + +object DynamicTest { + def test: String = new Foo().bazApply() // error +} diff --git a/tests/neg/dynamicApplyDynamicTest8.scala b/tests/neg/dynamicApplyDynamicTest8.scala new file mode 100644 index 000000000..ee8192d76 --- /dev/null +++ b/tests/neg/dynamicApplyDynamicTest8.scala @@ -0,0 +1,9 @@ +import scala.language.dynamics + +class Foo extends scala.Dynamic { + def applyDynamicNamed(name: String)(args: (String, Int)*): String = ??? +} + +object DynamicTest { + def test: String = new Foo().bazApply("1" -> 2) // error +} diff --git a/tests/neg/dynamicApplyDynamicTest9.scala b/tests/neg/dynamicApplyDynamicTest9.scala new file mode 100644 index 000000000..bc4f94d5e --- /dev/null +++ b/tests/neg/dynamicApplyDynamicTest9.scala @@ -0,0 +1,9 @@ +import scala.language.dynamics + +class Foo extends scala.Dynamic { + def applyDynamicNamed(name: String)(args: (String, Int)*): String = ??? +} + +object DynamicTest { + new Foo().applyDynamic("bar")("1" -> 2) // error +} diff --git a/tests/neg/dynamicApplyNamedDynamicTest1.scala b/tests/neg/dynamicApplyNamedDynamicTest1.scala new file mode 100644 index 000000000..a51cd2c7b --- /dev/null +++ b/tests/neg/dynamicApplyNamedDynamicTest1.scala @@ -0,0 +1,7 @@ +import scala.language.dynamics + +class Foo extends scala.Dynamic + +object DynamicTest { + new Foo().bazApply(a = "abc", b = 1) // error +} diff --git a/tests/neg/dynamicApplyNamedDynamicTest2.scala b/tests/neg/dynamicApplyNamedDynamicTest2.scala new file mode 100644 index 000000000..ca801e77c --- /dev/null +++ b/tests/neg/dynamicApplyNamedDynamicTest2.scala @@ -0,0 +1,10 @@ +import scala.language.dynamics + +class Foo extends scala.Dynamic { + def selectDynamic(name: String): Array[String] = ??? + def applyDynamic(name: String)(args: Any*): String = ??? +} + +object DynamicTest { + new Foo().bazApply(a = "abc", b = 1) // error +} diff --git a/tests/neg/dynamicApplyNamedDynamicTest3.scala b/tests/neg/dynamicApplyNamedDynamicTest3.scala new file mode 100644 index 000000000..b8ec41c6d --- /dev/null +++ b/tests/neg/dynamicApplyNamedDynamicTest3.scala @@ -0,0 +1,7 @@ +import scala.language.dynamics + +class Foo extends scala.Dynamic + +object DynamicTest { + new Foo().bazApply("abc", b = 1) // error +} diff --git a/tests/neg/dynamicApplyNamedDynamicTest4.scala b/tests/neg/dynamicApplyNamedDynamicTest4.scala new file mode 100644 index 000000000..983cbc599 --- /dev/null +++ b/tests/neg/dynamicApplyNamedDynamicTest4.scala @@ -0,0 +1,7 @@ +import scala.language.dynamics + +class Foo extends scala.Dynamic + +object DynamicTest { + new Foo().bazApply("abc", 4, b = 1, b = "bcd") // error +} diff --git a/tests/neg/dynamicApplyNamedDynamicTest5.scala b/tests/neg/dynamicApplyNamedDynamicTest5.scala new file mode 100644 index 000000000..3a48d38d8 --- /dev/null +++ b/tests/neg/dynamicApplyNamedDynamicTest5.scala @@ -0,0 +1,9 @@ +import scala.language.dynamics + +class Foo extends scala.Dynamic { + def applyDynamicNamed(name: String)(args: String*): String = ??? +} + +object DynamicTest { + new Foo().bazApply("abc", 4, b = 1, b = "bcd") // error // error // error // error +} diff --git a/tests/neg/dynamicApplyNamedDynamicTest6.scala b/tests/neg/dynamicApplyNamedDynamicTest6.scala new file mode 100644 index 000000000..4c39842af --- /dev/null +++ b/tests/neg/dynamicApplyNamedDynamicTest6.scala @@ -0,0 +1,9 @@ +import scala.language.dynamics + +class Foo extends scala.Dynamic { + def applyDynamicNamed(name: Int)(args: Any*): String = ??? +} + +object DynamicTest { + new Foo().bazApply("abc", 4, b = 1, b = "bcd") // error +} diff --git a/tests/neg/dynamicApplyNamedDynamicTest7.scala b/tests/neg/dynamicApplyNamedDynamicTest7.scala new file mode 100644 index 000000000..c29339f6d --- /dev/null +++ b/tests/neg/dynamicApplyNamedDynamicTest7.scala @@ -0,0 +1,9 @@ +import scala.language.dynamics + +class Foo extends scala.Dynamic { + def applyDynamicNamed(name: String)(args: Any*): String = ??? +} + +object DynamicTest { + def test: Int = new Foo().bazApply("abc", 4, b = 1, b = "bcd") // error +} diff --git a/tests/neg/dynamicApplyNamedDynamicTest8.scala b/tests/neg/dynamicApplyNamedDynamicTest8.scala new file mode 100644 index 000000000..e07b04ca1 --- /dev/null +++ b/tests/neg/dynamicApplyNamedDynamicTest8.scala @@ -0,0 +1,9 @@ +import scala.language.dynamics + +class Foo extends scala.Dynamic { + def applyDynamic(name: String)(args: Any*): String = ??? +} + +object DynamicTest { + new Foo().applyDynamicNamed("abc")() // error +} diff --git a/tests/neg/dynamicDynamicImplicitsTest1.scala b/tests/neg/dynamicDynamicImplicitsTest1.scala new file mode 100644 index 000000000..b044336aa --- /dev/null +++ b/tests/neg/dynamicDynamicImplicitsTest1.scala @@ -0,0 +1,13 @@ +import scala.language.dynamics + +class Foo extends scala.Dynamic { + def selectDynamic(name: String): String = ??? +} + +object DynamicTest { + implicit class Bar(foo: Foo) { + def bazSelect: Int = ??? + } + + def baz: String = new Foo().bazSelect // error +} diff --git a/tests/neg/dynamicDynamicImplicitsTest2.scala b/tests/neg/dynamicDynamicImplicitsTest2.scala new file mode 100644 index 000000000..3229d80e6 --- /dev/null +++ b/tests/neg/dynamicDynamicImplicitsTest2.scala @@ -0,0 +1,13 @@ +import scala.language.dynamics + +class Foo extends scala.Dynamic { + def applyDynamic(name: String)(args: Any*): String = ??? +} + +object DynamicTest { + implicit class Bar(foo: Foo) { + def bazApply: Int = ??? + } + + def baz: String = new Foo().bazApply("") // error +} diff --git a/tests/neg/dynamicDynamicImplicitsTest3.scala b/tests/neg/dynamicDynamicImplicitsTest3.scala new file mode 100644 index 000000000..6c26b9500 --- /dev/null +++ b/tests/neg/dynamicDynamicImplicitsTest3.scala @@ -0,0 +1,13 @@ +import scala.language.dynamics + +class Foo extends scala.Dynamic { + def applytDynamicNamed(name: String)(args: Any*): String = ??? +} + +object DynamicTest { + implicit class Bar(foo: Foo) { + def bazApply: Int = ??? + } + + def baz: String = new Foo().bazApply(a = "") // error +} diff --git a/tests/neg/dynamicSelectDynamicTest1.scala b/tests/neg/dynamicSelectDynamicTest1.scala new file mode 100644 index 000000000..a45671ad1 --- /dev/null +++ b/tests/neg/dynamicSelectDynamicTest1.scala @@ -0,0 +1,10 @@ +import scala.language.dynamics + +class Foo extends scala.Dynamic + +object DynamicTest { + def testSelect = { + new Foo().bazSelect // error + () + } +} diff --git a/tests/neg/dynamicSelectDynamicTest2.scala b/tests/neg/dynamicSelectDynamicTest2.scala new file mode 100644 index 000000000..9ba19a14d --- /dev/null +++ b/tests/neg/dynamicSelectDynamicTest2.scala @@ -0,0 +1,7 @@ +import scala.language.dynamics + +class Foo extends scala.Dynamic + +object DynamicTest { + def testSelect = new Foo().bazSelect // error +} diff --git a/tests/neg/dynamicSelectDynamicTest3.scala b/tests/neg/dynamicSelectDynamicTest3.scala new file mode 100644 index 000000000..acdad7033 --- /dev/null +++ b/tests/neg/dynamicSelectDynamicTest3.scala @@ -0,0 +1,7 @@ +import scala.language.dynamics + +class Foo extends scala.Dynamic + +object DynamicTest { + new Foo().bazSelect // error +} diff --git a/tests/neg/dynamicSelectDynamicTest4.scala b/tests/neg/dynamicSelectDynamicTest4.scala new file mode 100644 index 000000000..7295a43fd --- /dev/null +++ b/tests/neg/dynamicSelectDynamicTest4.scala @@ -0,0 +1,11 @@ +import scala.language.dynamics + +class Foo extends scala.Dynamic { + def selectDynamic(name: String): String = ??? +} + +object DynamicTest { + def testSelect: Int = { + new Foo().bazSelect // error + } +} diff --git a/tests/neg/dynamicSelectDynamicTest5.scala b/tests/neg/dynamicSelectDynamicTest5.scala new file mode 100644 index 000000000..17836efe4 --- /dev/null +++ b/tests/neg/dynamicSelectDynamicTest5.scala @@ -0,0 +1,7 @@ +import scala.language.dynamics + +class Foo extends scala.Dynamic + +object DynamicTest { + new Foo().bazSelectUpdate(6) = "a" // error +} diff --git a/tests/neg/dynamicSelectDynamicTest6.scala b/tests/neg/dynamicSelectDynamicTest6.scala new file mode 100644 index 000000000..8df9bf492 --- /dev/null +++ b/tests/neg/dynamicSelectDynamicTest6.scala @@ -0,0 +1,11 @@ +import scala.language.dynamics + +class Foo extends scala.Dynamic { + def selectDynamic(name: Int): String = ??? +} + +object DynamicTest { + def testSelect: String = { + new Foo().bazSelect // error + } +} diff --git a/tests/neg/dynamicSelectDynamicTest7.scala b/tests/neg/dynamicSelectDynamicTest7.scala new file mode 100644 index 000000000..4b4207844 --- /dev/null +++ b/tests/neg/dynamicSelectDynamicTest7.scala @@ -0,0 +1,9 @@ +import scala.language.dynamics + +class Foo extends scala.Dynamic { + def applyDynamic(name: String)(args: Any*): String = ??? +} + +object DynamicTest { + new Foo().selectDynamic("bar") // error +} diff --git a/tests/neg/dynamicUpdateDynamicTest1.scala b/tests/neg/dynamicUpdateDynamicTest1.scala new file mode 100644 index 000000000..8eba9fe60 --- /dev/null +++ b/tests/neg/dynamicUpdateDynamicTest1.scala @@ -0,0 +1,7 @@ +import scala.language.dynamics + +class Foo extends scala.Dynamic + +object DynamicTest { + new Foo().bazUpdate = 42 // error +} diff --git a/tests/neg/dynamicUpdateDynamicTest2.scala b/tests/neg/dynamicUpdateDynamicTest2.scala new file mode 100644 index 000000000..8bb8a9537 --- /dev/null +++ b/tests/neg/dynamicUpdateDynamicTest2.scala @@ -0,0 +1,9 @@ +import scala.language.dynamics + +class Foo extends scala.Dynamic { + def updateDynamic(name: String)(value: String): Unit = ??? +} + +object DynamicTest { + new Foo().bazUpdate = 42 // error +} diff --git a/tests/neg/dynamicUpdateDynamicTest3.scala b/tests/neg/dynamicUpdateDynamicTest3.scala new file mode 100644 index 000000000..22008dda4 --- /dev/null +++ b/tests/neg/dynamicUpdateDynamicTest3.scala @@ -0,0 +1,9 @@ +import scala.language.dynamics + +class Foo extends scala.Dynamic { + def updateDynamic(name: String)(value: Int): Unit = ??? +} + +object DynamicTest { + def test: Int = new Foo().bazUpdate = 42 // error +} diff --git a/tests/neg/dynamicUpdateDynamicTest4.scala b/tests/neg/dynamicUpdateDynamicTest4.scala new file mode 100644 index 000000000..3cdd32b3c --- /dev/null +++ b/tests/neg/dynamicUpdateDynamicTest4.scala @@ -0,0 +1,9 @@ +import scala.language.dynamics + +class Foo extends scala.Dynamic { + def updateDynamic(name: Int)(value: Int): Unit = ??? +} + +object DynamicTest { + new Foo().bazUpdate = 42 // error +} -- cgit v1.2.3 From 5a7cacbb37f8f1edfded03a095eb45c04a883185 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Fri, 3 Jun 2016 15:00:10 +0200 Subject: Add scala.Dynamic language feature check. --- src/dotty/tools/dotc/core/Definitions.scala | 4 +++- src/dotty/tools/dotc/core/StdNames.scala | 1 + src/dotty/tools/dotc/core/TypeOps.scala | 6 +++++- src/dotty/tools/dotc/reporting/Reporter.scala | 30 ++++++++++++++++++++++++++- src/dotty/tools/dotc/typer/Typer.scala | 8 ++++++- tests/neg/dynamicNoImport.scala | 3 +++ tests/pos/dynamicExtendsNoImport.scala | 7 +++++++ 7 files changed, 55 insertions(+), 4 deletions(-) create mode 100644 tests/neg/dynamicNoImport.scala create mode 100644 tests/pos/dynamicExtendsNoImport.scala (limited to 'tests/neg') diff --git a/src/dotty/tools/dotc/core/Definitions.scala b/src/dotty/tools/dotc/core/Definitions.scala index 5cb373cfd..1fa3f70f9 100644 --- a/src/dotty/tools/dotc/core/Definitions.scala +++ b/src/dotty/tools/dotc/core/Definitions.scala @@ -424,8 +424,10 @@ class Definitions { def Product_productArity(implicit ctx: Context) = Product_productArityR.symbol lazy val Product_productPrefixR = ProductClass.requiredMethodRef(nme.productPrefix) def Product_productPrefix(implicit ctx: Context) = Product_productPrefixR.symbol - lazy val LanguageModuleRef = ctx.requiredModule("dotty.language") + lazy val LanguageModuleRef = ctx.requiredModule("dotty.language") def LanguageModuleClass(implicit ctx: Context) = LanguageModuleRef.symbol.moduleClass.asClass + lazy val Scala2LanguageModuleRef = ctx.requiredModule("scala.language") + def Scala2LanguageModuleClass(implicit ctx: Context) = Scala2LanguageModuleRef.symbol.moduleClass.asClass lazy val NonLocalReturnControlType: TypeRef = ctx.requiredClassRef("scala.runtime.NonLocalReturnControl") lazy val ClassTagType = ctx.requiredClassRef("scala.reflect.ClassTag") diff --git a/src/dotty/tools/dotc/core/StdNames.scala b/src/dotty/tools/dotc/core/StdNames.scala index 81f6da0e2..345322cf5 100644 --- a/src/dotty/tools/dotc/core/StdNames.scala +++ b/src/dotty/tools/dotc/core/StdNames.scala @@ -383,6 +383,7 @@ object StdNames { val delayedInit: N = "delayedInit" val delayedInitArg: N = "delayedInit$body" val drop: N = "drop" + val dynamics: N = "dynamics" val dummyApply: N = "" val elem: N = "elem" val emptyValDef: N = "emptyValDef" diff --git a/src/dotty/tools/dotc/core/TypeOps.scala b/src/dotty/tools/dotc/core/TypeOps.scala index 1288c0b23..3da119a9c 100644 --- a/src/dotty/tools/dotc/core/TypeOps.scala +++ b/src/dotty/tools/dotc/core/TypeOps.scala @@ -455,7 +455,8 @@ trait TypeOps { this: Context => // TODO: Make standalone object. */ def featureEnabled(owner: ClassSymbol, feature: TermName): Boolean = { def toPrefix(sym: Symbol): String = - if (sym eq defn.LanguageModuleClass) "" else toPrefix(sym.owner) + sym.name + "." + if (!sym.exists || (sym eq defn.LanguageModuleClass) || (sym eq defn.Scala2LanguageModuleRef)) "" + else toPrefix(sym.owner) + sym.name + "." def featureName = toPrefix(owner) + feature def hasImport(implicit ctx: Context): Boolean = ( ctx.importInfo != null @@ -477,6 +478,9 @@ trait TypeOps { this: Context => // TODO: Make standalone object. def scala2Mode = featureEnabled(defn.LanguageModuleClass, nme.Scala2) + def dynamicsEnabled = + featureEnabled(defn.Scala2LanguageModuleClass, nme.dynamics) + def testScala2Mode(msg: String, pos: Position) = { if (scala2Mode) migrationWarning(msg, pos) scala2Mode diff --git a/src/dotty/tools/dotc/reporting/Reporter.scala b/src/dotty/tools/dotc/reporting/Reporter.scala index e4169b1fd..bddfd2f68 100644 --- a/src/dotty/tools/dotc/reporting/Reporter.scala +++ b/src/dotty/tools/dotc/reporting/Reporter.scala @@ -12,6 +12,7 @@ import config.Printers import java.lang.System.currentTimeMillis import core.Mode import interfaces.Diagnostic.{ERROR, WARNING, INFO} +import dotty.tools.dotc.core.Symbols.Symbol object Reporter { class Error(msgFn: => String, pos: SourcePosition) extends Diagnostic(msgFn, pos, ERROR) @@ -68,6 +69,29 @@ trait Reporting { this: Context => def featureWarning(msg: => String, pos: SourcePosition = NoSourcePosition): Unit = reporter.report(new FeatureWarning(msg, pos)) + def featureWarning(feature: String, featureDescription: String, isScala2Feature: Boolean, + featureUseSite: Symbol, required: Boolean, pos: SourcePosition): Unit = { + val req = if (required) "needs to" else "should" + val prefix = if (isScala2Feature) "scala." else "dotty." + val fqname = prefix + "language." + feature + + val explain = { + if (reporter.isReportedFeatureUseSite(featureUseSite)) "" + else { + reporter.reportNewFeatureUseSite(featureUseSite) + s"""| + |This can be achieved by adding the import clause 'import $fqname' + |or by setting the compiler option -language:$feature. + |See the Scala docs for value $fqname for a discussion + |why the feature $req be explicitly enabled.""".stripMargin + } + } + + val msg = s"$featureDescription $req be enabled\nby making the implicit value $fqname visible.$explain" + if (required) error(msg, pos) + else reporter.report(new FeatureWarning(msg, pos)) + } + def warning(msg: => String, pos: SourcePosition = NoSourcePosition): Unit = reporter.report(new Warning(msg, pos)) @@ -172,7 +196,7 @@ abstract class Reporter extends interfaces.ReporterResult { /** Report a diagnostic */ def doReport(d: Diagnostic)(implicit ctx: Context): Unit - /** Whether very long lines can be truncated. This exists so important + /** Whether very long lines can be truncated. This exists so important * debugging information (like printing the classpath) is not rendered * invisible due to the max message length. */ @@ -206,6 +230,10 @@ abstract class Reporter extends interfaces.ReporterResult { */ def errorsReported = hasErrors + private[this] var reportedFeaturesUseSites = Set[Symbol]() + def isReportedFeatureUseSite(featureTrait: Symbol): Boolean = reportedFeaturesUseSites.contains(featureTrait) + def reportNewFeatureUseSite(featureTrait: Symbol): Unit = reportedFeaturesUseSites += featureTrait + val unreportedWarnings = new mutable.HashMap[String, Int] { override def default(key: String) = 0 } diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala index 019c460e8..34400ede7 100644 --- a/src/dotty/tools/dotc/typer/Typer.scala +++ b/src/dotty/tools/dotc/typer/Typer.scala @@ -1092,7 +1092,13 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit .withType(dummy.nonMemberTermRef) checkVariance(impl1) if (!cls.is(AbstractOrTrait) && !ctx.isAfterTyper) checkRealizableBounds(cls.typeRef, cdef.pos) - assignType(cpy.TypeDef(cdef)(name, impl1, Nil), cls) + val cdef1 = assignType(cpy.TypeDef(cdef)(name, impl1, Nil), cls) + if (ctx.phase.isTyper && cdef1.tpe.derivesFrom(defn.DynamicClass) && !ctx.dynamicsEnabled) { + val isRequired = parents1.exists(_.tpe.isRef(defn.DynamicClass)) + ctx.featureWarning(nme.dynamics.toString, "extension of type scala.Dynamic", isScala2Feature = true, + cls, isRequired, cdef.pos) + } + cdef1 // todo later: check that // 1. If class is non-abstract, it is instantiatable: diff --git a/tests/neg/dynamicNoImport.scala b/tests/neg/dynamicNoImport.scala new file mode 100644 index 000000000..cfaac66a4 --- /dev/null +++ b/tests/neg/dynamicNoImport.scala @@ -0,0 +1,3 @@ +class Foo extends scala.Dynamic // error +trait Bar extends scala.Dynamic // error +object Baz extends scala.Dynamic // error diff --git a/tests/pos/dynamicExtendsNoImport.scala b/tests/pos/dynamicExtendsNoImport.scala new file mode 100644 index 000000000..51f3719c5 --- /dev/null +++ b/tests/pos/dynamicExtendsNoImport.scala @@ -0,0 +1,7 @@ + +package foo { + import scala.language.dynamics + class Bar extends scala.Dynamic +} + +class Baz extends foo.Bar -- cgit v1.2.3 From 7e00c724273d432c8900c0e8ec852bb77357958e Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Mon, 6 Jun 2016 14:16:10 +0200 Subject: Fix TypeOps.featureEnabled ignoring import disabling. --- src/dotty/tools/dotc/core/TypeOps.scala | 19 ++++++++++--------- tests/neg/dynamicNoImport.scala | 10 ++++++++++ 2 files changed, 20 insertions(+), 9 deletions(-) (limited to 'tests/neg') diff --git a/src/dotty/tools/dotc/core/TypeOps.scala b/src/dotty/tools/dotc/core/TypeOps.scala index 3da119a9c..63d8dff3b 100644 --- a/src/dotty/tools/dotc/core/TypeOps.scala +++ b/src/dotty/tools/dotc/core/TypeOps.scala @@ -458,15 +458,16 @@ trait TypeOps { this: Context => // TODO: Make standalone object. if (!sym.exists || (sym eq defn.LanguageModuleClass) || (sym eq defn.Scala2LanguageModuleRef)) "" else toPrefix(sym.owner) + sym.name + "." def featureName = toPrefix(owner) + feature - def hasImport(implicit ctx: Context): Boolean = ( - ctx.importInfo != null - && ( (ctx.importInfo.site.widen.typeSymbol eq owner) - && ctx.importInfo.originals.contains(feature) - || - { var c = ctx.outer - while (c.importInfo eq ctx.importInfo) c = c.outer - hasImport(c) - })) + def hasImport(implicit ctx: Context): Boolean = { + if (ctx.importInfo == null || (ctx.importInfo.site.widen.typeSymbol ne owner)) false + else if (ctx.importInfo.excluded.contains(feature)) false + else if (ctx.importInfo.originals.contains(feature)) true + else { + var c = ctx.outer + while (c.importInfo eq ctx.importInfo) c = c.outer + hasImport(c) + } + } def hasOption = ctx.base.settings.language.value exists (s => s == featureName || s == "_") hasImport(ctx.withPhase(ctx.typerPhase)) || hasOption } diff --git a/tests/neg/dynamicNoImport.scala b/tests/neg/dynamicNoImport.scala index cfaac66a4..c009d91a4 100644 --- a/tests/neg/dynamicNoImport.scala +++ b/tests/neg/dynamicNoImport.scala @@ -1,3 +1,13 @@ class Foo extends scala.Dynamic // error trait Bar extends scala.Dynamic // error object Baz extends scala.Dynamic // error + +package A { + import scala.language.dynamics + package B { + import scala.language.{ dynamics => _ } + class Foo extends scala.Dynamic // error + trait Bar extends scala.Dynamic // error + object Baz extends scala.Dynamic // error + } +} -- cgit v1.2.3