scala / scala3

The Scala 3 compiler, also known as Dotty.
https://dotty.epfl.ch
Apache License 2.0
5.82k stars 1.05k forks source link

Exceptions inexplicably swallowed when inlined context functions interact #21187

Open keynmol opened 2 months ago

keynmol commented 2 months ago

Compiler version

Tested it with 3.3.3, 3.3.4-RC1, 3.4.2, 3.5.0-RC4

Minimized code

def oops(msg: String) = sys.error(msg)

class Zone
object Zone:
  inline def apply[T](inline f: Zone ?=> T): T = f(using new Zone)

inline def zone[A](inline f: Zone ?=> A) = Zone.apply(z => f(using z))

@main def hello = 
  // this swallows exceptions!
  zone(oops("here"))

  // this doesn't
  Zone(oops("not here"))

Output

Exception in thread "main"java.lang.RuntimeException: not here
        at scala.sys.package$.error(Unknown Source)
        at test$package$.oops(Unknown Source)
        at test$package$.hello(Unknown Source)
        at hello.main(Unknown Source)
        at <none>.main(Unknown Source)

Expectation

I expected the first call to oops to throw the error, but it's quietly swallowed. This is extremely unsettling, I have no idea what other places I have where exceptions are swallowed like this

Noticed this when converting a project from SN 0.4 to SN 0.5 which ships a Zone.apply that uses context functions out of the box (I used to have zone helper before, and it worked fine)

som-snytt commented 2 months ago

Did you intend

inline def zone[A](inline f: Zone ?=> A): A = Zone.apply(z ?=> f(using z))

otherwise you get a closure and this throws

zone(oops("here again"))(new Zone)
JD557 commented 2 months ago

I wonder if there could be a flag to warn when a context function doesn't use the context.

For example

// With the flag enabled, this would trigger a warning
val x: Int ?=> Int = 5

// Expecting the code to be rewritten as
val x: Int ?=> Int = _ ?=> 5

This might be annoying for some DSLs, so this warning would probably have to be disabled by default. though 🤔