diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/InferenceContext18.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/InferenceContext18.java index c50b66910c9..78694bb8ec4 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/InferenceContext18.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/InferenceContext18.java @@ -1149,48 +1149,52 @@ public boolean reduceAndIncorporate(ConstraintFormula constraint) throws Inferen final int numVars = variableSet.size(); if (numVars > 0) { final InferenceVariable[] variables = variableSet.toArray(new InferenceVariable[numVars]); - variables: if (!isRecordPatternTypeInference && !tmpBoundSet.hasCaptureBound(variableSet)) { + variables: if (!tmpBoundSet.hasCaptureBound(variableSet)) { // try to instantiate this set of variables in a fresh copy of the bound set: BoundSet prevBoundSet = tmpBoundSet; tmpBoundSet = tmpBoundSet.copy(); for (int j = 0; j < variables.length; j++) { InferenceVariable variable = variables[j]; - // try lower bounds: - TypeBinding[] lowerBounds = tmpBoundSet.lowerBounds(variable, true/*onlyProper*/); - if (lowerBounds != Binding.NO_TYPES) { - TypeBinding lub = this.scope.lowerUpperBound(lowerBounds); - if (lub == TypeBinding.VOID || lub == null) - return null; - tmpBoundSet.addBound(new TypeBound(variable, lub, ReductionResult.SAME), this.environment); + if (isRecordPatternTypeInference) { + tmpBoundSet.addBound(new TypeBound(variable, this.object, ReductionResult.SAME), this.environment); } else { - TypeBinding[] upperBounds = tmpBoundSet.upperBounds(variable, true/*onlyProper*/); - // check exception bounds: - if (tmpBoundSet.inThrows.contains(variable.prototype()) && tmpBoundSet.hasOnlyTrivialExceptionBounds(variable, upperBounds)) { - TypeBinding runtimeException = this.scope.getType(TypeConstants.JAVA_LANG_RUNTIMEEXCEPTION, 3); - tmpBoundSet.addBound(new TypeBound(variable, runtimeException, ReductionResult.SAME), this.environment); + // try lower bounds: + TypeBinding[] lowerBounds = tmpBoundSet.lowerBounds(variable, true/*onlyProper*/); + if (lowerBounds != Binding.NO_TYPES) { + TypeBinding lub = this.scope.lowerUpperBound(lowerBounds); + if (lub == TypeBinding.VOID || lub == null) + return null; + tmpBoundSet.addBound(new TypeBound(variable, lub, ReductionResult.SAME), this.environment); } else { - // try upper bounds: - TypeBinding glb = this.object; - if (upperBounds != Binding.NO_TYPES) { - if (upperBounds.length == 1) { - glb = upperBounds[0]; - } else { - TypeBinding[] glbs = Scope.greaterLowerBound(upperBounds, this.scope, this.environment); - if (glbs == null) { - return null; - } else if (glbs.length == 1) { - glb = glbs[0]; + TypeBinding[] upperBounds = tmpBoundSet.upperBounds(variable, true/*onlyProper*/); + // check exception bounds: + if (tmpBoundSet.inThrows.contains(variable.prototype()) && tmpBoundSet.hasOnlyTrivialExceptionBounds(variable, upperBounds)) { + TypeBinding runtimeException = this.scope.getType(TypeConstants.JAVA_LANG_RUNTIMEEXCEPTION, 3); + tmpBoundSet.addBound(new TypeBound(variable, runtimeException, ReductionResult.SAME), this.environment); + } else { + // try upper bounds: + TypeBinding glb = this.object; + if (upperBounds != Binding.NO_TYPES) { + if (upperBounds.length == 1) { + glb = upperBounds[0]; } else { - glb = intersectionFromGlb(glbs); - if (glb == null) { - // inconsistent intersection - tmpBoundSet = prevBoundSet; // clean up - break variables; // and start over + TypeBinding[] glbs = Scope.greaterLowerBound(upperBounds, this.scope, this.environment); + if (glbs == null) { + return null; + } else if (glbs.length == 1) { + glb = glbs[0]; + } else { + glb = intersectionFromGlb(glbs); + if (glb == null) { + // inconsistent intersection + tmpBoundSet = prevBoundSet; // clean up + break variables; // and start over + } } } } + tmpBoundSet.addBound(new TypeBound(variable, glb, ReductionResult.SAME), this.environment); } - tmpBoundSet.addBound(new TypeBound(variable, glb, ReductionResult.SAME), this.environment); } } } diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/RecordPatternTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/RecordPatternTest.java index f3f5a38adc0..a42deb6b3c5 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/RecordPatternTest.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/RecordPatternTest.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2022, 2023 IBM Corporation and others. + * Copyright (c) 2022, 2025 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -28,7 +28,7 @@ public class RecordPatternTest extends AbstractRegressionTest9 { static { // TESTS_NUMBERS = new int [] { 40 }; // TESTS_RANGE = new int[] { 1, -1 }; -// TESTS_NAMES = new String[] { "testRecordTypeInfer_4643" }; +// TESTS_NAMES = new String[] { "testRecordPatternTypeInference_001" }; } private String extraLibPath; public static Class testClass() { @@ -5089,5 +5089,25 @@ public static void main(String[] args) { "Record component with type Integer is not compatible with type String\n" + "----------\n"); } + public void testRecordTypeInfer_1361_001() { + runConformTest(new String[] { "X.java", + """ + record Record(T a) {} + public class X { + static void test(Object o) { + if (o instanceof Record(var x)) { + var v = new Record<>(x); + Record r = v; + System.out.println(true); + } + } + public static void main(String[] args) { + Record r = new Record<>(10); + test(r); + } + } + """ }, + "true"); + } } \ No newline at end of file