为什么scala.language.implicitConversions不是最后一次导入时发出警告?

时间:2015-01-14 11:42:38

标签: scala import warnings implicit-conversion

在我的Scala代码中,我有一些隐式转换,我有必要的导入存在:

import scala.language.implicitConversions

但是,有时当在此之后再进行另一次导入时,我会收到警告,好像导入根本不存在:

  

警告:(112,18)应启用隐式转换方法pair2Dimension   通过使隐式值scala.language.implicitConversions可见。

build.sbt:

name := "ImplicitSBT"

version := "1.0"

scalaVersion := "2.11.5"

scalacOptions ++= Seq("-deprecation","-feature")

libraryDependencies += "org.scala-lang.modules" %% "scala-swing" % "1.0.1"

Main.scala:

import scala.language.implicitConversions
import scala.swing.{Action, _}

object Main extends App {

  implicit def pair2Dimension(pair: (Int, Int)): Dimension = new Dimension(pair._1, pair._2)

  val dim : Dimension = (0,0)

  println(dim)


}

为什么会这样? import scala.swing.{Action, _}如何隐藏implicitConversions导入?

3 个答案:

答案 0 :(得分:4)

  

如何导入scala.swing。{Action,_}隐藏implicitConversions导入?

您:

import scala.language.implicitConversions

...在implicitConversions包对象中被scala.swing defined遮蔽:

package scala

...

package object swing {

...

implicit lazy val implicitConversions = scala.language.implicitConversions

...

}

由于您在此处使用通配符导入:

import scala.swing.{Action, _}

... scala.swing.implicitConversionsscala.swing导入,最后导致阴影scala.language.implicitConversions

有趣的问题是:如果有两个“功能标志”(在这种情况下为scalac),implicitConversions无法确定语言功能是否已启用,为什么scala.language.implicitConversions无法确定是否启用了语言功能。

这可能是一个错误以及SIP 18如何实现的具体细节。

无论如何,要解决此问题,我建议您执行以下操作之一:

  1. 不导入scala.swing(因为在通配符导入时已导入scala.swing

  2. 不要从implicitConversions进行通配符导入(不要污染您的范围并导入您需要的内容)

  3. Main对象级别{{1}}进行另一次导入(不会被另一个导入)

答案 1 :(得分:4)

中所述

http://docs.scala-lang.org/tutorials/FAQ/finding-implicits.html

通配符导入(正如您所写)给予任何Swing隐式定义一个相当高的优先级,并且显然隐藏了你的。

由于您正在使用SBT进行编译,因此传递以下设置并不容易

scalacOptions ++= Seq(
  "-feature",
  "-language:implicitConversions"
)

并且不再担心什么是正确的导入地点scala.language.implicitConversions

答案 2 :(得分:1)

这是隐式查找中的错误。

这是更常规代码中的相同结构,其中所需的隐含是执行上下文。

(通配符导入是来自包对象,还是其他包是否在同一个编译单元中。)

由于代码使用显式global进行编译,因此应使用隐式arg进行编译。

隐式可用,如果它可以是accessed without a prefix

binding precedence不受源代码顺序的影响。阴影以通常的方式工作;绑定永远不会影响更高优先级的绑定。

/*
package object bound2 {
  implicit lazy val global = scala.concurrent.ExecutionContext.Implicits.global
}
*/
package bound2 {
  object B {
    implicit lazy val global: concurrent.ExecutionContextExecutor = scala.concurrent.ExecutionContext.global
  }
}

package bound {
  // the order of these imports in the same scope should not matter
  import scala.concurrent.ExecutionContext.Implicits.global
  import bound2.B._

  object Test extends App {
    val f = concurrent.Future(42)  //(global) // explicit arg works
    Console println concurrent.Await.result(f, concurrent.duration.Duration.Inf)
  }
}

在规范示例2.0.1中,添加标记为“OK”的行进行编译,并且您可以验证顺序无关紧要,但它在内部范围内变得模糊,因为“通配符y”不会影响来自外部范围的“显式y”:

    import X.y           // `y' bound by explicit import
    println("L16: "+y)   // `y' refers to `Q.X.y' here
    import P.X._
    println("OK: "+y)   // `y' refers to `Q.X.y' here

    locally { val x = "abc"      // `x' bound by local definition
      import P.X._       // `x' and `y' bound by wildcard import
//        println("L19: "+y) // reference to `y' is ambiguous here