上下文抽象 的重新设计带来了一些不兼容性。
不兼容性 | Scala 2.13 | Scala 3 迁移重写 | Scalafix 规则 | 运行时不兼容性 |
---|---|---|---|---|
隐式 def 的类型 | ✅ | |||
隐式视图 | 可能 | |||
视图边界 | 弃用 | |||
在 A 和 => A 上的转换不明确 |
隐式定义的类型
隐式定义的类型(val
或 def
)需要在 Scala 3 中显式给出。它们不能再被推断了。
名为 ExplicitResultTypes 的 Scalafix 规则可以自动编写缺少的类型注释。
隐式视图
Scala 3 不支持从隐式函数值(形式为 implicit val ev: A => B
)进行隐式转换。
以下代码段在 Scala 3 中现在无效
trait Pretty {
val print: String
}
def pretty[A](a: A)(implicit ev: A => Pretty): String =
a.print // In Scala 3, Error: value print is not a member of A
Scala 3 迁移编译 可以针对这些情况发出警告,但不会尝试修复它。
请注意,此不兼容性可能会产生运行时不兼容性并破坏您的程序。实际上,编译器可以从更广泛的作用域中找到另一个隐式转换,这最终会导致在运行时出现不需要的行为。
此示例说明了这种情况
trait Pretty {
val print: String
}
implicit def anyPretty(any: Any): Pretty = new Pretty { val print = "any" }
def pretty[A](a: A)(implicit ev: A => Pretty): String =
a.print // always print "any"
已解析的转换取决于编译器模式
-source:3.0-migration
:编译器执行ev
转换-source:3.0
:编译器无法执行ev
转换,但可以执行anyPretty
,这是不需要的
在 Scala 3 中,一个简单的修复方法是明确提供正确的转换
视图界限
视图界限已弃用很长时间,但仍在 Scala 2.13 中受支持。它们不再可以与 Scala 3 一起编译。
def foo[A <% Long](a: A): Long = a
在此示例中,在 Scala 3 中,我们收到以下错误消息
该消息建议使用上下文界限而不是视图界限,但这会更改方法的签名。保留二进制兼容性可能更容易且更安全。要做到这一点,必须显式声明并调用隐式转换。
小心不要陷入上面在 隐式视图 中描述的运行时不兼容性。
在 A
和 => A
上的模棱两可的转换
在 Scala 2.13 中,在 A
上的隐式转换优于在 => A
上的隐式转换。在 Scala 3 中不再是这样,并导致模棱两可的转换。
例如,在此示例中
implicit def boolFoo(bool: Boolean): Foo = ???
implicit def lazyBoolFoo(lazyBool: => Boolean): Foo = ???
true.foo()
Scala 2.13 编译器选择 boolFoo
转换,但 Scala 3 编译器无法编译。
一个临时解决方案是显式编写转换。
此页面的贡献者
内容
- 兼容性参考
- 源代码级别
- 类路径级别
- 运行时
- 元编程
- 迁移工具之旅
- Scala 2 使用 -Xsource:3
- Scala 3 迁移模式
- 迁移教程
- 先决条件
- 移植 sbt 项目(使用 sbt-scala3-migrate)
- 移植 sbt 项目(手动)
- 交叉构建宏库
- 混合使用 Scala 2.13 和 Scala 3 宏
- Scala 3 语法重写
- 不兼容性表
- 语法更改
- 已删除的功能
- 上下文抽象
- 其他已更改的功能
- 类型检查器
- 类型推断
- 编译器选项
- 编译器选项查找表
- 新的编译器选项
- Scala2 和 Scala3 之间的 Scaladoc 设置兼容性
- 编译器插件
- Kind Projector 迁移
- 外部资源