Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Looks into indirect types during compilation #2543

Merged
merged 16 commits into from
Jul 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2000, 2023 IBM Corporation and others.
* Copyright (c) 2000, 2024 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
Expand Down Expand Up @@ -4485,7 +4485,7 @@ public int generateMethodInfoAttributes(MethodBinding methodBinding) {
}
}
if ((methodBinding.tagBits & TagBits.HasMissingType) != 0) {
this.missingTypes = methodBinding.collectMissingTypes(this.missingTypes);
this.missingTypes = methodBinding.collectMissingTypes(this.missingTypes, true);
}
return attributesNumber;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2000, 2021 IBM Corporation and others.
* Copyright (c) 2000, 2024 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
Expand Down Expand Up @@ -505,7 +505,7 @@ public TypeBinding resolveType(BlockScope scope) {
scope.problemReporter().invalidConstructor(this, this.binding);
return this.resolvedType;
}
if ((this.binding.tagBits & TagBits.HasMissingType) != 0) {
if ((this.binding.tagBits & TagBits.HasMissingType) != 0 && isMissingTypeRelevant()) {
scope.problemReporter().missingTypeInConstructor(this, this.binding);
}
if (isMethodUseDeprecated(this.binding, scope, true, this)) {
Expand Down Expand Up @@ -539,6 +539,20 @@ public TypeBinding resolveType(BlockScope scope) {
return this.resolvedType;
}

protected boolean isMissingTypeRelevant() {
if (this.binding != null && this.binding.isVarargs()) {
if (this.arguments.length < this.binding.parameters.length) {
// are all but the irrelevant varargs type present?
for (int i = 0; i < this.arguments.length; i++) {
if ((this.binding.parameters[i].tagBits & TagBits.HasMissingType) != 0)
return true; // this one *is* relevant - actually this case is already detected during findConstructorBinding()
}
return false;
}
}
return true;
}

protected void checkPreConstructorContext(BlockScope scope) {
if (this.inPreConstructorContext && this.type != null &&
this.type.resolvedType instanceof ReferenceBinding currentType
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -995,7 +995,7 @@ public TypeBinding resolveType(BlockScope scope) {
this.binding = scope.environment().updatePolymorphicMethodReturnType((PolymorphicMethodBinding) this.binding, TypeBinding.VOID);
}
}
if ((this.binding.tagBits & TagBits.HasMissingType) != 0) {
if ((this.binding.tagBits & TagBits.HasMissingType) != 0 && isMissingTypeRelevant()) {
scope.problemReporter().missingTypeInMethod(this, this.binding);
}
if (!this.binding.isStatic()) {
Expand Down Expand Up @@ -1112,6 +1112,25 @@ protected boolean isUnnecessaryReceiverCast(BlockScope scope, TypeBinding uncast
|| MethodVerifier.doesMethodOverride(otherMethod, this.binding, scope.environment());
}

protected boolean isMissingTypeRelevant() {
if ((this.bits & ASTNode.InsideExpressionStatement) != 0) {
if (this.binding.collectMissingTypes(null, false) == null)
return false; // only irrelevant return type is missing
}
if ((this.binding.returnType.tagBits & TagBits.HasMissingType) == 0
&& this.binding.isVarargs()) {
if (this.arguments.length < this.binding.parameters.length) {
// are all but the irrelevant varargs type present?
for (int i = 0; i < this.arguments.length; i++) {
if ((this.binding.parameters[i].tagBits & TagBits.HasMissingType) != 0)
return true; // this one *is* relevant - actually this case is already detected during findMethodBinding()
}
return false;
}
}
return true;
}

protected TypeBinding handleNullnessCodePatterns(BlockScope scope, TypeBinding returnType) {
// j.u.s.Stream.filter() may modify nullness of stream elements:
if (this.binding.isWellknownMethod(TypeConstants.JAVA_UTIL_STREAM__STREAM, TypeConstants.FILTER)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -586,7 +586,7 @@ private TypeBinding resolveTypeForQualifiedAllocationExpression(BlockScope scope
scope.problemReporter().invalidConstructor(this, constructorBinding);
return this.resolvedType;
}
if ((constructorBinding.tagBits & TagBits.HasMissingType) != 0) {
if ((constructorBinding.tagBits & TagBits.HasMissingType) != 0 && isMissingTypeRelevant()) {
scope.problemReporter().missingTypeInConstructor(this, constructorBinding);
}
if (this.enclosingInstance != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1951,33 +1951,39 @@ MethodBinding resolveTypesFor(MethodBinding method) {

if ((method.modifiers & ExtraCompilerModifiers.AccUnresolved) == 0)
return method;
boolean tolerateSave = this.environment.mayTolerateMissingType;
this.environment.mayTolerateMissingType |= this.environment.globalOptions.complianceLevel >= ClassFileConstants.JDK1_8; // tolerance only implemented for 1.8+
try {

if (!method.isConstructor()) {
TypeBinding resolvedType = resolveType(method.returnType, this.environment, true /* raw conversion */);
method.returnType = resolvedType;
if ((resolvedType.tagBits & TagBits.HasMissingType) != 0) {
method.tagBits |= TagBits.HasMissingType;
if (!method.isConstructor()) {
TypeBinding resolvedType = resolveType(method.returnType, this.environment, true /* raw conversion */);
method.returnType = resolvedType;
if ((resolvedType.tagBits & TagBits.HasMissingType) != 0) {
method.tagBits |= TagBits.HasMissingType;
}
}
}
for (int i = method.parameters.length; --i >= 0;) {
TypeBinding resolvedType = resolveType(method.parameters[i], this.environment, true /* raw conversion */);
method.parameters[i] = resolvedType;
if ((resolvedType.tagBits & TagBits.HasMissingType) != 0) {
method.tagBits |= TagBits.HasMissingType;
for (int i = method.parameters.length; --i >= 0;) {
TypeBinding resolvedType = resolveType(method.parameters[i], this.environment, true /* raw conversion */);
method.parameters[i] = resolvedType;
if ((resolvedType.tagBits & TagBits.HasMissingType) != 0) {
method.tagBits |= TagBits.HasMissingType;
}
}
}
for (int i = method.thrownExceptions.length; --i >= 0;) {
ReferenceBinding resolvedType = (ReferenceBinding) resolveType(method.thrownExceptions[i], this.environment, true /* raw conversion */);
method.thrownExceptions[i] = resolvedType;
if ((resolvedType.tagBits & TagBits.HasMissingType) != 0) {
method.tagBits |= TagBits.HasMissingType;
for (int i = method.thrownExceptions.length; --i >= 0;) {
ReferenceBinding resolvedType = (ReferenceBinding) resolveType(method.thrownExceptions[i], this.environment, true /* raw conversion */);
method.thrownExceptions[i] = resolvedType;
if ((resolvedType.tagBits & TagBits.HasMissingType) != 0) {
method.tagBits |= TagBits.HasMissingType;
}
}
for (int i = method.typeVariables.length; --i >= 0;) {
method.typeVariables[i].resolve();
}
method.modifiers &= ~ExtraCompilerModifiers.AccUnresolved;
return method;
} finally {
this.environment.mayTolerateMissingType = tolerateSave;
}
for (int i = method.typeVariables.length; --i >= 0;) {
method.typeVariables[i].resolve();
}
method.modifiers &= ~ExtraCompilerModifiers.AccUnresolved;
return method;
}
@Override
AnnotationBinding[] retrieveAnnotations(Binding binding) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2000, 2021 IBM Corporation and others.
* Copyright (c) 2000, 2024 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
Expand Down Expand Up @@ -63,13 +63,10 @@ public CaptureBinding(WildcardBinding wildcard, ReferenceBinding sourceType, int
this.environment.typeSystem.cacheDerivedType(this, unannotated, this);
// propagate from wildcard to capture - use super version, because our own method propagates type annotations in the opposite direction:
super.setTypeAnnotations(wildcard.getTypeAnnotations(), wildcard.environment.globalOptions.isAnnotationBasedNullAnalysisEnabled);
if (wildcard.hasNullTypeAnnotations())
this.tagBits |= TagBits.HasNullTypeAnnotation;
this.tagBits |= wildcard.tagBits & (TagBits.HasNullTypeAnnotation|TagBits.HasMissingType);
} else {
computeId(this.environment);
if(wildcard.hasNullTypeAnnotations()) {
this.tagBits |= (wildcard.tagBits & TagBits.AnnotationNullMASK) | TagBits.HasNullTypeAnnotation;
}
this.tagBits |= wildcard.tagBits & (TagBits.AnnotationNullMASK|TagBits.HasNullTypeAnnotation|TagBits.HasMissingType);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ public ConstraintExceptionFormula(FunctionalExpression left, TypeBinding type) {

@Override
public Object reduce(InferenceContext18 inferenceContext) {
if ((this.right.tagBits & TagBits.HasMissingType) != 0) {
inferenceContext.hasIgnoredMissingType = true;
return TRUE;
}
// JLS 18.2.5
Scope scope = inferenceContext.scope;
if (!this.right.isFunctionalInterface(scope))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ class ConstraintExpressionFormula extends ConstraintFormula {

@Override
public Object reduce(InferenceContext18 inferenceContext) throws InferenceFailureException {
if ((this.right.tagBits & TagBits.HasMissingType) != 0) {
inferenceContext.hasIgnoredMissingType = true;
return TRUE;
}

if (this.relation == POTENTIALLY_COMPATIBLE) {
/* 15.12.2.1: ... The definition of potential applicability goes beyond a basic arity check to also take into account the presence and "shape" of functional interface
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ private ConstraintTypeFormula(TypeBinding exprType, TypeBinding right, int relat
// return: ReductionResult or ConstraintFormula[]
@Override
public Object reduce(InferenceContext18 inferenceContext) {
if ((this.left.tagBits & TagBits.HasMissingType) != 0 || (this.right.tagBits & TagBits.HasMissingType) != 0) {
inferenceContext.hasIgnoredMissingType = true;
return TRUE;
}
switch (this.relation) {
case COMPATIBLE:
// 18.2.2:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,8 @@ public class InferenceContext18 {
// the following two flags control to what degree we continue with incomplete information:
private boolean isInexactVarargsInference = false;
boolean prematureOverloadResolution = false;
// during reduction we ignore missing types but record that fact here:
boolean hasIgnoredMissingType;

public static boolean isSameSite(InvocationSite site1, InvocationSite site2) {
if (site1 == site2)
Expand Down Expand Up @@ -754,6 +756,7 @@ private boolean addConstraintsToC_OneExpr(Expression expri, Set<ConstraintFormul
protected int getInferenceKind(MethodBinding nonGenericMethod, TypeBinding[] argumentTypes) {
switch (this.scope.parameterCompatibilityLevel(nonGenericMethod, argumentTypes)) {
case Scope.AUTOBOX_COMPATIBLE:
case Scope.COMPATIBLE_IGNORING_MISSING_TYPE: // if in doubt the method with missing types should be accepted to signal its relevance for resolution
return CHECK_LOOSE;
case Scope.VARARGS_COMPATIBLE:
return CHECK_VARARG;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,8 +144,7 @@ public TypeBinding substitute(TypeVariableBinding typeVariable) {
typeVariable.superclass = superclass;
typeVariable.superInterfaces = superInterfaces;
typeVariable.firstBound = superclass != null ? superclass : superInterfaces[0];
if (typeVariable.firstBound.hasNullTypeAnnotations())
typeVariable.tagBits |= TagBits.HasNullTypeAnnotation;
typeVariable.tagBits |= typeVariable.firstBound.tagBits & (TagBits.HasNullTypeAnnotation|TagBits.HasMissingType);
}
return typeVariable;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -413,9 +413,11 @@ public final boolean canBeSeenBy(TypeBinding receiverType, InvocationSite invoca
return false;
}

public List<TypeBinding> collectMissingTypes(List<TypeBinding> missingTypes) {
public List<TypeBinding> collectMissingTypes(List<TypeBinding> missingTypes, boolean considerReturnType) {
if ((this.tagBits & TagBits.HasMissingType) != 0) {
missingTypes = this.returnType.collectMissingTypes(missingTypes);
if (considerReturnType) {
missingTypes = this.returnType.collectMissingTypes(missingTypes);
}
for (TypeBinding parameter : this.parameters) {
missingTypes = parameter.collectMissingTypes(missingTypes);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ public static MethodBinding computeCompatibleMethod(MethodBinding originalMethod
ParameterizedGenericMethodBinding substitute = inferFromArgumentTypes(scope, originalMethod, arguments, parameters, inferenceContext);
if (substitute != null && substitute.returnType.isCompatibleWith(expectedType)) {
// Do not use the new solution if it results in incompatibilities in parameter types
if ((scope.parameterCompatibilityLevel(substitute, arguments, false)) > Scope.NOT_COMPATIBLE) {
if ((scope.parameterCompatibilityLevel(substitute, arguments, false)) > Scope.NOT_COMPATIBLE) { // don't worry about COMPATIBLE_IGNORING_MISSING_TYPE in 1.7 context
methodSubstitute = substitute;
} else {
inferenceContext = oldContext;
Expand Down Expand Up @@ -307,6 +307,9 @@ public static MethodBinding computeCompatibleMethod18(MethodBinding originalMeth
if (invocationSite instanceof Invocation && allArgumentsAreProper && (expectedType == null || expectedType.isProperType(true)))
infCtx18.forwardResults(result, (Invocation) invocationSite, methodSubstitute, expectedType);
try {
if (infCtx18.hasIgnoredMissingType) {
return new ProblemMethodBinding(originalMethod, originalMethod.selector, parameters, ProblemReasons.MissingTypeInSignature);
}
if (hasReturnProblem) { // illegally working from the provisional result?
MethodBinding problemMethod = infCtx18.getReturnProblemMethodIfNeeded(expectedType, methodSubstitute);
if (problemMethod instanceof ProblemMethodBinding) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ public ParameterizedMethodBinding(final ParameterizedTypeBinding parameterizedDe
for (int i = 0; i < length; i++) { // copy original type variable to relocate
TypeVariableBinding originalVariable = originalVariables[i];
substitutedVariables[i] = new TypeVariableBinding(originalVariable.sourceName, this, originalVariable.rank, parameterizedDeclaringClass.environment);
substitutedVariables[i].tagBits |= (originalVariable.tagBits & (TagBits.AnnotationNullMASK|TagBits.HasNullTypeAnnotation));
substitutedVariables[i].tagBits |= (originalVariable.tagBits & (TagBits.AnnotationNullMASK|TagBits.HasNullTypeAnnotation|TagBits.HasMissingType));
}
stephan-herrmann marked this conversation as resolved.
Show resolved Hide resolved
this.typeVariables = substitutedVariables;

Expand Down Expand Up @@ -209,7 +209,7 @@ public ParameterizedMethodBinding(final ReferenceBinding declaringClass, MethodB
this,
originalVariable.rank,
environment);
substitutedVariables[i].tagBits |= (originalVariable.tagBits & (TagBits.AnnotationNullMASK|TagBits.HasNullTypeAnnotation));
substitutedVariables[i].tagBits |= (originalVariable.tagBits & (TagBits.AnnotationNullMASK|TagBits.HasNullTypeAnnotation|TagBits.HasMissingType));
}
this.typeVariables = substitutedVariables;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,5 @@ public interface ProblemReasons {
final int InterfaceMethodInvocationNotBelow18 = 29;
final int NotAccessible = 30; // JLS 6.6.1 - module aspects
final int ErrorAlreadyReported = 31;
final int MissingTypeInSignature = 32;
}
Loading
Loading