Skip to content

Commit

Permalink
[24] don't request access to enclosing class if it's never used (#3198)
Browse files Browse the repository at this point in the history
Fixes #3194
  • Loading branch information
stephan-herrmann authored Oct 29, 2024
1 parent 7a3bce4 commit 9e19805
Show file tree
Hide file tree
Showing 4 changed files with 119 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -921,18 +921,22 @@ public void manageSyntheticAccessIfNecessary(BlockScope currentScope, FlowInfo f
if ((this.bits & Binding.FIELD) != 0) {
FieldBinding fieldBinding = (FieldBinding) this.binding;
FieldBinding codegenField = fieldBinding.original();
if (((this.bits & ASTNode.DepthMASK) != 0)
&& ((codegenField.isPrivate() // private access
&& !currentScope.enclosingSourceType().isNestmateOf(codegenField.declaringClass) )
|| (codegenField.isProtected() // implicit protected access
&& codegenField.declaringClass.getPackage() != currentScope.enclosingSourceType().getPackage()))) {
if (this.syntheticAccessors == null)
this.syntheticAccessors = new MethodBinding[2];
this.syntheticAccessors[isReadAccess ? SingleNameReference.READ : SingleNameReference.WRITE] =
((SourceTypeBinding)currentScope.enclosingSourceType().
enclosingTypeAt((this.bits & ASTNode.DepthMASK) >> ASTNode.DepthSHIFT)).addSyntheticMethod(codegenField, isReadAccess, false /*not super access*/);
currentScope.problemReporter().needToEmulateFieldAccess(codegenField, this, isReadAccess);
return;
if ((this.bits & ASTNode.DepthMASK) != 0) {
if ((codegenField.isPrivate() // private access
&& !currentScope.enclosingSourceType().isNestmateOf(codegenField.declaringClass))
|| (codegenField.isProtected() // implicit protected access
&& codegenField.declaringClass.getPackage() != currentScope.enclosingSourceType().getPackage())) {
if (this.syntheticAccessors == null)
this.syntheticAccessors = new MethodBinding[2];
this.syntheticAccessors[isReadAccess ? SingleNameReference.READ : SingleNameReference.WRITE] =
((SourceTypeBinding) currentScope.enclosingSourceType().
enclosingTypeAt((this.bits & ASTNode.DepthMASK) >> ASTNode.DepthSHIFT)).addSyntheticMethod(codegenField, isReadAccess, false /* not super access */);
currentScope.problemReporter().needToEmulateFieldAccess(codegenField, this, isReadAccess);
return;
}
if (!codegenField.isStatic() && currentScope.enclosingSourceType() instanceof NestedTypeBinding nestedType) {
nestedType.requestEnclosingInstancePathTo(codegenField.declaringClass);
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1072,9 +1072,14 @@ public void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope, Fl
outerScope = outerScope.enclosingInstanceScope();
earlySeen = methodScope.isInsideEarlyConstructionContext(nestedType.enclosingType(), false);
}
if (JavaFeature.FLEXIBLE_CONSTRUCTOR_BODIES.isSupported(currentScope.compilerOptions())) {
if (JavaFeature.FLEXIBLE_CONSTRUCTOR_BODIES.isSupported(currentScope.compilerOptions())
&& nestedType.enclosingInstances != null) // only if access to enclosing instance has already been requested
{
// JEP 482: this is the central location for organizing synthetic arguments and fields
// to serve far outer instances even in inner early construction context.
// Only SingleNameReference.manageSyntheticAccessIfNecessary() may add more synth outers later on
// (using NestedTypeBinding.requestEnclosingInstancePathTo()).
//
// Locations MethodBinding.computeSignature() and BlockScope.getEmulationPath() will faithfully
// use the information generated here, to decide about signature and call sequence.
while (outerScope != null) {
Expand Down Expand Up @@ -1138,8 +1143,8 @@ public void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope, Fl
*/
public void manageEnclosingInstanceAccessIfNecessary(ClassScope currentScope, FlowInfo flowInfo) {
if ((flowInfo.tagBits & FlowInfo.UNREACHABLE_OR_DEAD) == 0) {
NestedTypeBinding nestedType = (NestedTypeBinding) this.binding;
nestedType.addSyntheticArgumentAndField(this.binding.enclosingType());
NestedTypeBinding nestedType = (NestedTypeBinding) this.binding;
nestedType.addSyntheticArgumentAndField(this.binding.enclosingType());
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,14 +126,27 @@ public SyntheticArgumentBinding addSyntheticArgumentAndField(ReferenceBinding ta
if (!isPrototype()) throw new IllegalStateException();
if (this.scope.isInsideEarlyConstructionContext(targetEnclosingType, false))
return null;
SyntheticArgumentBinding synthLocal = addSyntheticArgument(targetEnclosingType);
if (synthLocal == null) return null;
return doAddSyntheticArgumentAndField(targetEnclosingType);
}

private SyntheticArgumentBinding doAddSyntheticArgumentAndField(ReferenceBinding targetEnclosingType) {
SyntheticArgumentBinding synthLocal = addSyntheticArgument(targetEnclosingType);
if (synthLocal == null)
return null;
if (synthLocal.matchingField == null)
synthLocal.matchingField = addSyntheticFieldForInnerclass(targetEnclosingType);
return synthLocal;
}

public void requestEnclosingInstancePathTo(ReferenceBinding targetEnclosingClass) {
if (isCompatibleWith(targetEnclosingClass))
return;
if (getSyntheticField(targetEnclosingClass, false) == null)
doAddSyntheticArgumentAndField(targetEnclosingClass);
if (this.enclosingType instanceof NestedTypeBinding nestedType)
nestedType.requestEnclosingInstancePathTo(targetEnclosingClass);
}

/* Answer the receiver's enclosing type... null if the receiver is a top level type.
*/
@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2056,7 +2056,12 @@ class C4 { // not early for C3
^^
Cannot read field f2 in an early construction context
----------
2. WARNING in C1.java (at line 18)
2. ERROR in C1.java (at line 15)
new C4();
^^^^^^^^
No enclosing instance of the type C1 is accessible in scope
----------
3. WARNING in C1.java (at line 18)
super();
^^^^^^^^
You are using a preview language feature that may or may not be supported in a future release
Expand Down Expand Up @@ -2355,4 +2360,78 @@ class Local {}
"");
}

public void testCtorRef_neg () {
runNegativeTest(new String[] {
"Outer.java",
"""
import java.util.function.Supplier;
@SuppressWarnings("unused")
class Outer {
void m() { }
class Inner {
Inner() {
class Foo {
void g() {
m();
}
}
super();
class Bar {
static void r() {
Supplier<Foo> sfoo = Foo::new;
}
};
}
}
}
"""
},
"""
----------
1. ERROR in Outer.java (at line 9)
m();
^^^
No enclosing instance of the type Outer is accessible in scope
----------
2. WARNING in Outer.java (at line 12)
super();
^^^^^^^^
You are using a preview language feature that may or may not be supported in a future release
----------
""");
}

public void testCtorRef_pos () {
runConformTest(new String[] {
"Outer.java",
"""
import java.util.function.Supplier;
class Outer {
void m() { }
class Inner {
Inner() {
class Foo {
void g() {
System.out.print("g");
// m();
}
}
super();
class Bar {
static void r() {
Supplier<Foo> sfoo = Foo::new;
sfoo.get().g();
}
};
Bar.r();
}
}
public static void main(String... args) {
new Outer().new Inner();
}
}
"""
},
"g");
}
}

0 comments on commit 9e19805

Please sign in to comment.