- Notifications
You must be signed in to change notification settings - Fork 1.1k
Description
This means that some type-safe code will fail to compile.
Compiler version
Tested on 3.7.2, 3.3.6, 3.7.3-RC1, 3.0.0 (all via scastie)
Minimized code
https://scastie.scala-lang.org/b1zJrCWFR9yD71xTREwJtA
trait C[T] { } class Cls[T](f: T => C[T] = (x: T) => throw new Exception("a")) val _ = Cls[Int]() // doesn't compile def f[T](g: T => C[T] = (x: T) => throw new Exception("a")) = () val _ = f[Int]() // doesn't compile def default[T](x: T) = ??? class Cls2[T](f: T => C[T] = default[T]) val _ = new Cls2[Int]() // doesn't compileOutput
Note that the return type of the function / lambda is over-specifialised to C[Nothing], despite the fact there's no code to restrict it to that. This causes a type error at the call-site of the constructor/function.
It is not clear why the type error happens only when calling, rather than when defining the default parameter.
[error] -- [E007] Type Mismatch Error: /home/X.scala:6:8 [error] 6 |val _ = Cls[Int]() // doesn't compile [error] | ^^^^^^^^ [error] | Found: Int => C[Nothing] [error] | Required: Int => C[Int] [error] | [error] | longer explanation available when compiling with `-explain` [error] -- [E007] Type Mismatch Error: /home/X.scala:10:8 [error] 10 |val _ = f[Int]() // doesn't compile [error] | ^^^^^^ [error] | Found: Int => C[Nothing] [error] | Required: Int => C[Int] [error] | [error] | longer explanation available when compiling with `-explain` [error] -- [E007] Type Mismatch Error: /home/X.scala:14:12 [error] 14 |val _ = new Cls2[Int]() // doesn't compile [error] | ^^^^^^^^^ [error] | Found: Int => C[Nothing] [error] | Required: Int => C[Int] [error] | [error] | longer explanation available when compiling with `-explain`Expectation
As far as I can tell, this code should type-check. The function's return type should be Nothing, so it should be coercible to the required T => C[T] type.
These changes will cause the code to start compiling:
- changing the parameter type to
T => Nothing - adding a variance annotation to
C, either + or - will work - type-annotating the function with
: T => C[T]or: T => Nothing - type-annotating the throwing expression as
(throw new Exception()): C[T] - explicitly passing the parameter, even without removing the default parameter
- using scala 2.13.16
These changes will not cause the code to compile:
- changing the parameter field to a var or val
- type-annotating the throwing expression as
(??? : Nothing)
Given the longevity of this bug, I'd be surprised if it hadn't been seen before, but I couldn't find any other reports with a quick search.