Skip to content

Conversation

@NthPortal
Copy link
Contributor

@NthPortal NthPortal commented Sep 3, 2018

Add subclasses of ControlThrowable which strictly disable stack trace
writing and exception suppression.

This has implications for Java's try-with-resources and scala.util.Using,
both of which suppress exceptions.

Fixes scala/bug#11116

@NthPortal NthPortal added the WIP label Sep 3, 2018
@scala-jenkins scala-jenkins added this to the 2.13.0-RC1 milestone Sep 3, 2018
@NthPortal
Copy link
Contributor Author

@viktorklang could I get your thoughts on this?

@edmundnoble
Copy link
Contributor

Since there is no exception-caching going on here, I'd suggest a different prefix like Untraced.

I'm also wondering what the relationship between these classes and scala.util.control.NoStackTrace is.

override def fillInStackTrace(): Throwable = super[Throwable].fillInStackTrace()
}

class Cached(message: String)
Copy link
Contributor

Choose a reason for hiding this comment

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

also, in what sense is this "cached"? It appears to just be a Throwable with neither stack trace nor suppression.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It is called "cached" because it is intended to be used for cached ControlThrowables, where e.g. having suppressed exceptions would lead to memory leaking. For non-cached ControlThrowables (e.g. NonLocalReturnControl), though a suppressed exception will probably get ignored anyway, it doesn't hurt to add a suppressed exception because the NonLocalReturnControl will go out of scope and it will all get GCed anyway.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I am open to other names

Copy link
Contributor

Choose a reason for hiding this comment

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

Hmm, ok. I'm not a fan of the name. Stateless might be better, or Immutable, or even Cacheable.

My brilliant idea of "what if we just override addSuppressed as a no-op, too" is stymied by Java's library designers thinking they know better...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm okay with Cacheable. Immutable sounds weird, cuz exceptions aren't usually thought of as mutable. Maybe Stateless, but I wouldn't usually think of an exception as statefull either.

I threw this together in like 15 minutes at 3am, so the name wasn't intended to be final anyway xD

@NthPortal NthPortal changed the title [WIP] Add cached ControlThrowables [WIP] Add cached ControlThrowables [ci: last-only] Sep 3, 2018
*/
trait ControlThrowable extends Throwable with NoStackTrace

object ControlThrowable {
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this wrapper object needed?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

idk. I wanted it to be clear that they're all ControlThrowables

@NthPortal
Copy link
Contributor Author

@edmundnoble they (like NonLocalReturnControl) are stricter, and won't ever have a stack trace regardless of what Java properties are set. The only reason they extend NoStackTrace is because ControlThrowable does, and they extend ControlThrowable.

@NthPortal NthPortal changed the title [WIP] Add cached ControlThrowables [ci: last-only] [WIP] Add cache-able ControlThrowables [ci: last-only] Sep 8, 2018
@SethTisue
Copy link
Member

@NthPortal should this stay open...?

@NthPortal
Copy link
Contributor Author

@SethTisue I don't know. I think it would be good to merge it, or at least discuss whether or not it is a viable solution to the problem, but it didn't seem to really get many eyes on it. I don't think I ever got @viktorklang (with whom I tangentially discussed this topic wrt scala.util.Using) to have a look at it either.

It doesn't seem too controversial to me (though perhaps the names could use some work), though I know we're supposed to be in a feature freeze.

If you think it needs more motivation, I could perhaps try to motivate it better.

trait ControlThrowable extends Throwable with NoStackTrace

object ControlThrowable {
sealed trait CacheableBase extends ControlThrowable {
Copy link
Contributor

Choose a reason for hiding this comment

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

This name doesn't really reflect what it does though.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The base trait is mainly there to reduce code duplication, and should actually be private if possible (I don't know if the compiler will allow it)

override def fillInStackTrace(): Throwable = this
}

class Cacheable(message: String)
Copy link
Contributor

Choose a reason for hiding this comment

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

This ought to be CacheableThrowable, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, but (a) ControlThrowable already has Throwable in its name, and (b) it's the "default", so I wanted it to have a shorter name.

@viktorklang
Copy link
Contributor

@NthPortal Apologies, I totally dropped the ball on this one. :(

@lrytz
Copy link
Member

lrytz commented Nov 7, 2018

It looks good. There should more doc comments why it exists and how it works internally. And the name is not obvious, it only makes sense once you know what it does.. Maybe something more blunt like IgnoringSuppressed?

@NthPortal
Copy link
Contributor Author

@viktorklang no worries

@NthPortal
Copy link
Contributor Author

NthPortal commented Nov 9, 2018

@lrytz I agree with you that Cacheable is not a great name.

I'm not a huge fan of IgnoringSuppressed, as it's really long - it will yield RuntimeExceptionIgnoringSuppressed (or similar), which is unpleasantly long. It also doesn't feel like it combines well with the exception type, but maybe that's just me.

The shed could definitely use a paint job

@NthPortal
Copy link
Contributor Author

Another possible name: NoSuppression? NoSuppressionError? idk. sounds a bit off.

Suppressionless? That's definitely not a word, but it's would be an adjective if it was a word, which makes it sound better I think (e.g. SuppressionlessException).

More ideas welcome.

@som-snytt
Copy link
Contributor

It's very tempting for me to join in the discussion about naming, but I think 2.13 is the time to bite the bullet and just do the simple thing, at the cost of very minor migration discomfort.

Obviously, I think the linked PR is simple. Maybe there is a real-world use case for requiring a mix-in, but what could that be? throw new IOException with ControlThrowable {} I mean a non-perverse use case.

@som-snytt
Copy link
Contributor

I also wondered if trait parameters saves traitness here, but I read in the sip that no secondary ctors, so making message optional is harder. (Maybe a default arg would be OK? But less efficient. ControlThrowables should be lightweight as possible.)

@NthPortal
Copy link
Contributor Author

Closing in favour of #7413. Will reopen if that one doesn't pan out.

@NthPortal NthPortal closed this Nov 18, 2018
@SethTisue SethTisue removed this from the 2.13.0-RC1 milestone Nov 19, 2018
@NthPortal NthPortal deleted the topic/control-throwable/PR branch December 15, 2018 06:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants