-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Rewriting tool should warn on extending DelayedInit #559
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
Comments
ping @samuelgruetter |
@odersky is there a plan to completely remove |
Yes, we should remove delayedInit. But given the 900 test failures I think it would be reasonable if the
becomes
{ ... }} If we have macro annotations, we could envision having syntactic sugar like
for this. App can be left as a convenience class in dotty, but it would not
On Wed, May 13, 2015 at 1:16 PM, Denys Shabalin [email protected]
Martin Odersky |
@odersky For tests, I've added an superclass that has a main method: dotty-staging@28bb276 dotty-staging@28bb276 This is almost equivalent to moving statements into the body of class, the only difference is that tests are actually now executed before main method is called. |
|
Honestly, I dislike the |
I like |
@Application / @app, either is fine with me. On Wed, May 13, 2015 at 2:32 PM, kerr [email protected] wrote:
Martin Odersky |
Lets create wiki page that lists all of the expected incompatibilities starting with this one. (Unfortunately I don't have the permission to do this.) |
@densh the list of incompatibilities is currently maintained as a bullet-point list in the readme of the rewrite tool. So Dmitry's |
App class itself relies on |
Bikeshedding a little:: object Test1 {
def main = {
}
} And have scala add a main-method bridge. If you want the arguments, write the full main method. Or allow the slightly less jarring signature (as in Java); object Test2 {
def main(args: String*) = {
}
} I prefer this over @app object Test {
val x = 42
}
object Test2 {
def main(a: Array[String]) = {
Test.x // null under Scala 2(with a warning). Maybe this wouldn't compile under the macro annotation version?
}
} |
While I've got the paint out, here's another colour: @app class C { println("foo") }
@app class D(args: String*) { println(args.length) } class C { println("foo"); <static> def main(args: Array[String]) = new C() }
class D(args: String*) { println(args.length); <static> def main(args: Array[String]) = new C(WrappedArray(args)) } |
On Thu, May 14, 2015 at 1:52 AM, Jason Zaugg [email protected]
Cheers
—
Martin Odersky |
Maybe we can allow top-level methods in some form (e.g. automatically wrap them into objects internally). This way it won't be confusing and will still be low-overhead syntax-wise. |
But I guess the natural encoding of a top-level method
would be
So we still would need a way to tell that we want a
On Thu, May 14, 2015 at 10:50 AM, Denys Shabalin [email protected]
Martin Odersky |
Maybe top-level methods named |
Sorry to see App go away (as a restricted usage of DelayedInit). It's handy because it moves code out of the static class initializer, which was a headache for performance-minded REPL users. |
The hope is that we will be able to use some kind of annotation macros to @app object Foo { ... } We don't have that yet defined though.
On Sat, Jun 6, 2015 at 10:34 PM, som-snytt [email protected] wrote:
Martin Odersky |
Scalafix now has a Should there be a rewrite for code that uses |
@olafurpg Does your rewrite deal with things like object Main extends App {
println("Starting the app")
val foo = { println("Initializing foo"); "hello" }
init()
def init(): Unit = println(foo)
} ? |
@sjrd That gets rewritten into object Main {
def main(args: Array[String]): Unit = {
println("Starting the app")
val foo = { println("Initializing foo"); "hello" }
init()
def init(): Unit = println(foo)
}
} which prints the same output as before
What would you expect it to rewrite into? |
Ah I see. The current object Main extends Object with App {
...
final <stable> <accessor> def initCode(): scala.collection.mutable.ListBuffer = Main.this.initCode;
private[this] val initCode: scala.collection.mutable.ListBuffer = _;
@deprecated("The delayedInit mechanism will disappear.", "2.11.0") override def delayedInit(body: Function0): Unit = scala.App$class.delayedInit(Main.this, body);
@deprecatedOverriding("main should not be overridden", "2.11.0") def main(args: Array[String]): Unit = scala.App$class.main(Main.this, args);
private[this] val foo: String = _;
<stable> <accessor> def foo(): String = Main.this.foo;
def init(): Unit = scala.this.Predef.println(Main.this.foo());
final <synthetic> def delayedEndpoint$Main$1: Unit = {
scala.this.Predef.println("Starting the app");
Main.this.foo = {
scala.this.Predef.println("Initializing foo");
"hello"
};
Main.this.init();
()
};
def <init>(): Main.type = {
Main.super.<init>();
scala.App$class./*App$class*/$init$(Main.this);
Main.this.delayedInit(new Main$delayedInit$body(Main.this));
()
}
};
final <synthetic> class Main$delayedInit$body extends runtime.AbstractFunction0 {
...
} where |
Your rewrite won't be able to support cases where there are methods in the object that override/implement methods from the superclass. |
Good catch @sjrd I opened scalacenter/scalafix#215, let's move the discussion there. It should be possible to keep overriden members in the object's template body, although care needs to be taken with eagerly evaluated vals/vars. |
Out of 1500 run tests that fail, 900 fail due to them extending
scala.App
, which relies onDelayedInit
, that is not supported.The text was updated successfully, but these errors were encountered: