Skip to content

Commit

Permalink
* Exclude unnamed pattern bindings from scope, flow analysis and code
Browse files Browse the repository at this point in the history
generation

* Fixes #2020
  • Loading branch information
srikanth-sankaran committed Mar 5, 2024
1 parent 57f62f3 commit 10f6432
Show file tree
Hide file tree
Showing 7 changed files with 475 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,8 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl
}
if (this.initialization == null) {
if (this.binding != null && this.binding.isPatternVariable())
this.bits |= FirstAssignmentToLocal;
if (!this.binding.declaration.isUnnamed(currentScope))
this.bits |= FirstAssignmentToLocal;
return flowInfo;
}
this.initialization.checkNPEbyUnboxing(currentScope, flowContext, flowInfo);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@ public void setEnclosingPattern(RecordPattern enclosingPattern) {
this.enclosingPattern = enclosingPattern;
}

public boolean isUnnamed() {
return false;
}

/**
* Implement the rules in the spec under 14.11.1.1 Exhaustive Switch Blocks
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -237,12 +237,13 @@ original record instance as receiver - leaving the stack drained.
p.accessorMethod.returnType.erasure()))
codeStream.checkcast(p.accessorMethod.returnType); // lastComponent ? [C] : [R, C]
if (p instanceof RecordPattern || !p.isTotalTypeNode) {
codeStream.dup(); // lastComponent ? [C, C] : [R, C, C]
codeStream.instance_of(p.resolvedType); // lastComponent ? [C, boolean] : [R, C, boolean]
if (!p.isUnnamed())
codeStream.dup(); // lastComponent ? named ? ([C, C] : [R, C, C]) : ([C] : [R, C])
codeStream.instance_of(p.resolvedType); // lastComponent ? named ? ([C, boolean] : [R, C, boolean]) : ([boolean] : [R, boolean])
BranchLabel target = falseLabel != null ? falseLabel : new BranchLabel(codeStream);
BranchLabel innerTruthLabel = new BranchLabel(codeStream);
codeStream.ifne(innerTruthLabel); // lastComponent ? [C] : [R, C]
int pops = 1; // Not going to store into the component pattern binding, so need to pop, the duped value.
codeStream.ifne(innerTruthLabel); // lastComponent ? named ? ([C] : [R, C]) : ([] : [R])
int pops = p.isUnnamed() ? 0 : 1; // Not going to store into the component pattern binding, so need to pop, the duped value.
Pattern current = p;
RecordPattern outer = this;
while (outer != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,26 @@ public TypePattern(LocalDeclaration local) {
this.local = local;
}

public static TypePattern createTypePattern(LocalDeclaration lokal) {
if (lokal.name.length == 1 && lokal.name[0] == '_') {
return new TypePattern(lokal) {
@Override
public boolean isUnnamed() {
return true;
}
};
}
return new TypePattern(lokal);
}

@Override
public TypeReference getType() {
return this.local.type;
}

@Override
public LocalVariableBinding[] bindingsWhenTrue() {
return this.local.binding == null ? NO_VARIABLES : new LocalVariableBinding[] { this.local.binding };
return this.isUnnamed() || this.local.binding == null ? NO_VARIABLES : new LocalVariableBinding[] { this.local.binding };
}

@Override
Expand All @@ -62,6 +74,10 @@ public boolean checkUnsafeCast(Scope scope, TypeBinding castType, TypeBinding ex
public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
flowInfo = this.local.analyseCode(currentScope, flowContext, flowInfo);
FlowInfo patternInfo = flowInfo.copy();

if (this.isUnnamed())
return patternInfo; // exclude anonymous blokes from flow analysis.

patternInfo.markAsDefinitelyAssigned(this.local.binding);
if (!this.isTotalTypeNode) {
// non-total type patterns create a nonnull local:
Expand All @@ -80,10 +96,23 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl

@Override
public void generateOptimizedBoolean(BlockScope currentScope, CodeStream codeStream, BranchLabel trueLabel, BranchLabel falseLabel) {
if (!this.isTotalTypeNode) {
codeStream.checkcast(this.local.binding.type);
if (isUnnamed()) {
if (this.isTotalTypeNode) {
switch (this.local.binding.type.id) {
case T_long :
case T_double :
codeStream.pop2();
break;
default :
codeStream.pop();
}
} // else we don't value on stack.
} else {
if (!this.isTotalTypeNode) {
codeStream.checkcast(this.local.binding.type);
}
this.local.generateCode(currentScope, codeStream);
}
this.local.generateCode(currentScope, codeStream);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,20 +146,21 @@ public final void addLocalVariable(LocalVariableBinding binding) {
return;
}
checkAndSetModifiersForVariable(binding);
// insert local in scope
if (this.localIndex == this.locals.length)
System.arraycopy(
this.locals,
0,
(this.locals = new LocalVariableBinding[this.localIndex * 2]),
0,
this.localIndex);
this.locals[this.localIndex++] = binding;
// insert local in scope, skipping unnamed pattern variables.
if (!binding.isPatternVariable() || !binding.declaration.isUnnamed(this)) {
if (this.localIndex == this.locals.length)
System.arraycopy(
this.locals,
0,
(this.locals = new LocalVariableBinding[this.localIndex * 2]),
0,
this.localIndex);
this.locals[this.localIndex++] = binding;
binding.id = outerMostMethodScope().analysisIndex++; // share the outermost method scope analysisIndex
}

// update local variable binding
binding.declaringScope = this;
binding.id = outerMostMethodScope().analysisIndex++;
// share the outermost method scope analysisIndex
}

public void addSubscope(Scope childScope) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10357,7 +10357,7 @@ protected void consumeTypePattern() {
type.annotations = null;
local.type = type;

TypePattern aTypePattern = new TypePattern(local);
TypePattern aTypePattern = TypePattern.createTypePattern(local);
aTypePattern.sourceStart = this.intStack[this.intPtr--];
local.modifiers = this.intStack[this.intPtr--];
local.declarationSourceStart = type.sourceStart;
Expand All @@ -10379,7 +10379,7 @@ protected void consumeUnnamedPattern() {
this.identifierPtr--;
this.identifierLengthPtr--;

TypePattern aUnnamedPattern = new TypePattern(local);
TypePattern aUnnamedPattern = TypePattern.createTypePattern(local);
aUnnamedPattern.sourceStart = local.sourceStart;
aUnnamedPattern.sourceEnd = local.sourceEnd;

Expand Down

0 comments on commit 10f6432

Please sign in to comment.