diff options
author | Jason Zaugg <jzaugg@gmail.com> | 2016-11-18 16:04:49 +1000 |
---|---|---|
committer | Jason Zaugg <jzaugg@gmail.com> | 2016-11-18 18:17:30 +1000 |
commit | 944db65d63e12ae4e0135999cdc8b9f2695f4102 (patch) | |
tree | 0076ec04446f6eefc3c18dc0f079d6bd84761e68 /test | |
parent | 73678d4dafe250f0b38df2e953787af26b1a4ee3 (diff) | |
download | scala-944db65d63e12ae4e0135999cdc8b9f2695f4102.tar.gz scala-944db65d63e12ae4e0135999cdc8b9f2695f4102.tar.bz2 scala-944db65d63e12ae4e0135999cdc8b9f2695f4102.zip |
SI-10066 Fix crash in erroneous code with implicits, dynamic
The compiler support in the typechecker for `scala.Dynamic` is
very particular about the `Context` in which it is typechecked.
It looks at the `tree` in the enclosing context to find the expression
immediately enclosing the dynamic selection. See the logic in
`dyna::mkInvoke` for the details.
This commit substitutes the result of `resetAttrs` into the tree
of the typer context before continuing with typechecking.
Diffstat (limited to 'test')
-rw-r--r-- | test/files/neg/t10066.check | 7 | ||||
-rw-r--r-- | test/files/neg/t10066.scala | 38 | ||||
-rw-r--r-- | test/files/pos/t10066.scala | 38 |
3 files changed, 83 insertions, 0 deletions
diff --git a/test/files/neg/t10066.check b/test/files/neg/t10066.check new file mode 100644 index 0000000000..3555205d83 --- /dev/null +++ b/test/files/neg/t10066.check @@ -0,0 +1,7 @@ +t10066.scala:33: error: could not find implicit value for parameter extractor: dynamicrash.Extractor[String] + println(storage.foo[String]) + ^ +t10066.scala:37: error: could not find implicit value for parameter extractor: dynamicrash.Extractor[A] + println(storage.foo) + ^ +two errors found diff --git a/test/files/neg/t10066.scala b/test/files/neg/t10066.scala new file mode 100644 index 0000000000..ef52f333dd --- /dev/null +++ b/test/files/neg/t10066.scala @@ -0,0 +1,38 @@ +package dynamicrash + +import scala.language.dynamics + +class Config + +trait Extractor[A] { + def extract(config: Config, name: String): A +} + +object Extractor { + // note missing "implicit" + val stringExtractor = new Extractor[String] { + override def extract(config: Config, name: String): String = ??? + } +} + +class Workspace extends Dynamic { + val config: Config = new Config + + def selectDynamic[A](name: String)(implicit extractor: Extractor[A]): A = + extractor.extract(config, name) +} + +object Main { + val storage = new Workspace + + // this line works fine + // val a = storage.foo + + // this line crashes the compiler ("head of empty list") + // in ContextErrors$InferencerContextErrors$InferErrorGen$.NotWithinBoundsErrorMessage + println(storage.foo[String]) + + // this line crashes the compiler in different way ("unknown type") + // in the backend, warning: an unexpected type representation reached the compiler backend while compiling Test.scala: <error> + println(storage.foo) +} diff --git a/test/files/pos/t10066.scala b/test/files/pos/t10066.scala new file mode 100644 index 0000000000..bef85cb08c --- /dev/null +++ b/test/files/pos/t10066.scala @@ -0,0 +1,38 @@ +package dynamicrash + +import scala.language.dynamics + +class Config + +trait Extractor[A] { + def extract(config: Config, name: String): A +} + +object Extractor { + // this has "implicit", unlike the corresponding neg test + implicit val stringExtractor = new Extractor[String] { + override def extract(config: Config, name: String): String = ??? + } +} + +class Workspace extends Dynamic { + val config: Config = new Config + + def selectDynamic[A](name: String)(implicit extractor: Extractor[A]): A = + extractor.extract(config, name) +} + +object Main { + val storage = new Workspace + + // this line works fine + // val a = storage.foo + + // this line crashes the compiler ("head of empty list") + // in ContextErrors$InferencerContextErrors$InferErrorGen$.NotWithinBoundsErrorMessage + println(storage.foo[String]) + + // this line crashes the compiler in different way ("unknown type") + // in the backend, warning: an unexpected type representation reached the compiler backend while compiling Test.scala: <error> + println(storage.foo) +} |