I'm running into an unexpected (only for me?) ScalaC behavior.
The TL;DR is that the following is a recreation of an issue I saw while trying to migrate a codebase from maven to bazel. One of the main focuses of this migration is to try to minimize the dependencies each class needs for compilation so that builds will be triggered only when needed.
Unfortunately what I saw is that given ClassIndirectlyNeedingFoo(uses)->ClassUsingFoo(uses)->Supplier the compilation of ClassIndirectlyNeedingFoo breaks if Supplier is not on the classpath.
The full details are here (https://github.com/ittaiz/scalac-troubleshooting).
If anyone knows why scalac behaves like this I'd really appreciate it.
Thanks!
BTW, Supplier is not in the source or bytecode of ClassIndirectlyNeedingFoo...
Ok so the short answer is that Why isn't totally clear to anyone (see #4). What is clear is that it's known scalac sometimes needs more dependencies than one would think and it's also clear that sometimes when this happens it's a bug.
Furthermore from a discussion with Jason Zaugg on Gitter he seems to think my above issue is just apart of a family of bugs like the one linked above.
As Seth linked in the comments the ScalaCenter has accepted a proposal (original PR) for clarifying this area.
Most related to this issue are the four proposals there:
Improvements to the user experience of stub errors, centered around the Statement: that they are an expected common case, rather than a
rare, unexpected, or fatal condition.
Reduction of the number of cases that result in stub errors... ie, allowing more usecases that currently result in a stub error to
successfully compile, and thus allowing for fewer direct dependencies.
A compiler flag to require import statements for all symbols used during compilation (including those not otherwise mentioned in the
source). For symmetry with -Ywarn-unused-imports, this option might
potentially be called -Ywarn-undeclared-imports. It would primarily
assist with making the transition from transitive to direct
dependencies, rather than helping to maintain a build that is already
using direct dependencies. (as suggested by
#posco and
#adriaanm)
An expansion of the Scala Language Specification to list all cases in which a symbol from another compilation unit must be present on the
classpath, including: 1) subclassing, 2) return types of superclasses'
public methods, 3) direct reference, 4) etc.
It was agreed to go ahead with #3 though I don't know when the work will commence.
Eugeene Burmako, who co-authored the proposal, started prototyping the solution and I've made a small change on top of that.
For now this will have to do for my problem.
Related
Is there a reason the Eclipse content assits doesn't work in/around lambdas? In a normal case Eclipse usually does this after writing a dot:
Which works just fine like anywhere else. However just a couple of lines later I get nothing:
Both objects are of the same type. Unfortunately I use these all the time as they make everything much faster and I don't understand why it works in one lambda and not the other.
Attempting an explanation (you asked for a reason): parsing lambda expressions in Java is a technical challenge, as the Java grammar was not made for parser generators. Code completion, OTOH, inevitably depends on parsing incomplete code, i.e., heuristics must be used to continue parsing after a syntax error. These two just don't nicely cooperate. As a result in some situations your incomplete code will look like garbage to the compiler and hence content assist is not able to figure out, what would be meaningful proposals.
The applied heuristics are constantly being improved. I recommend trying your examples on a recent milestone build. If the problem still exists, you might help the team by filing a bug providing a code example, and describing your expectations and what actual behavior you observe.
I have used a few Scala DSL's, and was wondering whether developing one, can also cater for DSL-specific compilation erros. The idea is that a domain specific language would also have domain specific compilation error messaging, aiding the domain expert in getting things right. Is that possible in Scala?
One of the things that might be useful is annotation.implicitNotFound. You can customize compiler errors on unresolved implicits with it's help.
As #Dylan pointed out, if you're hacking Scala with macroses you can use c.abort, c.info and c.error to make compiller yield some custom error/extra info.
In this case annotation.compileTimeOnly might also be helpful. It allows to restrict usage of some parts of your code and produce custom error message if someone tries to access it.
sbt maintains dependencies between tasks, and the resulting graph can be reasoned about fairly easily. On the other hand, skimming the source code, it seems like the incremental compilation logic is a lot more opaque. I'd like to be able to do the following things:
Say the equivalent of "if I modified this interface [in this way], what would get invalidated?"
Build a graph of how modifying different class interfaces affects the rest of the build. Graphing scala import dependencies isn't a particularly good approximation of this, given how complicated implicit dependencies can get in Scala. It seems like sbt must maintain this information in some form or another to do incremental compilation, so I "just" need to figure out how to access it and hope that it's in a form suitable for my use case.
Are either of these feasible? I'm not opposed to writing sbt plugins, but would appreciate hints about how to proceed.
Edit: it looks like Relation's usesInternalSrc(dep: File): Set[File] could be promising. Does that capture all of sbt's dependency knowledge?
Edit 2: even more promising, there's a DotGraph object inside the sbt source tree. It has no documentation and google doesn't have any human-readable text about it. If I can figure out how to use it I'll post an answer.
Sample console-project session:
> val (s, a) = runTask(compile in Compile, currentState)
> DotGraph.sources(a.relations, file("source-graph"), Nil)
source-graph is a directory that will contain two dot files, one with source dependencies and one with binary. You can alternatively directly interact with a.relations of type Relations, as suggested in the question, and which does capture all of sbt's dependency knowledge. In 0.13 there will also be information about which dependencies are due to inheriting from something in another source file.
In terms of how modifying a source file affects invalidation, it is very coarse grained. Any change to any non-private signature marks a source as changed. In 0.12 and earlier, this will at least invalidate direct dependencies and maybe more. In 0.13, this will invalidate direct dependencies only, except for inherited dependencies, which are transitively invalidated. There is currently no way to see what will be invalidated when a source file's non-private API is modified except by doing it.
I've been programming in Scala for a while and I like it but one thing I'm annoyed by is the time it takes to compile programs. It's seems like a small thing but with Java I could make small changes to my program, click the run button in netbeans, and BOOM, it's running, and over time compiling in scala seems to consume a lot of time. I hear that with many large projects a scripting language becomes very important because of the time compiling takes, a need that I didn't see arising when I was using Java.
But I'm coming from Java which as I understand it, is faster than any other compiled language, and is fast because of the reasons I switched to Scala(It's a very simple language).
So I wanted to ask, can I make Scala compile faster and will scalac ever be as fast as javac.
There are two aspects to the (lack of) speed for the Scala compiler.
Greater startup overhead
Scalac itself consists of a LOT of classes which have to be loaded and jit-compiled
Scalac has to search the classpath for all root packages and files. Depending on the size of your classpath this can take one to three extra seconds.
Overall, expect a startup overhead of scalac of 4-8 seconds, longer if you run it the first time so disk-caches are not filled.
Scala's answer to startup overhead is to either use fsc or to do continuous building with sbt. IntelliJ needs to be configured to use either option, otherwise its overhead even for small files is unreasonably large.
Slower compilation speed. Scalac manages about 500 up to 1000 lines/sec. Javac manages about 10 times that. There are several reasons for this.
Type inference is costly, in particular if it involves implicit search.
Scalac has to do type checking twice; once according to Scala's rules and a second time after erasure according to Java's rules.
Besides type checking there are about 15 transformation steps to go from Scala to Java, which all take time.
Scala typically generates many more classes per given file size than Java, in particular if functional idioms are heavily used. Bytecode generation and class writing takes time.
On the other hand, a 1000 line Scala program might correspond to a 2-3K line Java program, so some of the slower speed when counted in lines per second has to balanced against more functionality per line.
We are working on speed improvements (for instance by generating class files in parallel), but one cannot expect miracles on this front. Scalac will never be as fast as javac.
I believe the solution will lie in compile servers like fsc in conjunction with good dependency analysis so that only the minimal set of files has to be recompiled. We are working on that, too.
The Scala compiler is more sophisticated than Java's, providing type inference, implicit conversion, and a much more powerful type system. These features don't come for free, so I wouldn't expect scalac to ever be as fast as javac. This reflects a trade-off between the programmer doing the work and the compiler doing the work.
That said, compile times have already improved noticeably going from Scala 2.7 to Scala 2.8, and I expect the improvements to continue now that the dust has settled on 2.8. This page documents some of the ongoing efforts and ideas to improve the performance of the Scala compiler.
Martin Odersky provides much more detail in his answer.
You should be aware that Scala compilation takes at least an order of magnitude longer than Java to compile. The reasons for this are as follows:
Naming conventions (a file XY.scala file need not contain a class called XY and may contain multiple top-level classes). The compiler may therefore have to search more source files to find a given class/trait/object identifier.
Implicits - heavy use of implicits means the compiler needs to search any in-scope implicit conversion for a given method and rank them to find the "right" one. (i.e. the compiler has a massively-increased search domain when locating a method.)
The type system - the scala type system is way more complicated than Java's and hence takes more CPU time.
Type inference - type inference is computationally expensive and a job that javac does not need to do at all
scalac includes an 8-bit simulator of a fully armed and operational battle station, viewable using the magic key combination CTRL-ALT-F12 during the GenICode compilation phase.
The best way to do Scala is with IDEA and SBT. Set up an elementary SBT project (which it'll do for you, if you like) and run it in automatic compile mode (command ~compile) and when you save your project, SBT will recompile it.
You can also use the SBT plug-in for IDEA and attach an SBT action to each of your Run Configurations. The SBT plug-in also gives you an interactive SBT console within IDEA.
Either way (SBT running externally or SBT plug-in), SBT stays running and thus all the classes used in building your project get "warmed up" and JIT-ed and the start-up overhead is eliminated. Additionally, SBT compiles only source files that need it. It is by far the most efficient way to build Scala programs.
The latest revisions of Scala-IDE (Eclipse) are much better atmanaging incremental compilation.
See "What’s the best Scala build system?" for more.
The other solution is to integrate fsc - Fast offline compiler for the Scala 2 language - (as illustrated in this blog post) as a builder in your IDE.
But not in directly Eclipse though, as Daniel Spiewak mentions in the comments:
You shouldn't be using FSC within Eclipse directly, if only because Eclipse is already using FSC under the surface.
FSC is basically a thin layer on top of the resident compiler which is precisely the mechanism used by Eclipse to compile Scala projects.
Finally, as Jackson Davis reminds me in the comments:
sbt (Simple build Tool) also include some kind of "incremental" compilation (through triggered execution), even though it is not perfect, and enhanced incremental compilation is in the work for the upcoming 0.9 sbt version.
Use fsc - it is a fast scala compiler that sits as a background task and does not need loading all the time. It can reuse previous compiler instance.
I'm not sure if Netbeans scala plugin supports fsc (documentation says so), but I couldn't make it work. Try nightly builds of the plugin.
You can use the JRebel plugin which is free for Scala. So you can kind of "develop in the debugger" and JRebel would always reload the changed class on the spot.
I read some statement somewhere by Martin Odersky himself where he is saying that the searches for implicits (the compiler must make sure there is not more than one single implicit for the same conversion to rule out ambiguities) can keep the compiler busy. So it might be a good idea to handle implicits with care.
If it doesn't have to be 100% Scala, but also something similar, you might give Kotlin a try.
-- Oliver
I'm sure this will be down-voted, but extremely rapid turn-around is not always conducive to quality or productivity.
Take time to think more carefully and execute fewer development micro-cycles. Good Scala code is denser and more essential (i.e., free from incidental details and complexity). It demands more thought and that takes time (at least at first). You can progress well with fewer code / test / debug cycles that are individually a little longer and still improve your productivity and the quality of your work.
In short: Seek an optimum working pattern better suited to Scala.
I have just finished the first version of a Java 6 compiler plugin, that automatically generates wrappers (proxy, adapter, delegate, call it what you like) based on an annotation.
Since I am doing mixed Java/Scala projects, I would like to be able to use the same annotation inside my Scala code, and get the same generated code (except of course in Scala). That basically means starting from scratch.
What I would like to do, and for which I haven't found an example yet, is how do I generate the code inside a Scala compiler plugin in the same way as in the Java compiler plugin. That is, I match/find where my annotation is used, get the AST for the annotated interface, and then ask the API to give me a Stream/Writer in which I output the generated Scala source code, using String manipulation.
That last part is what I could not find. So how do I tell the API to create a new Scala source file, and give me a Stream/Writer/File/Handle, so I can just write in it, and when I'm done, the Scala compiler compiles it, within the same run in which the plugin was invoked?
Why would I want to do that? Firstly, because than both plugins have the same structure, so maintenance is easy. Secondly, I want to open source it, and there is just no way to support every option that anyone would want, so I expect potential users to want to extend the generation with their own code. This will be a lot easier for them if they just have to do some printf(), instead of learning the AST API (this also applies to me).
Short answer:
It can't be done
Long answer:
You could conceivably generate your source file and push that through a parser instance within your plugin. But not in any way that's likely to be of any use to you, because you'd now have a bigger problem to contend with:
In order to grab all the type/name information for generating the delagate/proxy, you'll have to pick up the annotated type's AST after it has run through both the namer and typer phases (which are inseperable). The catch is that any attempts to call your generated code will already have failed typechecking, the compiler will have thrown an error, and any further bets are off.
Method synthesis is possible in limited cases, so long as you can somehow fool the typechecker for just long enough to get your code generated, which is the trick I pulled with my Autoproxy 'lite' plugin. Even then, you're far better off working with TreeDSL to generate code instead of pumping out raw source.
Kevin is entirely correct, but just for completeness it's worth mentioning that there is another alternative - write a compiler plugin that generates source. This is the approach that I've adopted in Borachio. It's not a very satisfactory solution, but it can be made to work.
Edit - I just reread your question and realised that you're actually asking about generating source anyway
So there is no support for this directly, but it's basically just a question of opening a file and writing the relevant "print" statements. There's no way to invoke the compiler "inside" a plugin AFAIK, but I've written an sbt plugin which hides most of the complexity of invoking the compiler twice.