-
Bug
-
Resolution: Fixed
-
P4
-
None
-
generic
-
generic
As of this commit: http://hg.openjdk.java.net/valhalla/valhalla/rev/f039363534f3
javac rejects attempts to update the final instance fields of a value class (made from a method in the same nest) if the field is not a member of local variable object.
Basically, after withfield produces a copy on the attempted write, we need to "write back" the updated value instance somewhere.
This requires a mutable handle of which the field undergoing update is a field.
This means that the following various attempts are legal/illegal as annotated.
__ByValue final class A {
final int x = 10;
void foo(A a, final A fa) {
a.x = 100; // OK.
(a).x = 100; // OK.
fa.x = 100; // Error.
x = 100; // Error, this is const.
this.x = 100; // Error.
A.this.x = 100; // Error.
}
}
So far it looks reasonable.
But presently, javac also insists that the field should be a member of an object which is a local variable.
This means that some of the code below is rejected, though they should perhaps not be:
class P {
A[] ca = new A[1];
A foo() {
return __MakeDefault A();
}
}
__ByValue final class A {
final int y = i();
final int x = 10;
int i() {
return 10;
}
__ByValue final class B {
final A a = __MakeDefault A();
}
__ByValue final class C {
final B b = __MakeDefault B();
}
__ByValue final class D {
final C c = __MakeDefault C();
void withfield(D d, final D fd) {
P p = new P();
p.ca[0].x = 40; // Not allowed now, but perhaps should be
p.foo().x = 50; // Error: can't write back to constant expression.
d.c.b.a.x = 11; // Not allowed now, but perhaps should be
fd.c.b.a.x = 11; // oops, can't write back to final parameter.
}
}
The cases tagged // Not allowed now, but perhaps should be
need to be looked into.
This would involve a fair bit of new type of complexity - the expression stacks sometimes won't have the information needed to write back.
javac rejects attempts to update the final instance fields of a value class (made from a method in the same nest) if the field is not a member of local variable object.
Basically, after withfield produces a copy on the attempted write, we need to "write back" the updated value instance somewhere.
This requires a mutable handle of which the field undergoing update is a field.
This means that the following various attempts are legal/illegal as annotated.
__ByValue final class A {
final int x = 10;
void foo(A a, final A fa) {
a.x = 100; // OK.
(a).x = 100; // OK.
fa.x = 100; // Error.
x = 100; // Error, this is const.
this.x = 100; // Error.
A.this.x = 100; // Error.
}
}
So far it looks reasonable.
But presently, javac also insists that the field should be a member of an object which is a local variable.
This means that some of the code below is rejected, though they should perhaps not be:
class P {
A[] ca = new A[1];
A foo() {
return __MakeDefault A();
}
}
__ByValue final class A {
final int y = i();
final int x = 10;
int i() {
return 10;
}
__ByValue final class B {
final A a = __MakeDefault A();
}
__ByValue final class C {
final B b = __MakeDefault B();
}
__ByValue final class D {
final C c = __MakeDefault C();
void withfield(D d, final D fd) {
P p = new P();
p.ca[0].x = 40; // Not allowed now, but perhaps should be
p.foo().x = 50; // Error: can't write back to constant expression.
d.c.b.a.x = 11; // Not allowed now, but perhaps should be
fd.c.b.a.x = 11; // oops, can't write back to final parameter.
}
}
The cases tagged // Not allowed now, but perhaps should be
need to be looked into.
This would involve a fair bit of new type of complexity - the expression stacks sometimes won't have the information needed to write back.