question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Unit-Insertion works differently in Scala 2 & Scala 3

See original GitHub issue

Scala 3 handles unit-insertion differently to Scala 2

Compiler version

3.0.0 vs 2.13.6 - both using Scastie

Minimized code

val f: Boolean => Any = g => {
  if (g)
    1
}
println(f(true))
println(f(false))

Output - using Scala 3…

()
()

plus warning… A pure expression does nothing in statement position; you may be omitting necessary parentheses

Expectation - as in Scala 2…

1
()

plus no warning

Comments

Scala 3 does give the above warning about a pure expression and changing the code to the following works…

val f: Boolean => Any = g => {
  if (g)
    1
  else
    ()
  }
}
println(f(true))
println(f(false))

From @smarter“it looks like unit-insertion is working differently in scala 2 and 3 (in scala 2 it only inserts Unit in the missing branch, in Scala 3 it inserts it in both branches)”

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Reactions:1
  • Comments:5 (2 by maintainers)

github_iconTop GitHub Comments

1reaction
som-snyttcommented, Jun 29, 2021

The behavior is specified:

A short form of the conditional expression eliminates the else-part. The conditional expression if (e1e_1e1​) e2e_2e2​ is evaluated as if it was if (e1e_1e1​) e2e_2e2​ else ().

Also the feature is not called “Unit insertion” (which sounds helpful) but “Value discard” (which sounds possibly dangerous).

0reactions
som-snyttcommented, Jul 21, 2021

I saw a tailrec method of the form def f: Unit = if (b) f and wondered does that even compile. It compiles for Unit result but not for Any. The Scala 2 rule, that if (b) expr means if (b) expr else (), is much easier to reason about, in that there is nothing to reason about.

import annotation._

class C() {
  //type R = Unit
  type R = Any
  @tailrec
  final def f(i: Int): R =
    if (i > 0) {
      println(s"$i ...")
      f(i-1)   // Cannot rewrite recursive call: it is not in tail position
    }
}

object Test extends App {
  val c = new C()
  println(c.f(5))
}
Read more comments on GitHub >

github_iconTop Results From Across the Web

Compatibility Reference | Scala 3 Migration Guide
This chapter describes the compatibility between Scala 2.13 and Scala 3. ... compatibility between the two versions at the different stages of the...
Read more >
Classpath Level | Scala 3 Migration Guide
In your code you can use public types and terms, and call public methods that are defined in a different module or library....
Read more >
New in Scala 3
The exciting new version of Scala 3 brings many improvements and new features. Here we provide you with a quick overview of the...
Read more >
Forward Compatibility for the Scala 3 Transition
To illustrate this scenario, we will start with an empty directory and build an sbt project with Scala 2.13 that has two modules,...
Read more >
Scala 3 Syntax Rewriting
In this chapter we show how you can use the compiler to rewrite your code automatically from the classic Scala 2 style to...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found