Skip to content

Commit

Permalink
* Eliminate repeated resolution attempts on patterns
Browse files Browse the repository at this point in the history
* Fixes #2044
  • Loading branch information
srikanth-sankaran committed Mar 5, 2024
1 parent c4ec545 commit 692667c
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 66 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -294,35 +294,26 @@ public ResolvedCase[] resolveCase(BlockScope scope, TypeBinding switchExpression
flagDuplicateDefault(scope, switchStatement, this);
return ResolvedCase.UnresolvedCase;
}
Expression constExpr = getFirstValidExpression(scope, switchStatement);
if (constExpr == null) {
if (getFirstValidExpression(scope, switchStatement) == null) {
return ResolvedCase.UnresolvedCase;
}

// add into the collection of cases of the associated switch statement
switchStatement.cases[switchStatement.caseCount++] = this;
if (switchExpressionType != null && switchExpressionType.isEnum() && (constExpr instanceof SingleNameReference)) {
((SingleNameReference) constExpr).setActualReceiverType((ReferenceBinding)switchExpressionType);
}

constExpr.setExpressionContext(ExpressionContext.INSTANCEOF_CONTEXT);
constExpr.setExpectedType(switchExpressionType);

TypeBinding caseType = constExpr.resolveType(scope);
if (caseType == null || switchExpressionType == null) return ResolvedCase.UnresolvedCase;
// tag constant name with enum type for privileged access to its members

List<ResolvedCase> cases = new ArrayList<>();
for (Expression e : this.constantExpressions) {
if (e != constExpr) {
if (switchExpressionType.isEnum() && (e instanceof SingleNameReference)) {
((SingleNameReference) e).setActualReceiverType((ReferenceBinding)switchExpressionType);
} else if (e instanceof FakeDefaultLiteral) {
continue; // already processed
}
caseType = e.resolveType(scope);
// tag constant name with enum type for privileged access to its members
if (switchExpressionType != null && switchExpressionType.isEnum() && (e instanceof SingleNameReference)) {
((SingleNameReference) e).setActualReceiverType((ReferenceBinding)switchExpressionType);
} else if (e instanceof FakeDefaultLiteral) {
continue; // already processed
}
if (caseType == null)
e.setExpressionContext(ExpressionContext.INSTANCEOF_CONTEXT);
e.setExpectedType(switchExpressionType);

TypeBinding caseType = e.resolveType(scope);

if (caseType == null || switchExpressionType == null)
return ResolvedCase.UnresolvedCase;
// Avoid further resolution and secondary errors
if (caseType.isValidBinding()) {
Expand Down Expand Up @@ -439,57 +430,52 @@ private Constant resolveConstantExpression(BlockScope scope,
SwitchStatement switchStatement,
Pattern e) {
Constant constant = Constant.NotAConstant;
TypeBinding type = e.resolveType(scope);

TypeBinding type = e.resolvedType;

if (type != null) {
constant = IntConstant.fromValue(switchStatement.constantIndex);
switchStatement.caseLabelElements.add(e);
if (e.resolvedType != null) {
// 14.30.2 at compile-time we "resolve" the pattern with respect to the (compile-time) type
// of the expression being pattern matched
e.setExpressionContext(ExpressionContext.INSTANCEOF_CONTEXT);
e.setExpectedType(switchStatement.expression.resolvedType);
TypeBinding pb = e.resolveType(scope);
if (pb != null) switchStatement.caseLabelElementTypes.add(pb);
TypeBinding expressionType = switchStatement.expression.resolvedType;
// The following code is copied from InstanceOfExpression#resolve()
// But there are enough differences to warrant a copy
if (!pb.isReifiable()) {
if (expressionType != TypeBinding.NULL && !(e instanceof RecordPattern)) {
boolean isLegal = e.checkCastTypesCompatibility(scope, pb, expressionType, e, false);
if (!isLegal || (e.bits & ASTNode.UnsafeCast) != 0) {
scope.problemReporter().unsafeCastInInstanceof(e, pb, expressionType);
}
}
} else if (pb.isValidBinding()) {
// if not a valid binding, an error has already been reported for unresolved type
if (pb.isPrimitiveType()) {
scope.problemReporter().unexpectedTypeinSwitchPattern(pb, e);
return Constant.NotAConstant;
}
if (pb.isBaseType()
|| !e.checkCastTypesCompatibility(scope, pb, expressionType, null, false)) {
scope.problemReporter().typeMismatchError(expressionType, pb, e, null);
return Constant.NotAConstant;

switchStatement.caseLabelElementTypes.add(type);
TypeBinding expressionType = switchStatement.expression.resolvedType;
// The following code is copied from InstanceOfExpression#resolve()
// But there are enough differences to warrant a copy
if (!type.isReifiable()) {
if (expressionType != TypeBinding.NULL && !(e instanceof RecordPattern)) {
boolean isLegal = e.checkCastTypesCompatibility(scope, type, expressionType, e, false);
if (!isLegal || (e.bits & ASTNode.UnsafeCast) != 0) {
scope.problemReporter().unsafeCastInInstanceof(e, type, expressionType);
}
}
if (e.coversType(expressionType)) {
if ((switchStatement.switchBits & SwitchStatement.TotalPattern) != 0) {
scope.problemReporter().duplicateTotalPattern(e);
return IntConstant.fromValue(-1);
}
switchStatement.switchBits |= SwitchStatement.Exhaustive;
if (e.isAlwaysTrue()) {
switchStatement.switchBits |= SwitchStatement.TotalPattern;
if (switchStatement.defaultCase != null && !(e instanceof RecordPattern))
scope.problemReporter().illegalTotalPatternWithDefault(this);
switchStatement.totalPattern = e;
}
e.isTotalTypeNode = true;
if (switchStatement.nullCase == null)
constant = IntConstant.fromValue(-1);
} else if (type.isValidBinding()) {
// if not a valid binding, an error has already been reported for unresolved type
if (type.isPrimitiveType()) {
scope.problemReporter().unexpectedTypeinSwitchPattern(type, e);
return Constant.NotAConstant;
}
if (type.isBaseType()
|| !e.checkCastTypesCompatibility(scope, type, expressionType, null, false)) {
scope.problemReporter().typeMismatchError(expressionType, type, e, null);
return Constant.NotAConstant;
}
}

if (e.coversType(expressionType)) {
if ((switchStatement.switchBits & SwitchStatement.TotalPattern) != 0) {
scope.problemReporter().duplicateTotalPattern(e);
return IntConstant.fromValue(-1);
}
switchStatement.switchBits |= SwitchStatement.Exhaustive;
if (e.isAlwaysTrue()) {
switchStatement.switchBits |= SwitchStatement.TotalPattern;
if (switchStatement.defaultCase != null && !(e instanceof RecordPattern))
scope.problemReporter().illegalTotalPatternWithDefault(this);
switchStatement.totalPattern = e;
}
e.isTotalTypeNode = true;
if (switchStatement.nullCase == null)
constant = IntConstant.fromValue(-1);
}
}
return constant;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ public boolean dominates(Pattern p) {
@Override
public TypeBinding resolveType(BlockScope scope) {
if (this.resolvedType != null)
return this.resolvedType; // Srikanth, fix reentry
return this.resolvedType;

Pattern enclosingPattern = this.getEnclosingPattern();
if (this.local.type == null || this.local.type.isTypeNameVar(scope)) {
Expand Down

0 comments on commit 692667c

Please sign in to comment.