-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Regression: inline implicit conversion get called when unnecessary #19862
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
Comments
summon[Function1[Int, Int]] is inlined in typer as val proxy: Int => Int = (value: Int) => uhOh[Int](value)
proxy as expected. Then in the inlining phase |
I get what you mean for the first sample. I think I got confused because I used it for implicit conversions (since |
It seems like this only worked by chance before. We could revert this change for 3.3.4 to keep compatibility, but I don't see a reason to revert it from 3.4.0. Especially since a future Scala version is supposed to deprecate
You can put an inline def in Conversion, but you have to keep in mind the desugaring: given foo: Conversion[Int, String] with
inline def apply(x: Int): String = x.toString becomes: given foo: foo = new foo()
class foo extends Conversion[Int, String]:
inline def apply(x: Int): String = x.toString
private def apply$retainedBody(x: Int): String = apply(x) (and when emitting bytecode, the So your inline def needs to be callable from a non-inline def with the same signature as the inline def. |
I think we could tweak implicit search so that |
`inline implicit def` is not really a supported feature since it combines Scala 3's `inline` with Scala 2's `implicit` where the latter should eventually be deprecated. This however didn't prevent at least one project from using this combination in a way that was broken by scala#18249, see scala#19862 for the details. The issue is that when definining: implicit def foo(x: A): B = ... Then `foo` is a valid implicit search candidate when looking up an implicit `Function1[A, B]`. However, before scala#18249 if instead we wrote: inline implicit def foo(x: A): B = ... Then `foo` would be considered as an implicit search candidate but discarded because eta-expansion was disabled. There is no particular reason for `inline implicit def` to behave differently from `implicit def` here, but since `implicit def` is a legacy feature and since Scala 3.3 is an LTS release, we choose to restore the pre-scala#18249 behavior for compatibility reasons. Fixes scala#19862.
`inline implicit def` is not really a supported feature since it combines Scala 3's `inline` with Scala 2's `implicit` where the latter should eventually be deprecated. This however didn't prevent at least one project from using this combination in a way that was broken by scala#18249, see scala#19862 for the details. The issue is that when definining: implicit def foo(x: A): B = ... Then `foo` is a valid implicit search candidate when looking up an implicit `Function1[A, B]`. However, before scala#18249 if instead we wrote: inline implicit def foo(x: A): B = ... Then `foo` would be considered as an implicit search candidate but discarded because eta-expansion was disabled. There is no particular reason for `inline implicit def` to behave differently from `implicit def` here, but since `implicit def` is a legacy feature and since Scala 3.3 is an LTS release, we choose to restore the pre-scala#18249 behavior for compatibility reasons. Fixes scala#19862.
There is already such a thread https://contributors.scala-lang.org/t/before-deprecating-old-style-implicit-conversions-we-need-this/6385/ |
`inline implicit def` is not really a supported feature since it combines Scala 3's `inline` with Scala 2's `implicit` where the latter should eventually be deprecated. This however didn't prevent at least one project from using this combination in a way that was broken by #18249, see #19862 for the details. The issue is that when definining: implicit def foo(x: A): B = ... Then `foo` is a valid implicit search candidate when looking up an implicit `Function1[A, B]`. However, before #18249 if instead we wrote: inline implicit def foo(x: A): B = ... Then `foo` would be considered as an implicit search candidate but discarded because eta-expansion was disabled. There is no particular reason for `inline implicit def` to behave differently from `implicit def` here, but since `implicit def` is a legacy feature and since Scala 3.3 is an LTS release, we choose to restore the pre-#18249 behavior for compatibility reasons. Fixes #19862.
I'm afraid this is not compatible with some usages of I will open a new thread on Scala Contributors since I don't think @soronpo's cover the same issue. |
`inline implicit def` is not really a supported feature since it combines Scala 3's `inline` with Scala 2's `implicit` where the latter should eventually be deprecated. This however didn't prevent at least one project from using this combination in a way that was broken by #18249, see #19862 for the details. The issue is that when definining: implicit def foo(x: A): B = ... Then `foo` is a valid implicit search candidate when looking up an implicit `Function1[A, B]`. However, before #18249 if instead we wrote: inline implicit def foo(x: A): B = ... Then `foo` would be considered as an implicit search candidate but discarded because eta-expansion was disabled. There is no particular reason for `inline implicit def` to behave differently from `implicit def` here, but since `implicit def` is a legacy feature and since Scala 3.3 is an LTS release, we choose to restore the pre-#18249 behavior for compatibility reasons. Fixes #19862. [Cherry-picked af69895]
Compiler version
Last working version:
3.3.1
Not working versions:
3.3.3
and3.4.0
Did not test nightly versions
Minimized code
Opaque type variant (also not working)
Output
Notes:
uhOh
is not called in 3.3.1Function1
.summon[Foo[Int, Int]]
works as expected ("no given instance ofFoo
...").A
is important. Replacing it byAny
does not produce the error.Expectation
I would expect this sample to compile as it did in
3.3.1
.Real world example
uhOh
looks meaningless but this issue also breaks actually useful code. For example in a library I have an inline implicit conversion which converts a typeA
to an opaque typeIronType[A, C] <: A
impacted by the problem described above, for example in its Scalacheck module.The text was updated successfully, but these errors were encountered: