PROPOSAL: Auto-assignment Parameters

Mark Mahieu markmahieu at googlemail.com
Tue Mar 24 18:07:25 PDT 2009


HTML version + prototype available at http://slm888.com/javac



Auto-assignment Parameters v0.1


AUTHOR(S):

Mark Mahieu


OVERVIEW

FEATURE SUMMARY: Should be suitable as a summary in a language tutorial.

An additional form of constructor parameter which provides automatic
assignment of the parameter's value to an instance field.  These parameters
are implicitly declared as final to prevent unintentional assignments to the
wrong variable in the constructor body.


MAJOR ADVANTAGE: What makes the proposal a favorable change?

Reduces the likelihood of some common coding errors relating to assignment
of fields in a constructor, including those where:

    * a field is assigned to itself
    * the parameter is assigned instead of the field
    * the assignment to the field is missing entirely

These and other errors are often caused by typos or code refactoring.


MAJOR BENEFIT: Why is the platform better if the proposal is adopted?

A programmer's intent is more clearly expressed for the extremely common
case of assigning a constructor parameter directly to an instance field with
the same name.


MAJOR DISADVANTAGE: There is always a cost.

As with any sugar which enables a more concise way of expressing an existing
idiom, programmers may be tempted to use it even when the original form
would be more appropriate.


ALTERNATIVES: Can the benefits and advantages be had some way without a
language change?

IDEs and tools such as FindBugs are good at warning about the kind of errors
mentioned above, however since the code in question is usually still valid
to the compiler, they are limited in what action they can take by default.

A language change can combine the ability to avoid these errors entirely
with a more expressive idiom, resulting in an increased signal to noise
ratio for readers of that code.



EXAMPLES

SIMPLE EXAMPLE: Show the simplest possible program utilizing the new
feature.

    class C {
        int i;
        C(int this.i) {}
    }


ADVANCED EXAMPLE: Show advanced usage(s) of the feature.


    class Proposal {

        private final String name;
        private final String author;
        private boolean suitableForCoin;
        private Integer score;

        public Proposal(String this.name,
                        String this.author,
                        boolean this.suitableForCoin,
                        int this.score) {

            if (name.equals(“Auto-assignment Parameters”)) {
               suitableForCoin = true; // final so compile-time error
            }
        }

        // rest of class ...
    }



DETAILS


SPECIFICATION: Describe how the proposal affects the grammar, type system,
and meaning of expressions and statements in the Java Programming Language
as well as any other known impacts.

The syntactic grammar is modified to include auto-assignment parameters for
constructors:

        ConstructorDeclaratorRest:
                 ConstructorParameters [throws QualifiedIdentifierList]
MethodBody

        ConstructorParameters:
                 ( [ConstructorParameterDecls] )

        ConstructorParameterDecls:
                 [final] [Annotations] Type ConstructorParameterDeclsRest

        ConstructorParameterDeclsRest:
                 ConstructorParameterId [ , ConstructorParameterDecls]
                 ... ConstructorParameterId

        ConstructorParameterId:
                 VariableDeclaratorId
                 this . VariableDeclaratorId
                 super . VariableDeclaratorId

An auto-assignment parameter is a formal parameter (JLSv3 §8.4.1) which
specifies an instance field instead of an identifier.  Its value is
automatically assigned to the specified field.  It may only be used in a
constructor.

The automatic assignment takes place after any explicit or implicit
invocation of another constructor, and before any statements in the body of
the constructor.  A constructor which declares n auto-assignment parameters
will perform n such automatic assignments, in the order that the parameters
are declared.

The parameter has the same name (JLSv3 §6.2) as the field to which it is
assigned; replacing each auto-assignment parameter with a normal formal
parameter with the same name would yield a constructor with an identical
signature.  As with a normal parameter, the parameter's name is entered into
the scope of the constructor body (JLSv3 §6.3), and therefore shadows the
field (JLSv3 §6.3.1) within that scope.

It is a compile-time error if the field is not accessible from the
constructor in which the parameter appears.

It is a compile-time error if the declared type of the parameter is not
assignment compatible (JLSv3 §5.2) with the field to which it is
automatically assigned.

If an unboxing conversion is required by an automatic assignment, any
NullPointerException thrown as a result (JLSv3 §5.1.8) will contain the name
of the field on which the conversion failed, which may be retrieved by
calling getMessage() on the exception.

Auto-assignment parameters are implicitly final, and follow the standard
rules for final variables (JLSv3 §4.12.4).  Explicitly declaring an
auto-assignment parameter as final has no effect, and does not cause a
compilation error.

Auto-assignment parameters follow the standard definite assignment rules for
formal parameters (JLSv3 §16.3).

An auto-assignment parameter may be annotated.

If an auto-assignment parameter is the last parameter in the list, and
refers to a field of array type, it may be a variable arity parameter.



COMPILATION: How would the feature be compiled to class files? Show how the
simple and advanced examples would be compiled. Compilation can be expressed
as at least one of a desugaring to existing source constructs and a
translation down to bytecode. If a new bytecode is used or the semantics of
an existing bytecode are changed, describe those changes, including how they
impact verification. Also discuss any new class file attributes that are
introduced. Note that there are many downstream tools that consume class
files and that they may to be updated to support the proposal!

Desugaring of the following class:

    class Foo {
        int value;
        Foo(Integer this.value) {
            System.out.println(value);
        }
    }

would result in (unboxing desugaring omitted):

    class Foo {
        int value;
        Foo(final Integer value) {
            super();
            if (value == null)
                throw new NullPointerException("value");
            this.value = value;
            System.out.println(value);
        }
    }

No changes to the classfile format are required.  Tools which consume class
files see the constructor signature as though it had been written using
normal formal parameters.


TESTING: How can the feature be tested?

An initial set of jtreg tests is included in the prototype.


LIBRARY SUPPORT: Are any supporting libraries needed for the feature?

No


REFLECTIVE APIS: Do any of the various and sundry reflection APIs need to be
updated? This list of reflective APIs includes but is not limited to core
reflection (java.lang.Class and java.lang.reflect.*), javax.lang.model.*,
the doclet API, and JPDA.

com.sun.source.tree.VariableTree would require an additional method which
returns the auto-assigned field.


OTHER CHANGES: Do any other parts of the platform need be updated too?
Possibilities include but are not limited to JNI, serialization, and output
of the javadoc tool.

No


MIGRATION: Sketch how a code base could be converted, manually or
automatically, to use the new feature.

Assignment statements in constructors for which all of the following are
true can be considered suitable for conversion:
     * the lhs of the assignment is a non-static field
     * the rhs is a parameter with the same name as the field
     * there are no other assignments to the parameter anywhere in the
constructor
     * there are no assignments to, or other uses of the field before the
assignment statement in question (including invoked constructors)

Such statements can be converted by:
    1) replacing the parameter with an auto-assignment parameter (prefixing
the existing parameter's identifier with 'this.'), and
    2) removing the assignment statement



COMPATIBILITY

BREAKING CHANGES: Are any previously valid programs now invalid? If so, list
one.

No


EXISTING PROGRAMS: How do source and class files of earlier platform
versions interact with the feature? Can any new overloadings occur? Can any
new overriding occur?

The semantics of existing class files and legal source files are unchanged
by this feature.



REFERENCES

EXISTING BUGS: Please include a list of any existing Sun bug ids related to
this proposal.

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6582394
(uses a 'setter' method rather than a constructor in its example)

FindBugs bug patterns - http://findbugs.sourceforge.net/bugDescriptions.html
* Self assignment of field (SA_FIELD_SELF_ASSIGNMENT)
* Self comparison of field with itself (SA_FIELD_SELF_COMPARISON)
* Nonsensical self computation involving a field (e.g., x & x)
(SA_FIELD_SELF_COMPUTATION)
* Self assignment of local variable (SA_LOCAL_SELF_ASSIGNMENT)
* Nonsensical self computation involving a variable (e.g., x & x)
(SA_LOCAL_SELF_COMPUTATION)
* Uninitialized read of field in constructor (UR_UNINIT_READ)
* Unwritten field (UWF_UNWRITTEN_FIELD)
* Dead store to local variable (DLS_DEAD_LOCAL_STORE)
* Dead store of null to local variable (DLS_DEAD_LOCAL_STORE_OF_NULL)



URL FOR PROTOTYPE (optional):

http://slm888.com/javac



DESIGN ALTERNATIVES:

The following variations have been explored and are worth mentioning:

* Allow auto-assignment parameters on all non-abstract methods.
    This may be especially useful on the extremely common 'setter' methods
in 'value object' classes.

* Remove the requirement for (or even disallow) the type to be specified on
auto-assignment parameters.
    Experimentation with this idea suggests that it may work quite well for
constructors, further emphasising the difference in intent and semantics
from those of normal parameters. However, it may not work so well in
combination with auto-assignment parameters on all non-abstract methods, and
requires a change to the order in which javac compiles classes (can still
pass jtreg tests).

* Allow an alternative name to be specified.
    This adds additional complexity to support a fractional percentage of
cases, which could continue to use the existing coding pattern.



More information about the coin-dev mailing list