- About Scala
- Documentation
- Code Examples
- Software
- Scala Developers
non-constants to @throws / @deprecated / ...
Wed, 2010-03-31, 14:46
Hello,
there are some Scala annotations which expect a compile-time
constant argument, e.g. @deprecated, @migrate, @throws,
@SerialVersionUID.
This is not handled systematically right now. For instance,
the following will crash the JVM backend
class C {
val c = classOf[Exception]
@throws(c) def foo {}
}
We can
1) silently ignore the annotation when there's a non-constant argument (like SerialVersionUID)
2) warn or fail late (in the backend)
3) special-case typedAnnotation to check arguments to these known annotations early
4) introduce some mechanism to require a constant argument, e.g.
class throws(@annotation.meta.constant clazz: Class[_]) extends StaticAnnotation
Let me know your opinions.
Lukas
there are some Scala annotations which expect a compile-time
constant argument, e.g. @deprecated, @migrate, @throws,
@SerialVersionUID.
This is not handled systematically right now. For instance,
the following will crash the JVM backend
class C {
val c = classOf[Exception]
@throws(c) def foo {}
}
We can
1) silently ignore the annotation when there's a non-constant argument (like SerialVersionUID)
2) warn or fail late (in the backend)
3) special-case typedAnnotation to check arguments to these known annotations early
4) introduce some mechanism to require a constant argument, e.g.
class throws(@annotation.meta.constant clazz: Class[_]) extends StaticAnnotation
Let me know your opinions.
Lukas
Wed, 2010-03-31, 17:27
#2
Re: non-constants to @throws / @deprecated / ...
On Wed, Mar 31, 2010 at 03:46:24PM +0200, Lukas Rytz wrote:
> there are some Scala annotations which expect a compile-time constant
> argument, e.g. @deprecated, @migrate, @throws, @SerialVersionUID.
Thank you, I've been meaning to bring this up forever. (Although I'm
ostensibly reworking @elidable as per martin's idea, it also is in this
category, and my struggle with this issue is documented therein.)
> 4) introduce some mechanism to require a constant argument, e.g.
> class throws(@annotation.meta.constant clazz: Class[_]) extends
> StaticAnnotation
I am pretty sure that more expressions could be treated as constants for
this purpose than presently are, and it winds up making a big difference
in usability. (This is going to be from memory so forgive any
inaccuracies.) If an annotation requires a constant Int argument then
you have to know about the secret sauce for the constant folder:
object Foo {
val Bar1: Int = 1 // does not work, not singleton type
val Bar2 = 1 // does not work, not marked final
final val Bar3 = 1 // does work
final val Bar4: Int = 1 // can't remember if this works
}
The real killer is the difficulty of applying any abstraction. For
instance there are a couple dozen places with migration annotations with
very tiny variations on this message:
"As of 2.8, this operation creates a new map. To add the elements as a\n"+
"side effect to an existing map and return that map itself, use ++=."
The message is just duplicated across all of those. To my last breath I
will fight such duplication. It's almost worse in documentation than in
code because there are no little static checking tricks to pull -- once
the comments start drifting apart, only an insanely tedious and utterly
thankless effort from some future party will make them consistent with
whatever future reality is. Which of course never happens. It's like
using a time machine to send incorrect documentation to the future.
So if there were some way to write a function which I could annotate as
being guaranteed to do a straight manipulation of constant expressions,
if I could write
def mymsg(s: String) = "blah blah this " + s + " blah blah"
and if the compiler would inline the string addition and constant fold
it for the purposes of annotation, then the world looks pretty again.
Do we think this is unduly difficult and/or solving the wrong problem?
I'll endorse any solution which lets me eliminate the duplication.
Incidentally, another variation on massive-cut-and-paste is that every
annotation in scala.annotation.target has the same or almost the same 40
line doc comment. But maybe the new scaladoc makes it possible to
tackle that one that way?
Wed, 2010-03-31, 17:37
#3
Re: non-constants to @throws / @deprecated / ...
On Wed, Mar 31, 2010 at 6:23 PM, Paul Phillips <paulp@improving.org> wrote:
On Wed, Mar 31, 2010 at 03:46:24PM +0200, Lukas Rytz wrote:That's a fairly tall order. Doing arbitrary compile-time computations is a pretty big change to spec and (probably less so) to implement.
> there are some Scala annotations which expect a compile-time constant
> argument, e.g. @deprecated, @migrate, @throws, @SerialVersionUID.
Thank you, I've been meaning to bring this up forever. (Although I'm
ostensibly reworking @elidable as per martin's idea, it also is in this
category, and my struggle with this issue is documented therein.)
> 4) introduce some mechanism to require a constant argument, e.g.
> class throws(@annotation.meta.constant clazz: Class[_]) extends
> StaticAnnotation
I am pretty sure that more expressions could be treated as constants for
this purpose than presently are, and it winds up making a big difference
in usability. (This is going to be from memory so forgive any
inaccuracies.) If an annotation requires a constant Int argument then
you have to know about the secret sauce for the constant folder:
object Foo {
val Bar1: Int = 1 // does not work, not singleton type
val Bar2 = 1 // does not work, not marked final
final val Bar3 = 1 // does work
final val Bar4: Int = 1 // can't remember if this works
}
The real killer is the difficulty of applying any abstraction. For
instance there are a couple dozen places with migration annotations with
very tiny variations on this message:
"As of 2.8, this operation creates a new map. To add the elements as a\n"+
"side effect to an existing map and return that map itself, use ++=."
The message is just duplicated across all of those. To my last breath I
will fight such duplication. It's almost worse in documentation than in
code because there are no little static checking tricks to pull -- once
the comments start drifting apart, only an insanely tedious and utterly
thankless effort from some future party will make them consistent with
whatever future reality is. Which of course never happens. It's like
using a time machine to send incorrect documentation to the future.
So if there were some way to write a function which I could annotate as
being guaranteed to do a straight manipulation of constant expressions,
if I could write
def mymsg(s: String) = "blah blah this " + s + " blah blah"
and if the compiler would inline the string addition and constant fold
it for the purposes of annotation, then the world looks pretty again.
Do we think this is unduly difficult and/or solving the wrong problem?
I'll endorse any solution which lets me eliminate the duplication.
Maybe, just maybe use @inline. But there are all sorts of unknowns regarding separate compilation, termination, and so on. So this looks like a big project where someone would have to think things through in detail and then male a SID proposal.
Incidentally, another variation on massive-cut-and-paste is that everyYes, this one is easy. Just define and use a variable.
annotation in scala.annotation.target has the same or almost the same 40
line doc comment. But maybe the new scaladoc makes it possible to
tackle that one that way?
Cheers
-- Martin
On Wed, Mar 31, 2010 at 3:46 PM, Lukas Rytz <lukas.rytz@epfl.ch> wrote:
definitely 4) -- Martin