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

Default methods #31

Closed
luontola opened this issue Sep 3, 2014 · 7 comments
Closed

Default methods #31

luontola opened this issue Sep 3, 2014 · 7 comments

Comments

@luontola
Copy link
Owner

luontola commented Sep 3, 2014

This issue relates to pull requests #26 and #30

The backport of default methods is based on the technique of modifying all implementors of an interface to add there method implementations that Java 8 would otherwise take from the interface. The actual default method implementations will be moved to a companion class as static methods. Since it won't be possible to modify library interfaces, they should be silently ignored and the default methods in them should not be copied to their implementors.

@luontola luontola mentioned this issue Sep 5, 2014
@luontola
Copy link
Owner Author

luontola commented Sep 5, 2014

The master branch has a work-in-progress implementation of default method support. It can be enabled using feature toggles: build the project with DEFAULT_METHODS=1 mvn clean verify on Linux/OSX/Cygwin. (On Windows a user-level environment variable seems to be needed, instead of just a set DEFAULT_METHODS=1 on the command prompt, so that both Maven and the JVMs launched by Maven can see it.)

@Arneball
Copy link
Contributor

Arneball commented Sep 5, 2014

What will happen if we're doing an incremental compilation kind of thing? If the classpath contains already rewritten interfaces the changed classes processed incrementally will have no idea about the needs for proxies to static $helper-methods, right?
I guess we could annotate the interface with some info in a class annotation for example and look for it when we are looking into the classes interfaces in the hunt for default methods needing proxy. However, that feels error prone and hackish.

Another thing that brought my attention; If we are only creating $helper classes to interfaces that are non library, how can we differentiate them from other classes in the classpath? One thing i was considering was having the NonDelegatingClassLoader keeping a separate classloader for say the first element in the constructors array for classes that are in the project, and the other elements for library classes. The CL could then have a method to check wether that particular interface belongs to the users and not the library classes. But then we would have to impose a constraint on the user to have the classpath as "bin/myclasses:lib.jar:android8.jar:blabla.jar". Is that reasonable?

@luontola
Copy link
Owner Author

luontola commented Sep 5, 2014

Let's just ignore incremental compilation - somebody will probably file a bug if there are problems with it. :) I think the use case that may cause problems is this:

  1. interface and its implementer are compiled
  2. only its implementer is compiled

That will probably cause a comple error on step 2. It may be necessary to have a toggle for enabling/disabling the default method backporting, so that incremental compilers can disable it if it causes problems. Or disable incremental compilers for projects that use default methods.

@luontola
Copy link
Owner Author

luontola commented Sep 5, 2014

Another thing that brought my attention; If we are only creating $helper classes to interfaces that are non library, how can we differentiate them from other classes in the classpath?

Why would it be necessary to differentiate between them?

I just now did some work to simplify processing the classes. First all user classes are visited and analyzed, after which all transformations done, after which all writing of the new bytecode is done. That makes it easier to have complete information for backporting the default methods. See https://github.com/orfjackal/retrolambda/blob/eeb888628090a53cb5196224e216f9413b4f8721/retrolambda/src/main/java/net/orfjackal/retrolambda/Retrolambda.java#L43-L64

@Arneball
Copy link
Contributor

Arneball commented Sep 6, 2014

I think that you had a remark on generating static helpers to lib classes.
But maybe that was only java.* you referred to.

@luontola
Copy link
Owner Author

luontola commented Sep 6, 2014

I don't quite understand what you mean exactly.

My idea is that it's not possible to modify classes that are in JAR files or part of the JDK. Only classes in the program's inputDir can be changed. And because backporting the default methods requires modifying both the interface and all classes which implement it, it'll be required that all of them are together in the same inputDir.

I don't see any other reliable way of backporting default methods. And under this scheme it's trivial to know what are library classes and what are not - based on whether they are in the inputDir or not.

@luontola
Copy link
Owner Author

This has been included in Retrolambda 2.0.0. It's off by default.

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

No branches or pull requests

2 participants