Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Problem reading lists of non-trivial types #44

Open
danielspicar opened this issue Oct 29, 2019 · 1 comment
Open

Problem reading lists of non-trivial types #44

danielspicar opened this issue Oct 29, 2019 · 1 comment

Comments

@danielspicar
Copy link

danielspicar commented Oct 29, 2019

Hi

I have come across an interesting problem when using configs version 0.4.4 and 0.5.0-SNAPSHOT (22ad412) with scala 2.11.

Example:

object MyEnum extends Enumeration {
  type MyEnum = Value

  val Foo = Value("foo")
  val Bar = Value("bar")
}

case class Foo2(enum: Option[MyEnum])

Reading this class from a config works:

val config2_0 = ConfigFactory.parseString("foo = {enum = foo}")
val result2_0 = ConfigReader[Foo2].read(config2_0, "foo")
println(result2_0)

However, reading a List (or Seq) of this class does not compile!

val config2_1 = ConfigFactory.parseString("foo = [{enum = foo}, {enum = bar}]")
val result2_1 = ConfigReader[List[Foo2]].read(config2_1, "foo")
println(result2_1)
Error:(36, 33) diverging implicit expansion for type configs.ConfigReader[java.util.List[Foo2]]
starting with method fromStringConfigReader in class ConfigReaderInstances
    val result2_1 = ConfigReader[List[Foo2]].read(config2_1, "foo")

Error:(36, 33) diverging implicit expansion for type configs.ConfigReader[Option[MyEnum.MyEnum]]
starting with macro method autoDeriveConfigReader in class ConfigReaderInstances3
    val result2_1 = ConfigReader[List[Foo2]].read(config2_1, "foo")

Error:(36, 33) not enough arguments for method apply: (implicit A: configs.ConfigReader[List[Foo2]])configs.ConfigReader[List[Foo2]] in object ConfigReader.
Unspecified value parameter A.
    val result2_1 = ConfigReader[List[Foo2]].read(config2_1, "foo")

The same problem appears in other similar cases. For example:

case class EitherExample(num: Either[Int, String])

with the following reader:

implicit def eitherReader[A, B](implicit aReader: ConfigReader[A], bReader: ConfigReader[B]): ConfigReader[Either[A, B]] = {
  ConfigReader.fromTry { (c, p) =>
    aReader.read(c, p).map(Left(_)).orElse(bReader.read(c, p).map(Right(_))).valueOrThrow(_.configException)
  }
}

Reading this class from a config works:

val config3_0 = ConfigFactory.parseString("{num = two}")
val result3_0 = ConfigReader[EitherExample].extract(config3_0)
println(result3_0)

However, reading a List (or Seq) of this class does not compile!

val config3_1 = ConfigFactory.parseString("foo = [{num = 2}, {num = two}]")
val result3_1 = ConfigReader[List[EitherExample]].read(config3_1, "foo")
print(result3_1)
Error:(44, 33) diverging implicit expansion for type configs.ConfigReader[Either[Int,String]]
starting with method eitherReader in object Bug
    val result3_1 = ConfigReader[List[EitherExample]].read(config3_1, "foo")

Error:(44, 33) diverging implicit expansion for type configs.ConfigReader[java.util.List[EitherExample]]
starting with method fromStringConfigReader in class ConfigReaderInstances
    val result3_1 = ConfigReader[List[EitherExample]].read(config3_1, "foo")

Error:(44, 33) diverging implicit expansion for type configs.ConfigReader[Either[Int,String]]
starting with macro method autoDeriveConfigReader in class ConfigReaderInstances3
    val result3_1 = ConfigReader[List[EitherExample]].read(config3_1, "foo")

Error:(44, 33) not enough arguments for method apply: (implicit A: configs.ConfigReader[List[EitherExample]])configs.ConfigReader[List[EitherExample]] in object ConfigReader.
Unspecified value parameter A.
    val result3_1 = ConfigReader[List[EitherExample]].read(config3_1, "foo")

Note: All examples compile and run with Scala 2.13. However, I do not have the option to upgrade beyond 2.11 in the project I am working on.

Any clues as to what is happening and whether it can be fixed or avoided?

Thank you!

@danielspicar
Copy link
Author

We found a workaround (hopefully) which may help to shed some light on what is happening.

The examples above work, when the "pimp my library" decorator for the typesafe Config is used instead of ConfigReader[A].

These work:

import configs.syntax._

val result2_1 = config2_1.get[List[Foo2]]("foo")

val result3_1 = config3_1.get[List[EitherExample]]("foo")

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant