Skip to content

Commit

Permalink
* ECJ incorrectly allows boxing and primitive widening/narrowing at
Browse files Browse the repository at this point in the history
pattern applicability check

* Fixes #2001
  • Loading branch information
srikanth-sankaran committed Mar 5, 2024
1 parent 10f6432 commit 279c915
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ public void traverse(ASTVisitor visitor, BlockScope scope) {
}

@Override
protected boolean isPatternTypeCompatible(TypeBinding other, BlockScope scope) {
return this.primaryPattern.isPatternTypeCompatible(other, scope);
protected boolean isApplicable(TypeBinding other, BlockScope scope) {
return this.primaryPattern.isApplicable(other, scope);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,8 @@ public TypeReference getType() {
return null;
}

protected abstract boolean isPatternTypeCompatible(TypeBinding other, BlockScope scope);
// 14.30.3 Properties of Patterns: A pattern p is said to be applicable at a type T if ...
protected abstract boolean isApplicable(TypeBinding other, BlockScope scope);

public abstract boolean dominates(Pattern p);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ public TypeBinding resolveType(BlockScope scope) {
tp.local.binding.type = componentBinding.type;
}
TypeBinding expressionType = componentBinding.type;
if (p1.isPatternTypeCompatible(expressionType, scope)) {
if (p1.isApplicable(expressionType, scope)) {
p1.isTotalTypeNode = p1.coversType(componentBinding.type);
MethodBinding[] methods = this.resolvedType.getMethods(componentBinding.name);
if (methods != null && methods.length > 0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,10 +128,15 @@ public boolean coversType(TypeBinding type) {
}

@Override
protected boolean isPatternTypeCompatible(TypeBinding other, BlockScope scope) {
protected boolean isApplicable(TypeBinding other, BlockScope scope) {
TypeBinding patternType = this.resolvedType;
if (patternType == null) // ill resolved pattern
return false;
// 14.30.3 Properties of Patterns doesn't allow boxing nor unboxing, primitive widening/narrowing.
if (patternType.isBaseType() != other.isBaseType()) {
scope.problemReporter().incompatiblePatternType(this, other, patternType);
return false;
}
if (patternType.isBaseType()) {
if (!TypeBinding.equalsEquals(other, patternType)) {
scope.problemReporter().incompatiblePatternType(this, other, patternType);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4387,4 +4387,45 @@ public static void main(String[] args) {
""" },
"java.lang.MatchException");
}
// https://github.com/eclipse-jdt/eclipse.jdt.core/issues/2001
// [Patterns][records] ECJ fails to reject incompatible pattern types.
public void testIssue2001() {
runNegativeTest(new String[] { "X.java",
"""
public class X {
record R1(Long color) {}
record R2(short color) {}
public static void main(String[] args) {
Object o = new R1(10L);
if (o instanceof R1(long d)) {
System.out.println(d);
}
if (o instanceof R2(Short d)) {
System.out.println(d);
}
if (o instanceof R2(int d)) {
System.out.println(d);
}
}
}
"""
},
"----------\n" +
"1. ERROR in X.java (at line 7)\n" +
" if (o instanceof R1(long d)) {\n" +
" ^^^^^^\n" +
"Record component with type Long is not compatible with type long\n" +
"----------\n" +
"2. ERROR in X.java (at line 10)\n" +
" if (o instanceof R2(Short d)) {\n" +
" ^^^^^^^\n" +
"Record component with type short is not compatible with type java.lang.Short\n" +
"----------\n" +
"3. ERROR in X.java (at line 13)\n" +
" if (o instanceof R2(int d)) {\n" +
" ^^^^^\n" +
"Record component with type short is not compatible with type int\n" +
"----------\n");
}
}

0 comments on commit 279c915

Please sign in to comment.