Skip to content

Commit

Permalink
Restore pre-3.3.2 behavior of inline implicit def
Browse files Browse the repository at this point in the history
`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]
  • Loading branch information
smarter authored and WojciechMazur committed Jul 2, 2024
1 parent 38ab06f commit bfcdef8
Show file tree
Hide file tree
Showing 3 changed files with 11 additions and 0 deletions.
1 change: 1 addition & 0 deletions compiler/src/dotty/tools/dotc/core/Flags.scala
Original file line number Diff line number Diff line change
Expand Up @@ -581,6 +581,7 @@ object Flags {
val LazyGiven: FlagSet = Given | Lazy
val InlineOrProxy: FlagSet = Inline | InlineProxy // An inline method or inline argument proxy */
val InlineMethod: FlagSet = Inline | Method
val InlineImplicitMethod: FlagSet = Implicit | InlineMethod
val InlineParam: FlagSet = Inline | Param
val InlineByNameProxy: FlagSet = InlineProxy | Method
val JavaEnumTrait: FlagSet = JavaDefined | Enum // A Java enum trait
Expand Down
2 changes: 2 additions & 0 deletions compiler/src/dotty/tools/dotc/typer/Typer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3939,10 +3939,12 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer

// Reasons NOT to eta expand:
// - we reference a constructor
// - we reference an inline implicit def (see #19862)
// - we are in a pattern
// - the current tree is a synthetic apply which is not expandable (eta-expasion would simply undo that)
if arity >= 0
&& !tree.symbol.isConstructor
&& !tree.symbol.isAllOf(InlineImplicitMethod)
&& !ctx.mode.is(Mode.Pattern)
&& !(isSyntheticApply(tree) && !functionExpected)
then
Expand Down
8 changes: 8 additions & 0 deletions tests/pos/i19862.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import scala.language.implicitConversions

object Test:
implicit inline def uhOh[A](value: A): A =
compiletime.error("Should not have been called")
def test =
// Compiles because `uhOh` fails to eta-expand and we fallback to `Predef.$conforms[A, A]`
summon[Function1[Int, Int]]

0 comments on commit bfcdef8

Please sign in to comment.