public ParameterizedTypeBinding getParameterizedType( ReferenceBinding genericType, TypeBinding[] typeArguments, ReferenceBinding enclosingType, AnnotationBinding[] annotations) { if (genericType.hasTypeAnnotations()) // @NonNull (List<String>) and not (@NonNull List)<String> throw new IllegalStateException(); ParameterizedTypeBinding parameterizedType = this.parameterizedTypes.get(genericType, typeArguments, enclosingType, annotations); if (parameterizedType != null) return parameterizedType; ParameterizedTypeBinding nakedType = super.getParameterizedType(genericType, typeArguments, enclosingType); if (!haveTypeAnnotations(genericType, enclosingType, typeArguments, annotations)) return nakedType; parameterizedType = new ParameterizedTypeBinding(genericType, typeArguments, enclosingType, this.environment); parameterizedType.id = nakedType.id; parameterizedType.setTypeAnnotations(annotations, this.isAnnotationBasedNullAnalysisEnabled); this.parameterizedTypes.put(genericType, typeArguments, enclosingType, parameterizedType); return (ParameterizedTypeBinding) cacheDerivedType(genericType, nakedType, parameterizedType); }
public void checkBounds(Scope scope) { if (this.resolvedType == null) return; if (this.resolvedType.leafComponentType() instanceof ParameterizedTypeBinding) { ParameterizedTypeBinding parameterizedType = (ParameterizedTypeBinding) this.resolvedType.leafComponentType(); ReferenceBinding currentType = parameterizedType.genericType(); TypeVariableBinding[] typeVariables = currentType.typeVariables(); TypeBinding[] argTypes = parameterizedType.arguments; if (argTypes != null && typeVariables != null) { // may be null in error cases parameterizedType.boundCheck(scope, this.typeArguments); } } }
public void checkTypeArgumentRedundancy( ParameterizedTypeBinding allocationType, ReferenceBinding enclosingType, TypeBinding[] argumentTypes, final BlockScope scope) { ProblemReporter reporter = scope.problemReporter(); if ((reporter.computeSeverity(IProblem.RedundantSpecificationOfTypeArguments) == ProblemSeverities.Ignore) || scope.compilerOptions().sourceLevel < ClassFileConstants.JDK1_7) return; if (allocationType.arguments == null) return; // raw binding if (this.genericTypeArguments != null) return; // diamond can't occur with explicit type args for constructor if (argumentTypes == Binding.NO_PARAMETERS && this.typeExpected instanceof ParameterizedTypeBinding) { ParameterizedTypeBinding expected = (ParameterizedTypeBinding) this.typeExpected; if (expected.arguments != null && allocationType.arguments.length == expected.arguments.length) { // check the case when no ctor takes no params and inference uses the expected type directly // eg. X<String> x = new X<String>() int i; for (i = 0; i < allocationType.arguments.length; i++) { if (allocationType.arguments[i] != expected.arguments[i]) break; } if (i == allocationType.arguments.length) { reporter.redundantSpecificationOfTypeArguments(this.type, allocationType.arguments); return; } } } TypeBinding[] inferredTypes = inferElidedTypes(allocationType.genericType(), enclosingType, argumentTypes, scope); if (inferredTypes == null) { return; } for (int i = 0; i < inferredTypes.length; i++) { if (inferredTypes[i] != allocationType.arguments[i]) return; } reporter.redundantSpecificationOfTypeArguments(this.type, allocationType.arguments); }
boolean addConstraintsFromTypeParameters( TypeBinding subCandidate, ParameterizedTypeBinding ca, List<ConstraintFormula> constraints) { TypeBinding[] ai = ca.arguments; // C<A1,A2,...> if (ai == null) return true; // no arguments here means nothing to check TypeBinding cb = subCandidate.findSuperTypeOriginatingFrom(ca); // C<B1,B2,...> if (cb == null) return false; // nothing here means we failed if (TypeBinding.equalsEquals(ca, cb)) // incl C#RAW vs C#RAW return true; if (!(cb instanceof ParameterizedTypeBinding)) { // if C is parameterized with its own type variables, there're no more constraints to be // created here, otherwise let's fail return ca.isParameterizedWithOwnVariables(); } TypeBinding[] bi = ((ParameterizedTypeBinding) cb).arguments; if (cb.isRawType() || bi == null || bi.length == 0) return (this.isSoft && InferenceContext18.SIMULATE_BUG_JDK_8026527) ? true : false; // FALSE would conform to the spec for (int i = 0; i < ai.length; i++) constraints.add( ConstraintTypeFormula.create(bi[i], ai[i], TYPE_ARGUMENT_CONTAINED, this.isSoft)); return true; }
private TypeBinding internalResolveLeafType( Scope scope, ReferenceBinding enclosingType, boolean checkBounds) { ReferenceBinding currentType; if (enclosingType == null) { this.resolvedType = scope.getType(this.token); if (this.resolvedType.isValidBinding()) { currentType = (ReferenceBinding) this.resolvedType; } else { reportInvalidType(scope); switch (this.resolvedType.problemId()) { case ProblemReasons.NotFound: case ProblemReasons.NotVisible: case ProblemReasons.InheritedNameHidesEnclosingName: TypeBinding type = this.resolvedType.closestMatch(); if (type instanceof ReferenceBinding) { currentType = (ReferenceBinding) type; break; } // $FALL-THROUGH$ - unable to complete type binding, but still resolve type arguments default: boolean isClassScope = scope.kind == Scope.CLASS_SCOPE; int argLength = this.typeArguments.length; for (int i = 0; i < argLength; i++) { TypeReference typeArgument = this.typeArguments[i]; if (isClassScope) { typeArgument.resolveType((ClassScope) scope); } else { typeArgument.resolveType((BlockScope) scope, checkBounds); } } return null; } // be resilient, still attempt resolving arguments } enclosingType = currentType.enclosingType(); // if member type if (enclosingType != null) { enclosingType = currentType.isStatic() ? (ReferenceBinding) scope .environment() .convertToRawType( enclosingType, false /*do not force conversion of enclosing types*/) : scope.environment().convertToParameterizedType(enclosingType); currentType = scope .environment() .createParameterizedType( (ReferenceBinding) currentType.erasure(), null /* no arg */, enclosingType); } } else { // resolving member type (relatively to enclosingType) this.resolvedType = currentType = scope.getMemberType(this.token, enclosingType); if (!this.resolvedType.isValidBinding()) { scope.problemReporter().invalidEnclosingType(this, currentType, enclosingType); return null; } if (isTypeUseDeprecated(currentType, scope)) scope.problemReporter().deprecatedType(currentType, this); ReferenceBinding currentEnclosing = currentType.enclosingType(); if (currentEnclosing != null && currentEnclosing.erasure() != enclosingType.erasure()) { enclosingType = currentEnclosing; // inherited member type, leave it associated with its enclosing // rather than subtype } } // check generic and arity boolean isClassScope = scope.kind == Scope.CLASS_SCOPE; TypeReference keep = null; if (isClassScope) { keep = ((ClassScope) scope).superTypeReference; ((ClassScope) scope).superTypeReference = null; } int argLength = this.typeArguments.length; TypeBinding[] argTypes = new TypeBinding[argLength]; boolean argHasError = false; ReferenceBinding currentOriginal = (ReferenceBinding) currentType.original(); for (int i = 0; i < argLength; i++) { TypeReference typeArgument = this.typeArguments[i]; TypeBinding argType = isClassScope ? typeArgument.resolveTypeArgument((ClassScope) scope, currentOriginal, i) : typeArgument.resolveTypeArgument((BlockScope) scope, currentOriginal, i); this.bits |= (typeArgument.bits & ASTNode.HasTypeAnnotations); if (argType == null) { argHasError = true; } else { if (typeArgument.annotations != null) argTypes[i] = captureTypeAnnotations(scope, enclosingType, argType, typeArgument.annotations[0]); else argTypes[i] = argType; } } if (argHasError) { return null; } if (isClassScope) { ((ClassScope) scope).superTypeReference = keep; if (((ClassScope) scope).detectHierarchyCycle(currentOriginal, this)) return null; } final boolean isDiamond = (this.bits & ASTNode.IsDiamond) != 0; TypeVariableBinding[] typeVariables = currentOriginal.typeVariables(); if (typeVariables == Binding.NO_TYPE_VARIABLES) { // non generic invoked with arguments boolean isCompliant15 = scope.compilerOptions().originalSourceLevel >= ClassFileConstants.JDK1_5; if ((currentOriginal.tagBits & TagBits.HasMissingType) == 0) { if (isCompliant15) { // below 1.5, already reported as syntax error this.resolvedType = currentType; scope .problemReporter() .nonGenericTypeCannotBeParameterized(0, this, currentType, argTypes); return null; } } // resilience do not rebuild a parameterized type unless compliance is allowing it if (!isCompliant15) { if (!this.resolvedType.isValidBinding()) return currentType; return this.resolvedType = currentType; } // if missing generic type, and compliance >= 1.5, then will rebuild a parameterized binding } else if (argLength != typeVariables.length) { if (!isDiamond) { // check arity, IsDiamond never set for 1.6- scope.problemReporter().incorrectArityForParameterizedType(this, currentType, argTypes); return null; } } else if (!currentType.isStatic()) { ReferenceBinding actualEnclosing = currentType.enclosingType(); if (actualEnclosing != null && actualEnclosing.isRawType()) { scope .problemReporter() .rawMemberTypeCannotBeParameterized( this, scope.environment().createRawType(currentOriginal, actualEnclosing), argTypes); return null; } } ParameterizedTypeBinding parameterizedType = scope.environment().createParameterizedType(currentOriginal, argTypes, enclosingType); // check argument type compatibility for non <> cases - <> case needs no bounds check, we will // scream foul if needed during inference. if (!isDiamond) { if (checkBounds) // otherwise will do it in Scope.connectTypeVariables() or generic method // resolution parameterizedType.boundCheck(scope, this.typeArguments); else scope.deferBoundCheck(this); } if (isTypeUseDeprecated(parameterizedType, scope)) reportDeprecatedType(parameterizedType, scope); if (!this.resolvedType.isValidBinding()) { return parameterizedType; } return this.resolvedType = parameterizedType; }