Skip to content
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

Refine handling of CanThrow capabilities #13866

Merged
merged 4 commits into from Nov 8, 2021
Merged

Conversation

odersky
Copy link
Contributor

@odersky odersky commented Nov 3, 2021

  1. Disallow throws clauses over RuntimeExceptions
  2. Don't generate CanThrow capabilities for catches with guards

Fixes #13864
Fixes #13846
Fixes #13849

Restrict catch patterns to `ex: T` with no guard under saferExceptions
so that capabilities can be generated safely.

Fixes scala#13849
@prolativ
Copy link
Contributor

prolativ commented Nov 3, 2021

This doesn't fix #13816 (I'll push the fix after this gets merged to avoid conflicts).
I guess you meant #13864 instead

checkedArgs = checkedArgs.mapconserve(arg =>
checkSimpleKinded(checkNoWildcard(arg)))
else if tycon == defn.throwsAlias
&& checkedArgs.length == 2
&& checkedArgs(1).tpe.derivesFrom(defn.RuntimeExceptionClass)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there really a gain in explicitly preventing users from declaring throwing RuntimeExceptions? And even if we disallow methods like

def foo(): Int throws ArithmeticException = ???

then

def foo()(using CanThrow[ArithmeticException]): Int = ???

will be still valid, right? So this somehow defeats the purpose IMHO

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We won't generate a capability for it, so it's better to communicate that early. But I think ding this for throws clauses is enough. I don't want to start imposing restrictions on general implicit parameters.

| ^
| The capability to throw exception ArithmeticException is missing.
| The capability can be provided by one of the following:
| - A using clause `(using CanThrow[ArithmeticException])`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we don't synthesize instances of CanThrow for subtypes of RuntimeException then this message is rather misleading than helpful, as propagating this capability with using clauses won't make the compilation succeed unless someone creates such an instance by themself. And X throws ArithmeticException won't even compile

@odersky
Copy link
Contributor Author

odersky commented Nov 4, 2021

That's an @implicitiNotFound error message, and IMO it should stay one. There is no way we can customize the message according to what the caught exception is.

@prolativ
Copy link
Contributor

prolativ commented Nov 4, 2021

Then at least maybe we could extend the generic implicitNotFound message for CanThrow with a note that this won't work if E is a subtype of RuntimeException? Also this should be explicitly stated in the docs that you cannot declare throwing RuntimeExceptions.
Anyway, if someone (maybe in a library) defines a method with (using CanThrow[E]) if E <:< RuntimeException (which would still be possible) an then someone else would like to use this method while having saferExceptions enabled, what would be the steps to make this work?

@odersky odersky merged commit 045c8bd into scala:master Nov 8, 2021
@odersky odersky deleted the fix-13846 branch November 8, 2021 09:49
@Kordyjan Kordyjan added this to the 3.1.2 milestone Aug 2, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
3 participants