macwire icon indicating copy to clipboard operation
macwire copied to clipboard

wrong constructor is being picked up

Open pawelpanasewicz opened this issue 8 years ago • 4 comments

In below code I am trying to construct Target object. Target class has 3 constructors but only one is preffered (the one annotated). This results in compilation error because wire[Target] picks up wrong constructor. I've intentionally provided to much eligible values here in order to show the naughty behaviour:

  trait A
  trait B
  trait C

  class Target(a: A) {

    def this(b: B) = this(new A{})

    @javax.inject.Inject
    def this(c: C) = this(new A{})
  }

  val a: A = new A {}
  val a1: A = new A {} 
  val b: B = new B {}
  val b1: B = new B {}
  val c = new C {}
  val sa = wire[Target]

Error:(24, 16) Found multiple values of type [com.softwaremill.macwire.macwireakka.Demo.A]: [List(a, a1)] val sa = wire[Target] Error:(24, 16) ambiguous reference to overloaded definition, both constructor Target in class Target of type (c: com.softwaremill.macwire.macwireakka.Demo.C)com.softwaremill.macwire.macwireakka.Demo.Target and constructor Target in class Target of type (b: com.softwaremill.macwire.macwireakka.Demo.B)com.softwaremill.macwire.macwireakka.Demo.Target match argument types (Null) and expected result type com.softwaremill.macwire.macwireakka.Demo.Target val sa = wire[Target]

However if you provide type after sa:

  val sa: Target = wire[Target]

it works fine.

pawelpanasewicz avatar Dec 28 '16 21:12 pawelpanasewicz

Maybe I'm wrong, but is not your problem listed in the limitations section of the Readme (https://github.com/adamw/macwire#limitations)?

akozhemiakin avatar Dec 28 '16 23:12 akozhemiakin

Right. Due to macro limiations we are not able to implement nicer behaviour. Anyway, we can keep this issue open in order to address it in future. Maybe when scala meta comes to play it solves the problem.

At the moment scala macros doesn't see @Inject annotation if we don't provide type annotation. This is reason why in above example wire[Target] chooses primary public constructor over annotated one.

pawelpanasewicz avatar Dec 30 '16 19:12 pawelpanasewicz

I have another issue that looks like this

class ConfigModule(config: com.typesafe.config.Config) {
	@javax.inject.Inject
	def this(configuration: play.api.Configuration) = this(configuration.underlying) // underlying : com.typesafe.config.Config
}
lazy val playConfig: play.api.Configuration
lazy val configModule: ConfigModule = wire[ConfigModule]

gives

[error] Cannot find a value of type: [com.typesafe.config.Config]
[error]   lazy val configModule: ConfigModule = wire[ConfigModule]

aeons avatar Jan 27 '17 11:01 aeons

The original issue appears to be already solved in MacWire 2.3.5 and Scala 2.12.11.

mkrzemien avatar May 24 '20 18:05 mkrzemien