PRE-PROPOSAL: Source and Encoding keyword

Joseph D. Darcy Joe.Darcy at Sun.COM
Tue Mar 17 23:03:50 PDT 2009


A few general comments here.

While it would be technically possible to add some kind of metadata to a 
Java source file, as such as annotation with a 
javax.lang.model.SourceVersion member, to state its source version, I 
don't find this a compelling problem to solve.  The issue primarily 
occurs when a mixed-version code base is being compiled with a single 
javac invocation:

    Patient: "Doctor, it hurts when I move my arm like this."
    Doctor: "Don't move your arm like that!"

The major impediments to compiling under a single source version in the 
past were the introduction of new keywords in later versions of the 
language.  As Alex Buckley has stated at JavaOne, we don't plan to add 
new keywords to the language, unless they are contextual keywords like 
"module" in JDK 7 which still allow the use of the reserved name for 
fields, methods, etc.

Defining source version metadata information with no semantics doesn't 
strike me as useful or meaningful in terms of a language specification.  
How would that be tested?

Mixing multiple source versions together in one compile could expose 
many compilation artifact details that need to be specified for 
cross-version interoperability.

I don't think this is a worthwhile path to pursue.

-Joe


Reinier Zwitserloot wrote:
> There is no proposal, Jeremy. I made a pre-proposal on the assumption  
> it would sail right through. It didn't, and that was that, until  
> Howard Lovatt re-opened the discussion in support of the proposal.
>
>
> Having a "source" statement that is spec'd to do nothing other than  
> set the CompilationUnit's source property *DOES* resolve the issue of  
> having half your codebase in v1.6 and half in v1.7.
>
> Because half is in v1.7, this is -obviously- only going to run in a  
> JVM v1.7 or above - this has been true in java for years and I don't  
> see how this could possibly change for v1.7 given that the class file  
> format is changing and the module system will be added. A JVM v1.7 - 
> will- be able to run both:
>
>   - class files compiled with javac 1.6, *and*
>   - class files compiled with javac 1.7 with -target 1.7 and -source  
> 1.6 on the command line (or after this proposal, source 1.6 in the  
> file).
>
>
> The only issue someone might have in the middle of porting old code is  
> that the 1.6 code is being compiled as if it is 1.7 code. To highlight  
> how annoying that can be: When java went from 1.4 to 1.5, old code  
> would produce an enormous list of generics warnings. Effectively you  
> had to disable ALL of them until you finished porting all your java  
> code to 1.5; there was no practical way to get a list of genuine  
> generics warnings for your post-porting code.
>
> *THAT* problem is what the 'source' keyword would address. If we had  
> it back then, javac would know NOT to generate those generics warnings  
> for all source files marked source 1.4.
>
>
> The notion that 'source 7;' isn't going to stop you from writing code  
> using Java8 APIs is true, but that's what the module system is for,  
> *NOT* the -source system. I fundamentally think its a mistake to  
> attempt to marry these two ideas together. For example, just now I'm  
> hacking om some HTML parsing using htmlparser, which was written for  
> java 1.4. One of the interfaces I need to implement passes my code a  
> (non-generified) Vector object. Instead  of dealing with the warnings,  
> I decided to just configure eclipse to set the entire project to  
> source compatibility 1.4. Nevertheless, I stil want to use  
> String.replace("foo", "bar"), which is a String method that exists  
> only in java6+. There is no problem, because I'll be running my code,  
> and the htmlparser library, on a JVM6.
>
> Imagining for a moment that both the source keyword exist, and the  
> module system, I'd have to bundle htmlparser into its own module, and  
> set my module bundle to be dependent on jvm.core=6+, and have a source  
> compatibility of java 1.4, lest it rains generics warnings.
>
>
> Once we have both the source and the module system, it becomes trivial  
> to create java files that will actually compile AND run on old  
> versions of the JDK/JVM: If both your source keyword AND your  
> java.core dependency are on java 1.X or below, then your code should  
> compile and run on a JDK/JVM 1.X or above. Whether the JDK itself  
> offers a command line option or other mechanism to enforce this, or  
> whether tool providers such as ant make handy shortcuts for this isn't  
> relevant: Someone can run with it, surely. However, a 'source' keyword  
> would help quite a bit, lest we get the reference situation:
>
> You only use library calls from java1.4 and below, but you are using  
> foreach loops and generics, so a JDK v1.4 won't compile your code, and  
> if you compile it with a JDK1.6, the class files won't run on a JVM1.4.
>
>
>
> There is, again, no need for the backticks, because there will be 0  
> new keywords in java7 (excluding context sensitive keywords). *IF*  
> java 8 includes a proposal that does have new keywords, then it would  
> automatically also require a backtick proposal. But it's not 2012 yet.
>
> javac (the compiler itself) will support -source 1.6, if history is  
> any indication. I think making that commitment at this point in time  
> is a no-brainer.
>
> There is no need for a compiler to neccessarily do the best possible  
> option when a "source 1.6;" is encountered. If that version of javac  
> no longer has the capability to parse v1.6 code, then it can  
> gracefully exit with an appropriate error message, instead of a weird  
> batch of parsing mismatches that leaves the person attempting to dust  
> off some 10 year old code none the wiser.
>
>   --Reinier Zwitserloot
>
>
> On Mar 16, 2009, at 03:02, Jeremy Manson wrote:
>
>   
>> Reinier,
>>
>> Fundamentally, I think we are in disagreement that the source keyword
>> that you are suggesting provides any useful semantics.  I haven't seen
>> your proposal (I can't find the message where you posted it?), but
>> here is one of your motivations from your pre-proposal:
>>
>>     
>>> Leaving half your sourcebase in v1.6 and the
>>> other half in v1.7 is pretty much impossible today, it's all-or-
>>> nothing.
>>>       
>> Having a "source" statement that is spec'd to do nothing other than
>> set a property in the CompilationUnit doesn't actually address this,
>> in the ways in which I said it didn't before:
>>
>> 1) My API / Classfile comment was not about changes to classfiles, it
>> was about the fact that your proposal doesn't address the fact that
>> different APIs are available to different Java versions.  "source 7;"
>> isn't going to stop the code I write from using some new API
>> introduced in Java 8, just as "-source 5" as a parameter to javac
>> doesn't stop me from using ConcurrentSkipListMap.  I know your
>> proposal isn't intended to address this, but I think any proposal that
>> provides versioning needs to address this, because you aren't keeping
>> half your codebase in Java 6 in any meaningful way if that code can
>> use Java 7 APIs.
>>
>> 2) I know that your proposal isn't intended to address the problem
>> that the backticks were intended to solve, but I think that any
>> proposal that provides versioning needs to address this, because it is
>> difficult to keep half of your codebase in Java 7 if you can't call
>> out to some APIs that your Java 6 code provides because their names
>> clash wit keywords.
>>
>> 3) All that javac says about -source is that it provides source
>> compatibility with the specified release.  However, there are releases
>> it doesn't support (anymore), and there are targets that can't be
>> generated from specific source versions.  You need, at the very least,
>> to define what sources are guaranteed to be supported.  You can't
>> leave half your codebase in Java 6 if no compiler supports Java 6.
>>
>> You seem to be willing to leave these things up in the air, which I
>> think is easier when it is an option to the javac program, where this
>> is offered as a convenience, but not fine for a language
>> specification, when the source code needs to be portable to any Java 7
>> compliant compiler.
>>
>> At any rate, Joe already stepped in and said that the proposal as it
>> stood was too complicated for Project Coin:
>>
>> http://mail.openjdk.java.net/pipermail/coin-dev/2009-March/000298.html
>>
>> Jeremy
>>
>> On Sun, Mar 15, 2009 at 5:45 PM, Reinier Zwitserloot
>> <reinier at zwitserloot.com> wrote:
>>     
>>> Neal:
>>>
>>> As I've mentioned at least twice on coin-dev already, the JLS only  
>>> needs to
>>> specify how the 'source' keyword sets the 'source' property of the
>>> CompilationUnit that contains the source keyword. As far as the JLS  
>>> is
>>> concerned, this is a string value that has no further meaning. It's  
>>> a bit
>>> like a comment in this sense. To be crystal clear: ** The JLS will  
>>> NOT
>>> specify what is supposed to happen when you write "source 1.1;" in  
>>> a JLSv3
>>> view of the source file! **
>>>
>>> The effect of a source property in a CompilationUnit will however be
>>> specified in the documentation for java compilers.
>>>
>>> Jeremy:
>>>
>>> 1) No, -source does not show up in the class file at all, so  
>>> obviously it
>>> wouldn't for a source keyword, either. Therefore the API / Classfile
>>> compatibility issue is 0.
>>>       
>>     
>>> 2) No, backticks aren't neccessary for the source keyword to work.  
>>> java7 is
>>> not going to be source incompatible with java6 and does not add new  
>>> keywords
>>> (well, module, but it'll be context sensitive). Compatibility  
>>> issue: 0. It
>>> would certainly help make it easier to make breaking changes in  
>>> java 7, if
>>> at that time a proposal comes along that makes sense but would be  
>>> better
>>> with a few breaking changes.
>>>       
>>     
>>> 3) There is no need for much *JLS* documentation at all.  
>>> CompilationUnits
>>> get a 'source' property, which is a string value. That's where it  
>>> ends as
>>> far as the JLS is concerned. It has no meaning within the JLS. Just a
>>> string, that's all. The documentation for javac has quite a bit to  
>>> say about
>>> this, but that's nothing new: The -source parameter has the exact  
>>> same
>>> function and is already documented. This documentation needs a very  
>>> minor
>>> update.
>>>
>>> 4)  "source 1.7;" is really neccessary at the top of the file. It  
>>> is crucial
>>> meta-data without which you cannot make any sense of a java  
>>> CompilationUnit.
>>> Is 'assert' a keyword or an identifier? What about strictfp? Are  
>>> inner
>>> classes legal? Is @Override on an interface-inherited method legal,  
>>> or an
>>> error? Should lack of generics result in a warning, or should any  
>>> generics
>>> actually be indicated as a compile-time error? You don't, of  
>>> course, -have-
>>> to put it there, but its suggested, and I expect IDEs and style  
>>> checkers
>>> will start warning when its missing. This is somewhat akin to package
>>> statements. Those are -really- neccessary as well. a  
>>> CompilationUnit's
>>> target package isn't a command line parameter for the same (good)  
>>> reason.
>>> This metadata is not dependent on a compile run, it is solely  
>>> dependent on
>>> the source file itself, and should therefore be inside it.
>>>
>>>  --Reinier Zwitserloot
>>>
>>>
>>>
>>> On Mar 16, 2009, at 00:58, Jeremy Manson wrote:
>>>
>>>       
>>>> Reinier,
>>>>
>>>> I wrote out a long response to each of your points, but I realized
>>>> that perhaps what it boiled down to was something I said in my
>>>> previous message: "I'm not objecting to versioning in principle,  
>>>> but I
>>>> think there are enough unanswered questions that this proposal is
>>>> probably beyond the scope of "small changes"."
>>>>
>>>> You are saying that if I have a problem with something, it is the
>>>> -source flag.  You are absolutely right: I have problems with the
>>>> -source flag.  Those problems should be sorted out before we include
>>>> it in the language.  Each solution to each of these problems makes
>>>> this change larger:
>>>>
>>>> 1) API / Classfile compatibility
>>>>
>>>> 2) Backticks for identifiers
>>>>
>>>> 3) A need for thorough documentation for each potential version we
>>>> support.  (You seem to be suggesting that this would be
>>>> implementation-dependent, but that's unlike everything else in the
>>>> language.  Java is historically opposed to things that are
>>>> implementation-dependent.  Part of the selling point of Java is that
>>>> code written for / compiled on a version of Java 7 will work with /
>>>> compile on all compliant Java 7 implementations.).
>>>>
>>>> 4) Is "source" really necessary at the top of the file (you seem  
>>>> to be
>>>> agreeing that it is), and if so, is that what we actually want?
>>>>
>>>> I also think it would be worthwhile finding out how this proposal  
>>>> gels
>>>> with the module system they are introducing.
>>>>
>>>> Fundamentally, it seems to me to be a large problem to solve, and I
>>>> think the right answer is to start a proper JSR and make sure you  
>>>> get
>>>> it right.
>>>>
>>>> It is, of course, by no means important to Project Coin that I (as  
>>>> one
>>>> person) happen to think that this change is (or should be) too  
>>>> large.
>>>> But I suspect that I'm not the only one.
>>>>
>>>> Jeremy
>>>>         
>>>       
>
>
>   




More information about the coin-dev mailing list