1 /******************************************************************************* 2 * Copyright (c) 2005, 2014 IBM Corporation and others. 3 * All rights reserved. This program and the accompanying materials 4 * are made available under the terms of the Eclipse Public License v1.0 5 * which accompanies this distribution, and is available at 6 * http://www.eclipse.org/legal/epl-v10.html 7 * 8 * Contributors: 9 * IBM Corporation - initial API and implementation 10 * Stephan Herrmann - Contribution for 11 * bug 349326 - [1.7] new warning for missing try-with-resources 12 * bug 359362 - FUP of bug 349326: Resource leak on non-Closeable resource 13 * bug 358903 - Filter practically unimportant resource leak warnings 14 * Bug 417295 - [1.8[[null] Massage type annotated null analysis to gel well with deep encoded type bindings. 15 * Bug 400874 - [1.8][compiler] Inference infrastructure should evolve to meet JLS8 18.x (Part G of JSR335 spec) 16 * Bug 423504 - [1.8] Implement "18.5.3 Functional Interface Parameterization Inference" 17 * Bug 426676 - [1.8][compiler] Wrong generic method type inferred from lambda expression 18 * Bug 427411 - [1.8][generics] JDT reports type mismatch when using method that returns generic type 19 * Bug 428019 - [1.8][compiler] Type inference failure with nested generic invocation. 20 * Bug 435962 - [RC2] StackOverFlowError when building 21 * Bug 438458 - [1.8][null] clean up handling of null type annotations wrt type variables 22 *******************************************************************************/ 23 package org.eclipse.jdt.internal.compiler.lookup; 24 25 import java.util.List; 26 import java.util.Set; 27 28 import org.eclipse.jdt.core.compiler.CharOperation; 29 import org.eclipse.jdt.internal.compiler.ast.Wildcard; 30 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; 31 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; 32 33 /* 34 * A wildcard acts as an argument for parameterized types, allowing to 35 * abstract parameterized types, e.g. List<String> is not compatible with List<Object>, 36 * but compatible with List<?>. 37 */ 38 public class WildcardBinding extends ReferenceBinding { 39 40 public ReferenceBinding genericType; 41 public int rank; 42 public TypeBinding bound; // when unbound denotes the corresponding type variable (so as to retrieve its bound lazily) 43 public TypeBinding[] otherBounds; // only positionned by lub computations (if so, #bound is also set) and associated to EXTENDS mode 44 char[] genericSignature; 45 public int boundKind; 46 ReferenceBinding superclass; 47 ReferenceBinding[] superInterfaces; 48 TypeVariableBinding typeVariable; // corresponding variable 49 LookupEnvironment environment; 50 51 /** 52 * When unbound, the bound denotes the corresponding type variable (so as to retrieve its bound lazily) 53 */ WildcardBinding(ReferenceBinding genericType, int rank, TypeBinding bound, TypeBinding[] otherBounds, int boundKind, LookupEnvironment environment)54 public WildcardBinding(ReferenceBinding genericType, int rank, TypeBinding bound, TypeBinding[] otherBounds, int boundKind, LookupEnvironment environment) { 55 this.rank = rank; 56 this.boundKind = boundKind; 57 this.modifiers = ClassFileConstants.AccPublic | ExtraCompilerModifiers.AccGenericSignature; // treat wildcard as public 58 this.environment = environment; 59 initialize(genericType, bound, otherBounds); 60 if (genericType instanceof UnresolvedReferenceBinding) 61 ((UnresolvedReferenceBinding) genericType).addWrapper(this, environment); 62 if (bound instanceof UnresolvedReferenceBinding) 63 ((UnresolvedReferenceBinding) bound).addWrapper(this, environment); 64 this.tagBits |= TagBits.HasUnresolvedTypeVariables; // cleared in resolve() 65 this.typeBits = TypeIds.BitUninitialized; 66 } 67 bound()68 TypeBinding bound() { 69 return this.bound; 70 } 71 boundKind()72 int boundKind() { 73 return this.boundKind; 74 } 75 allBounds()76 public TypeBinding allBounds() { 77 if (this.otherBounds == null || this.otherBounds.length == 0) 78 return this.bound; 79 ReferenceBinding[] allBounds = new ReferenceBinding[this.otherBounds.length+1]; 80 try { 81 allBounds[0] = (ReferenceBinding) this.bound; 82 System.arraycopy(this.otherBounds, 0, allBounds, 1, this.otherBounds.length); 83 } catch (ClassCastException cce) { 84 return this.bound; 85 } catch (ArrayStoreException ase) { 86 return this.bound; 87 } 88 return new IntersectionCastTypeBinding(allBounds, this.environment); 89 } 90 actualType()91 public ReferenceBinding actualType() { 92 return this.genericType; 93 } 94 additionalBounds()95 TypeBinding[] additionalBounds() { 96 return this.otherBounds; 97 } 98 kind()99 public int kind() { 100 return this.otherBounds == null ? Binding.WILDCARD_TYPE : Binding.INTERSECTION_TYPE; 101 } 102 103 /** 104 * Returns true if the argument type satisfies the wildcard bound(s) 105 */ boundCheck(TypeBinding argumentType)106 public boolean boundCheck(TypeBinding argumentType) { 107 switch (this.boundKind) { 108 case Wildcard.UNBOUND : 109 return true; 110 case Wildcard.EXTENDS : 111 if (!argumentType.isCompatibleWith(this.bound)) return false; 112 // check other bounds (lub scenario) 113 for (int i = 0, length = this.otherBounds == null ? 0 : this.otherBounds.length; i < length; i++) { 114 if (!argumentType.isCompatibleWith(this.otherBounds[i])) return false; 115 } 116 return true; 117 default: // SUPER 118 // ? super Exception ok for: IOException, since it would be ok for (Exception)ioException 119 return argumentType.isCompatibleWith(this.bound); 120 } 121 } 122 /** 123 * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#canBeInstantiated() 124 */ canBeInstantiated()125 public boolean canBeInstantiated() { 126 // cannot be asked per construction 127 return false; 128 } 129 130 /** 131 * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#collectMissingTypes(java.util.List) 132 */ collectMissingTypes(List missingTypes)133 public List collectMissingTypes(List missingTypes) { 134 if ((this.tagBits & TagBits.HasMissingType) != 0) { 135 missingTypes = this.bound.collectMissingTypes(missingTypes); 136 } 137 return missingTypes; 138 } 139 140 /** 141 * Collect the substitutes into a map for certain type variables inside the receiver type 142 * e.g. Collection<T>.collectSubstitutes(Collection<List<X>>, Map), will populate Map with: T --> List<X> 143 * Constraints: 144 * A << F corresponds to: F.collectSubstitutes(..., A, ..., CONSTRAINT_EXTENDS (1)) 145 * A = F corresponds to: F.collectSubstitutes(..., A, ..., CONSTRAINT_EQUAL (0)) 146 * A >> F corresponds to: F.collectSubstitutes(..., A, ..., CONSTRAINT_SUPER (2)) 147 */ collectSubstitutes(Scope scope, TypeBinding actualType, InferenceContext inferenceContext, int constraint)148 public void collectSubstitutes(Scope scope, TypeBinding actualType, InferenceContext inferenceContext, int constraint) { 149 150 if ((this.tagBits & TagBits.HasTypeVariable) == 0) return; 151 if (actualType == TypeBinding.NULL || actualType.kind() == POLY_TYPE) return; 152 153 if (actualType.isCapture()) { 154 CaptureBinding capture = (CaptureBinding) actualType; 155 actualType = capture.wildcard; 156 // this method should only be called in 1.7- inference, hence we don't expect to see CaptureBinding18 here. 157 } 158 159 switch (constraint) { 160 case TypeConstants.CONSTRAINT_EXTENDS : // A << F 161 switch (this.boundKind) { 162 case Wildcard.UNBOUND: // F={?} 163 // switch (actualType.kind()) { 164 // case Binding.WILDCARD_TYPE : 165 // WildcardBinding actualWildcard = (WildcardBinding) actualType; 166 // switch(actualWildcard.kind) { 167 // case Wildcard.UNBOUND: // A={?} << F={?} --> 0 168 // break; 169 // case Wildcard.EXTENDS: // A={? extends V} << F={?} ---> 0 170 // break; 171 // case Wildcard.SUPER: // A={? super V} << F={?} ---> 0 172 // break; 173 // } 174 // break; 175 // case Binding.INTERSECTION_TYPE :// A={? extends V1&...&Vn} << F={?} ---> 0 176 // break; 177 // default :// A=V << F={?} ---> 0 178 // break; 179 // } 180 break; 181 case Wildcard.EXTENDS: // F={? extends U} 182 switch(actualType.kind()) { 183 case Binding.WILDCARD_TYPE : 184 WildcardBinding actualWildcard = (WildcardBinding) actualType; 185 switch(actualWildcard.boundKind) { 186 case Wildcard.UNBOUND: // A={?} << F={? extends U} --> 0 187 break; 188 case Wildcard.EXTENDS: // A={? extends V} << F={? extends U} ---> V << U 189 this.bound.collectSubstitutes(scope, actualWildcard.bound, inferenceContext, TypeConstants.CONSTRAINT_EXTENDS); 190 break; 191 case Wildcard.SUPER: // A={? super V} << F={? extends U} ---> 0 192 break; 193 } 194 break; 195 case Binding.INTERSECTION_TYPE : // A={? extends V1&...&Vn} << F={? extends U} ---> V1 << U, ..., Vn << U 196 WildcardBinding actualIntersection = (WildcardBinding) actualType; 197 this.bound.collectSubstitutes(scope, actualIntersection.bound, inferenceContext, TypeConstants.CONSTRAINT_EXTENDS); 198 for (int i = 0, length = actualIntersection.otherBounds.length; i < length; i++) { 199 this.bound.collectSubstitutes(scope, actualIntersection.otherBounds[i], inferenceContext, TypeConstants.CONSTRAINT_EXTENDS); 200 } 201 break; 202 default : // A=V << F={? extends U} ---> V << U 203 this.bound.collectSubstitutes(scope, actualType, inferenceContext, TypeConstants.CONSTRAINT_EXTENDS); 204 break; 205 } 206 break; 207 case Wildcard.SUPER: // F={? super U} 208 switch (actualType.kind()) { 209 case Binding.WILDCARD_TYPE : 210 WildcardBinding actualWildcard = (WildcardBinding) actualType; 211 switch(actualWildcard.boundKind) { 212 case Wildcard.UNBOUND: // A={?} << F={? super U} --> 0 213 break; 214 case Wildcard.EXTENDS: // A={? extends V} << F={? super U} ---> 0 215 break; 216 case Wildcard.SUPER: // A={? super V} << F={? super U} ---> 0 217 this.bound.collectSubstitutes(scope, actualWildcard.bound, inferenceContext, TypeConstants.CONSTRAINT_SUPER); 218 for (int i = 0, length = actualWildcard.otherBounds == null ? 0 : actualWildcard.otherBounds.length; i < length; i++) { 219 this.bound.collectSubstitutes(scope, actualWildcard.otherBounds[i], inferenceContext, TypeConstants.CONSTRAINT_SUPER); 220 } 221 break; 222 } 223 break; 224 case Binding.INTERSECTION_TYPE : // A={? extends V1&...&Vn} << F={? super U} ---> 0 225 break; 226 default :// A=V << F={? super U} ---> V >> U 227 this.bound.collectSubstitutes(scope, actualType, inferenceContext, TypeConstants.CONSTRAINT_SUPER); 228 break; 229 } 230 break; 231 } 232 break; 233 case TypeConstants.CONSTRAINT_EQUAL : // A == F 234 switch (this.boundKind) { 235 case Wildcard.UNBOUND: // F={?} 236 // switch (actualType.kind()) { 237 // case Binding.WILDCARD_TYPE : 238 // WildcardBinding actualWildcard = (WildcardBinding) actualType; 239 // switch(actualWildcard.kind) { 240 // case Wildcard.UNBOUND: // A={?} == F={?} --> 0 241 // break; 242 // case Wildcard.EXTENDS: // A={? extends V} == F={?} ---> 0 243 // break; 244 // case Wildcard.SUPER: // A={? super V} == F={?} ---> 0 245 // break; 246 // } 247 // break; 248 // case Binding.INTERSECTION_TYPE :// A={? extends V1&...&Vn} == F={?} ---> 0 249 // break; 250 // default :// A=V == F={?} ---> 0 251 // break; 252 // } 253 break; 254 case Wildcard.EXTENDS: // F={? extends U} 255 switch (actualType.kind()) { 256 case Binding.WILDCARD_TYPE : 257 WildcardBinding actualWildcard = (WildcardBinding) actualType; 258 switch(actualWildcard.boundKind) { 259 case Wildcard.UNBOUND: // A={?} == F={? extends U} --> 0 260 break; 261 case Wildcard.EXTENDS: // A={? extends V} == F={? extends U} ---> V == U 262 this.bound.collectSubstitutes(scope, actualWildcard.bound, inferenceContext, TypeConstants.CONSTRAINT_EQUAL); 263 for (int i = 0, length = actualWildcard.otherBounds == null ? 0 : actualWildcard.otherBounds.length; i < length; i++) { 264 this.bound.collectSubstitutes(scope, actualWildcard.otherBounds[i], inferenceContext, TypeConstants.CONSTRAINT_EQUAL); 265 } 266 break; 267 case Wildcard.SUPER: // A={? super V} == F={? extends U} ---> 0 268 break; 269 } 270 break; 271 case Binding.INTERSECTION_TYPE : // A={? extends V1&...&Vn} == F={? extends U} ---> V1 == U, ..., Vn == U 272 WildcardBinding actuaIntersection = (WildcardBinding) actualType; 273 this.bound.collectSubstitutes(scope, actuaIntersection.bound, inferenceContext, TypeConstants.CONSTRAINT_EQUAL); 274 for (int i = 0, length = actuaIntersection.otherBounds == null ? 0 : actuaIntersection.otherBounds.length; i < length; i++) { 275 this.bound.collectSubstitutes(scope, actuaIntersection.otherBounds[i], inferenceContext, TypeConstants.CONSTRAINT_EQUAL); 276 } 277 break; 278 default : // A=V == F={? extends U} ---> 0 279 break; 280 } 281 break; 282 case Wildcard.SUPER: // F={? super U} 283 switch (actualType.kind()) { 284 case Binding.WILDCARD_TYPE : 285 WildcardBinding actualWildcard = (WildcardBinding) actualType; 286 switch(actualWildcard.boundKind) { 287 case Wildcard.UNBOUND: // A={?} == F={? super U} --> 0 288 break; 289 case Wildcard.EXTENDS: // A={? extends V} == F={? super U} ---> 0 290 break; 291 case Wildcard.SUPER: // A={? super V} == F={? super U} ---> 0 292 this.bound.collectSubstitutes(scope, actualWildcard.bound, inferenceContext, TypeConstants.CONSTRAINT_EQUAL); 293 for (int i = 0, length = actualWildcard.otherBounds == null ? 0 : actualWildcard.otherBounds.length; i < length; i++) { 294 this.bound.collectSubstitutes(scope, actualWildcard.otherBounds[i], inferenceContext, TypeConstants.CONSTRAINT_EQUAL); 295 } 296 break; 297 } 298 break; 299 case Binding.INTERSECTION_TYPE : // A={? extends V1&...&Vn} == F={? super U} ---> 0 300 break; 301 default : // A=V == F={? super U} ---> 0 302 break; 303 } 304 break; 305 } 306 break; 307 case TypeConstants.CONSTRAINT_SUPER : // A >> F 308 switch (this.boundKind) { 309 case Wildcard.UNBOUND: // F={?} 310 // switch (actualType.kind()) { 311 // case Binding.WILDCARD_TYPE : 312 // WildcardBinding actualWildcard = (WildcardBinding) actualType; 313 // switch(actualWildcard.kind) { 314 // case Wildcard.UNBOUND: // A={?} >> F={?} --> 0 315 // break; 316 // case Wildcard.EXTENDS: // A={? extends V} >> F={?} ---> 0 317 // break; 318 // case Wildcard.SUPER: // A={? super V} >> F={?} ---> 0 319 // break; 320 // } 321 // break; 322 // case Binding.INTERSECTION_TYPE :// A={? extends V1&...&Vn} >> F={?} ---> 0 323 // break; 324 // default :// A=V >> F={?} ---> 0 325 // break; 326 // } 327 break; 328 case Wildcard.EXTENDS: // F={? extends U} 329 switch (actualType.kind()) { 330 case Binding.WILDCARD_TYPE : 331 WildcardBinding actualWildcard = (WildcardBinding) actualType; 332 switch(actualWildcard.boundKind) { 333 case Wildcard.UNBOUND: // A={?} >> F={? extends U} --> 0 334 break; 335 case Wildcard.EXTENDS: // A={? extends V} >> F={? extends U} ---> V >> U 336 this.bound.collectSubstitutes(scope, actualWildcard.bound, inferenceContext, TypeConstants.CONSTRAINT_SUPER); 337 for (int i = 0, length = actualWildcard.otherBounds == null ? 0 : actualWildcard.otherBounds.length; i < length; i++) { 338 this.bound.collectSubstitutes(scope, actualWildcard.otherBounds[i], inferenceContext, TypeConstants.CONSTRAINT_SUPER); 339 } 340 break; 341 case Wildcard.SUPER: // A={? super V} >> F={? extends U} ---> 0 342 break; 343 } 344 break; 345 case Binding.INTERSECTION_TYPE : // A={? extends V1&...&Vn} >> F={? extends U} ---> V1 >> U, ..., Vn >> U 346 WildcardBinding actualIntersection = (WildcardBinding) actualType; 347 this.bound.collectSubstitutes(scope, actualIntersection.bound, inferenceContext, TypeConstants.CONSTRAINT_SUPER); 348 for (int i = 0, length = actualIntersection.otherBounds == null ? 0 : actualIntersection.otherBounds.length; i < length; i++) { 349 this.bound.collectSubstitutes(scope, actualIntersection.otherBounds[i], inferenceContext, TypeConstants.CONSTRAINT_SUPER); 350 } 351 break; 352 default : // A=V == F={? extends U} ---> 0 353 break; 354 } 355 break; 356 case Wildcard.SUPER: // F={? super U} 357 switch (actualType.kind()) { 358 case Binding.WILDCARD_TYPE : 359 WildcardBinding actualWildcard = (WildcardBinding) actualType; 360 switch(actualWildcard.boundKind) { 361 case Wildcard.UNBOUND: // A={?} >> F={? super U} --> 0 362 break; 363 case Wildcard.EXTENDS: // A={? extends V} >> F={? super U} ---> 0 364 break; 365 case Wildcard.SUPER: // A={? super V} >> F={? super U} ---> V >> U 366 this.bound.collectSubstitutes(scope, actualWildcard.bound, inferenceContext, TypeConstants.CONSTRAINT_SUPER); 367 for (int i = 0, length = actualWildcard.otherBounds == null ? 0 : actualWildcard.otherBounds.length; i < length; i++) { 368 this.bound.collectSubstitutes(scope, actualWildcard.otherBounds[i], inferenceContext, TypeConstants.CONSTRAINT_SUPER); 369 } 370 break; 371 } 372 break; 373 case Binding.INTERSECTION_TYPE : // A={? extends V1&...&Vn} >> F={? super U} ---> 0 374 break; 375 default : // A=V >> F={? super U} ---> 0 376 break; 377 } 378 break; 379 } 380 break; 381 } 382 } 383 384 /* 385 * genericTypeKey {rank}*|+|- [boundKey] 386 * p.X<T> { X<?> ... } --> Lp/X<TT;>;{0}* 387 */ computeUniqueKey(boolean isLeaf)388 public char[] computeUniqueKey(boolean isLeaf) { 389 char[] genericTypeKey = this.genericType.computeUniqueKey(false/*not a leaf*/); 390 char[] wildCardKey; 391 // We now encode the rank also in the binding key - https://bugs.eclipse.org/bugs/show_bug.cgi?id=234609 392 char[] rankComponent = ('{' + String.valueOf(this.rank) + '}').toCharArray(); 393 switch (this.boundKind) { 394 case Wildcard.UNBOUND : 395 wildCardKey = TypeConstants.WILDCARD_STAR; 396 break; 397 case Wildcard.EXTENDS : 398 wildCardKey = CharOperation.concat(TypeConstants.WILDCARD_PLUS, this.bound.computeUniqueKey(false/*not a leaf*/)); 399 break; 400 default: // SUPER 401 wildCardKey = CharOperation.concat(TypeConstants.WILDCARD_MINUS, this.bound.computeUniqueKey(false/*not a leaf*/)); 402 break; 403 } 404 return CharOperation.concat(genericTypeKey, rankComponent, wildCardKey); 405 } 406 407 408 409 /** 410 * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#constantPoolName() 411 */ constantPoolName()412 public char[] constantPoolName() { 413 return erasure().constantPoolName(); 414 } 415 clone(TypeBinding immaterial)416 public TypeBinding clone(TypeBinding immaterial) { 417 return new WildcardBinding(this.genericType, this.rank, this.bound, this.otherBounds, this.boundKind, this.environment); 418 } 419 annotatedDebugName()420 public String annotatedDebugName() { 421 StringBuffer buffer = new StringBuffer(16); 422 AnnotationBinding [] annotations = getTypeAnnotations(); 423 for (int i = 0, length = annotations == null ? 0 : annotations.length; i < length; i++) { 424 buffer.append(annotations[i]); 425 buffer.append(' '); 426 } 427 switch (this.boundKind) { 428 case Wildcard.UNBOUND : 429 return buffer.append(TypeConstants.WILDCARD_NAME).toString(); 430 case Wildcard.EXTENDS : 431 if (this.otherBounds == null) 432 return buffer.append(CharOperation.concat(TypeConstants.WILDCARD_NAME, TypeConstants.WILDCARD_EXTENDS, this.bound.annotatedDebugName().toCharArray())).toString(); 433 buffer.append(this.bound.annotatedDebugName()); 434 for (int i = 0, length = this.otherBounds.length; i < length; i++) { 435 buffer.append(" & ").append(this.otherBounds[i].annotatedDebugName()); //$NON-NLS-1$ 436 } 437 return buffer.toString(); 438 default: // SUPER 439 return buffer.append(CharOperation.concat(TypeConstants.WILDCARD_NAME, TypeConstants.WILDCARD_SUPER, this.bound.annotatedDebugName().toCharArray())).toString(); 440 } 441 } 442 /** 443 * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#debugName() 444 */ debugName()445 public String debugName() { 446 return toString(); 447 } 448 449 /* (non-Javadoc) 450 * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#erasure() 451 */ erasure()452 public TypeBinding erasure() { 453 if (this.otherBounds == null) { 454 if (this.boundKind == Wildcard.EXTENDS) 455 return this.bound.erasure(); 456 TypeVariableBinding var = typeVariable(); 457 if (var != null) 458 return var.erasure(); 459 return this.genericType; // if typeVariable() == null, then its inconsistent & return this.genericType to avoid NPE case 460 } 461 // intersection type 462 return this.bound.id == TypeIds.T_JavaLangObject 463 ? this.otherBounds[0].erasure() // use first explicit bound to improve stackmap 464 : this.bound.erasure(); 465 } 466 467 /* (non-Javadoc) 468 * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#signature() 469 */ genericTypeSignature()470 public char[] genericTypeSignature() { 471 if (this.genericSignature == null) { 472 switch (this.boundKind) { 473 case Wildcard.UNBOUND : 474 this.genericSignature = TypeConstants.WILDCARD_STAR; 475 break; 476 case Wildcard.EXTENDS : 477 this.genericSignature = CharOperation.concat(TypeConstants.WILDCARD_PLUS, this.bound.genericTypeSignature()); 478 break; 479 default: // SUPER 480 this.genericSignature = CharOperation.concat(TypeConstants.WILDCARD_MINUS, this.bound.genericTypeSignature()); 481 } 482 } 483 return this.genericSignature; 484 } 485 hashCode()486 public int hashCode() { 487 return this.genericType.hashCode(); 488 } 489 hasTypeBit(int bit)490 public boolean hasTypeBit(int bit) { 491 if (this.typeBits == TypeIds.BitUninitialized) { 492 // initialize from upper bounds 493 this.typeBits = 0; 494 if (this.superclass != null && this.superclass.hasTypeBit(~TypeIds.BitUninitialized)) 495 this.typeBits |= (this.superclass.typeBits & TypeIds.InheritableBits); 496 if (this.superInterfaces != null) 497 for (int i = 0, l = this.superInterfaces.length; i < l; i++) 498 if (this.superInterfaces[i].hasTypeBit(~TypeIds.BitUninitialized)) 499 this.typeBits |= (this.superInterfaces[i].typeBits & TypeIds.InheritableBits); 500 } 501 return (this.typeBits & bit) != 0; 502 } 503 initialize(ReferenceBinding someGenericType, TypeBinding someBound, TypeBinding[] someOtherBounds)504 void initialize(ReferenceBinding someGenericType, TypeBinding someBound, TypeBinding[] someOtherBounds) { 505 this.genericType = someGenericType; 506 this.bound = someBound; 507 this.otherBounds = someOtherBounds; 508 if (someGenericType != null) { 509 this.fPackage = someGenericType.getPackage(); 510 } 511 if (someBound != null) { 512 this.tagBits |= someBound.tagBits & (TagBits.HasTypeVariable | TagBits.HasMissingType | TagBits.ContainsNestedTypeReferences | 513 TagBits.HasNullTypeAnnotation | TagBits.HasCapturedWildcard); 514 } 515 if (someOtherBounds != null) { 516 for (int i = 0, max = someOtherBounds.length; i < max; i++) { 517 TypeBinding someOtherBound = someOtherBounds[i]; 518 this.tagBits |= someOtherBound.tagBits & (TagBits.ContainsNestedTypeReferences | TagBits.HasNullTypeAnnotation | TagBits.HasCapturedWildcard); 519 } 520 } 521 } 522 523 /** 524 * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#isSuperclassOf(org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding) 525 */ isSuperclassOf(ReferenceBinding otherType)526 public boolean isSuperclassOf(ReferenceBinding otherType) { 527 if (this.boundKind == Wildcard.SUPER) { 528 if (this.bound instanceof ReferenceBinding) { 529 return ((ReferenceBinding) this.bound).isSuperclassOf(otherType); 530 } else { // array bound 531 return otherType.id == TypeIds.T_JavaLangObject; 532 } 533 } 534 return false; 535 } 536 537 /** 538 * Returns true if the current type denotes an intersection type: Number & Comparable<?> 539 */ isIntersectionType()540 public boolean isIntersectionType() { 541 return this.otherBounds != null; 542 } 543 544 @Override getIntersectingTypes()545 public ReferenceBinding[] getIntersectingTypes() { 546 if (isIntersectionType()) { 547 ReferenceBinding[] allBounds = new ReferenceBinding[this.otherBounds.length+1]; 548 try { 549 allBounds[0] = (ReferenceBinding) this.bound; 550 System.arraycopy(this.otherBounds, 0, allBounds, 1, this.otherBounds.length); 551 } catch (ClassCastException cce) { 552 return null; 553 } catch (ArrayStoreException ase) { 554 return null; 555 } 556 return allBounds; 557 } 558 return null; 559 } 560 isHierarchyConnected()561 public boolean isHierarchyConnected() { 562 return this.superclass != null && this.superInterfaces != null; 563 } 564 565 // to prevent infinite recursion when inspecting recursive generics: 566 boolean inRecursiveFunction = false; 567 568 @Override enterRecursiveFunction()569 public boolean enterRecursiveFunction() { 570 if (this.inRecursiveFunction) 571 return false; 572 this.inRecursiveFunction = true; 573 return true; 574 } 575 @Override exitRecursiveFunction()576 public void exitRecursiveFunction() { 577 this.inRecursiveFunction = false; 578 } 579 isProperType(boolean admitCapture18)580 public boolean isProperType(boolean admitCapture18) { 581 if (this.inRecursiveFunction) 582 return true; 583 this.inRecursiveFunction = true; 584 try { 585 if (this.bound != null && !this.bound.isProperType(admitCapture18)) 586 return false; 587 if (this.superclass != null && !this.superclass.isProperType(admitCapture18)) 588 return false; 589 if (this.superInterfaces != null) 590 for (int i = 0, l = this.superInterfaces.length; i < l; i++) 591 if (!this.superInterfaces[i].isProperType(admitCapture18)) 592 return false; 593 return true; 594 } finally { 595 this.inRecursiveFunction = false; 596 } 597 } 598 substituteInferenceVariable(InferenceVariable var, TypeBinding substituteType)599 TypeBinding substituteInferenceVariable(InferenceVariable var, TypeBinding substituteType) { 600 boolean haveSubstitution = false; 601 TypeBinding currentBound = this.bound; 602 if (currentBound != null) { 603 currentBound = currentBound.substituteInferenceVariable(var, substituteType); 604 haveSubstitution |= TypeBinding.notEquals(currentBound, this.bound); 605 } 606 TypeBinding[] currentOtherBounds = null; 607 if (this.otherBounds != null) { 608 int length = this.otherBounds.length; 609 if (haveSubstitution) 610 System.arraycopy(this.otherBounds, 0, currentOtherBounds=new ReferenceBinding[length], 0, length); 611 for (int i = 0; i < length; i++) { 612 TypeBinding currentOtherBound = this.otherBounds[i]; 613 if (currentOtherBound != null) { 614 currentOtherBound = currentOtherBound.substituteInferenceVariable(var, substituteType); 615 if (TypeBinding.notEquals(currentOtherBound, this.otherBounds[i])) { 616 if (currentOtherBounds == null) 617 System.arraycopy(this.otherBounds, 0, currentOtherBounds=new ReferenceBinding[length], 0, length); 618 currentOtherBounds[i] = currentOtherBound; 619 } 620 } 621 } 622 } 623 haveSubstitution |= currentOtherBounds != null; 624 if (haveSubstitution) { 625 return this.environment.createWildcard(this.genericType, this.rank, currentBound, currentOtherBounds, this.boundKind); 626 } 627 return this; 628 } 629 630 /** 631 * Returns true if the type is a wildcard 632 */ isUnboundWildcard()633 public boolean isUnboundWildcard() { 634 return this.boundKind == Wildcard.UNBOUND; 635 } 636 637 /** 638 * Returns true if the type is a wildcard 639 */ isWildcard()640 public boolean isWildcard() { 641 return true; 642 } 643 rank()644 int rank() { 645 return this.rank; 646 } 647 648 /* (non-Javadoc) 649 * @see org.eclipse.jdt.internal.compiler.lookup.Binding#readableName() 650 */ readableName()651 public char[] readableName() { 652 switch (this.boundKind) { 653 case Wildcard.UNBOUND : 654 return TypeConstants.WILDCARD_NAME; 655 case Wildcard.EXTENDS : 656 if (this.otherBounds == null) 657 return CharOperation.concat(TypeConstants.WILDCARD_NAME, TypeConstants.WILDCARD_EXTENDS, this.bound.readableName()); 658 StringBuffer buffer = new StringBuffer(10); 659 buffer.append(this.bound.readableName()); 660 for (int i = 0, length = this.otherBounds.length; i < length; i++) { 661 buffer.append('&').append(this.otherBounds[i].readableName()); 662 } 663 int length; 664 char[] result = new char[length = buffer.length()]; 665 buffer.getChars(0, length, result, 0); 666 return result; 667 default: // SUPER 668 return CharOperation.concat(TypeConstants.WILDCARD_NAME, TypeConstants.WILDCARD_SUPER, this.bound.readableName()); 669 } 670 } 671 nullAnnotatedReadableName(CompilerOptions options, boolean shortNames)672 public char[] nullAnnotatedReadableName(CompilerOptions options, boolean shortNames) { 673 StringBuffer buffer = new StringBuffer(10); 674 appendNullAnnotation(buffer, options); 675 switch (this.boundKind) { 676 case Wildcard.UNBOUND : 677 buffer.append(TypeConstants.WILDCARD_NAME); 678 break; 679 case Wildcard.EXTENDS : 680 if (this.otherBounds == null) { 681 buffer.append(TypeConstants.WILDCARD_NAME).append(TypeConstants.WILDCARD_EXTENDS); 682 buffer.append(this.bound.nullAnnotatedReadableName(options, shortNames)); 683 } else { 684 buffer.append(this.bound.nullAnnotatedReadableName(options, shortNames)); 685 for (int i = 0, length = this.otherBounds.length; i < length; i++) { 686 buffer.append('&').append(this.otherBounds[i].nullAnnotatedReadableName(options, shortNames)); 687 } 688 } 689 break; 690 default: // SUPER 691 buffer.append(TypeConstants.WILDCARD_NAME).append(TypeConstants.WILDCARD_SUPER).append(this.bound.nullAnnotatedReadableName(options, shortNames)); 692 } 693 int length; 694 char[] result = new char[length = buffer.length()]; 695 buffer.getChars(0, length, result, 0); 696 return result; 697 } 698 resolve()699 ReferenceBinding resolve() { 700 if ((this.tagBits & TagBits.HasUnresolvedTypeVariables) == 0) 701 return this; 702 703 this.tagBits &= ~TagBits.HasUnresolvedTypeVariables; 704 BinaryTypeBinding.resolveType(this.genericType, this.environment, false /* no raw conversion */); 705 switch(this.boundKind) { 706 case Wildcard.EXTENDS : 707 TypeBinding resolveType = BinaryTypeBinding.resolveType(this.bound, this.environment, true /* raw conversion */); 708 this.bound = resolveType; 709 this.tagBits |= resolveType.tagBits & TagBits.ContainsNestedTypeReferences | TagBits.HasCapturedWildcard; 710 for (int i = 0, length = this.otherBounds == null ? 0 : this.otherBounds.length; i < length; i++) { 711 resolveType = BinaryTypeBinding.resolveType(this.otherBounds[i], this.environment, true /* raw conversion */); 712 this.otherBounds[i]= resolveType; 713 this.tagBits |= resolveType.tagBits & TagBits.ContainsNestedTypeReferences | TagBits.HasCapturedWildcard; 714 } 715 break; 716 case Wildcard.SUPER : 717 resolveType = BinaryTypeBinding.resolveType(this.bound, this.environment, true /* raw conversion */); 718 this.bound = resolveType; 719 this.tagBits |= resolveType.tagBits & TagBits.ContainsNestedTypeReferences | TagBits.HasCapturedWildcard; 720 break; 721 case Wildcard.UNBOUND : 722 } 723 return this; 724 } 725 726 /* (non-Javadoc) 727 * @see org.eclipse.jdt.internal.compiler.lookup.Binding#shortReadableName() 728 */ shortReadableName()729 public char[] shortReadableName() { 730 switch (this.boundKind) { 731 case Wildcard.UNBOUND : 732 return TypeConstants.WILDCARD_NAME; 733 case Wildcard.EXTENDS : 734 if (this.otherBounds == null) 735 return CharOperation.concat(TypeConstants.WILDCARD_NAME, TypeConstants.WILDCARD_EXTENDS, this.bound.shortReadableName()); 736 StringBuffer buffer = new StringBuffer(10); 737 buffer.append(this.bound.shortReadableName()); 738 for (int i = 0, length = this.otherBounds.length; i < length; i++) { 739 buffer.append('&').append(this.otherBounds[i].shortReadableName()); 740 } 741 int length; 742 char[] result = new char[length = buffer.length()]; 743 buffer.getChars(0, length, result, 0); 744 return result; 745 default: // SUPER 746 return CharOperation.concat(TypeConstants.WILDCARD_NAME, TypeConstants.WILDCARD_SUPER, this.bound.shortReadableName()); 747 } 748 } 749 750 /** 751 * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#signature() 752 */ signature()753 public char[] signature() { 754 // should not be called directly on a wildcard; signature should only be asked on 755 // original methods or type erasures (which cannot denote wildcards at first level) 756 if (this.signature == null) { 757 switch (this.boundKind) { 758 case Wildcard.EXTENDS : 759 return this.bound.signature(); 760 default: // SUPER | UNBOUND 761 return typeVariable().signature(); 762 } 763 } 764 return this.signature; 765 } 766 767 /* (non-Javadoc) 768 * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#sourceName() 769 */ sourceName()770 public char[] sourceName() { 771 switch (this.boundKind) { 772 case Wildcard.UNBOUND : 773 return TypeConstants.WILDCARD_NAME; 774 case Wildcard.EXTENDS : 775 return CharOperation.concat(TypeConstants.WILDCARD_NAME, TypeConstants.WILDCARD_EXTENDS, this.bound.sourceName()); 776 default: // SUPER 777 return CharOperation.concat(TypeConstants.WILDCARD_NAME, TypeConstants.WILDCARD_SUPER, this.bound.sourceName()); 778 } 779 } 780 781 /* (non-Javadoc) 782 * @see org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding#superclass() 783 */ superclass()784 public ReferenceBinding superclass() { 785 if (this.superclass == null) { 786 TypeBinding superType = null; 787 if (this.boundKind == Wildcard.EXTENDS && !this.bound.isInterface()) { 788 superType = this.bound; 789 } else { 790 TypeVariableBinding variable = typeVariable(); 791 if (variable != null) superType = variable.firstBound; 792 } 793 this.superclass = superType instanceof ReferenceBinding && !superType.isInterface() 794 ? (ReferenceBinding) superType 795 : this.environment.getResolvedType(TypeConstants.JAVA_LANG_OBJECT, null); 796 } 797 798 return this.superclass; 799 } 800 801 /* (non-Javadoc) 802 * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#superInterfaces() 803 */ superInterfaces()804 public ReferenceBinding[] superInterfaces() { 805 if (this.superInterfaces == null) { 806 if (typeVariable() != null) { 807 this.superInterfaces = this.typeVariable.superInterfaces(); 808 } else { 809 this.superInterfaces = Binding.NO_SUPERINTERFACES; 810 } 811 if (this.boundKind == Wildcard.EXTENDS) { 812 if (this.bound.isInterface()) { 813 // augment super interfaces with the wildcard bound 814 int length = this.superInterfaces.length; 815 System.arraycopy(this.superInterfaces, 0, this.superInterfaces = new ReferenceBinding[length+1], 1, length); 816 this.superInterfaces[0] = (ReferenceBinding) this.bound; // make bound first 817 } 818 if (this.otherBounds != null) { 819 // augment super interfaces with the wildcard otherBounds (interfaces per construction) 820 int length = this.superInterfaces.length; 821 int otherLength = this.otherBounds.length; 822 System.arraycopy(this.superInterfaces, 0, this.superInterfaces = new ReferenceBinding[length+otherLength], 0, length); 823 for (int i = 0; i < otherLength; i++) { 824 this.superInterfaces[length+i] = (ReferenceBinding) this.otherBounds[i]; 825 } 826 } 827 } 828 } 829 return this.superInterfaces; 830 } 831 swapUnresolved(UnresolvedReferenceBinding unresolvedType, ReferenceBinding resolvedType, LookupEnvironment env)832 public void swapUnresolved(UnresolvedReferenceBinding unresolvedType, ReferenceBinding resolvedType, LookupEnvironment env) { 833 boolean affected = false; 834 if (this.genericType == unresolvedType) { //$IDENTITY-COMPARISON$ 835 this.genericType = resolvedType; // no raw conversion 836 affected = true; 837 } 838 if (this.bound == unresolvedType) { //$IDENTITY-COMPARISON$ 839 this.bound = env.convertUnresolvedBinaryToRawType(resolvedType); 840 affected = true; 841 } 842 if (this.otherBounds != null) { 843 for (int i = 0, length = this.otherBounds.length; i < length; i++) { 844 if (this.otherBounds[i] == unresolvedType) { //$IDENTITY-COMPARISON$ 845 this.otherBounds[i] = env.convertUnresolvedBinaryToRawType(resolvedType); 846 affected = true; 847 } 848 } 849 } 850 if (affected) 851 initialize(this.genericType, this.bound, this.otherBounds); 852 } 853 854 /** 855 * @see java.lang.Object#toString() 856 */ toString()857 public String toString() { 858 if (this.hasTypeAnnotations()) 859 return annotatedDebugName(); 860 switch (this.boundKind) { 861 case Wildcard.UNBOUND : 862 return new String(TypeConstants.WILDCARD_NAME); 863 case Wildcard.EXTENDS : 864 if (this.otherBounds == null) 865 return new String(CharOperation.concat(TypeConstants.WILDCARD_NAME, TypeConstants.WILDCARD_EXTENDS, this.bound.debugName().toCharArray())); 866 StringBuffer buffer = new StringBuffer(this.bound.debugName()); 867 for (int i = 0, length = this.otherBounds.length; i < length; i++) { 868 buffer.append('&').append(this.otherBounds[i].debugName()); 869 } 870 return buffer.toString(); 871 default: // SUPER 872 return new String(CharOperation.concat(TypeConstants.WILDCARD_NAME, TypeConstants.WILDCARD_SUPER, this.bound.debugName().toCharArray())); 873 } 874 } 875 /** 876 * Returns associated type variable, or null in case of inconsistency 877 */ typeVariable()878 public TypeVariableBinding typeVariable() { 879 if (this.typeVariable == null) { 880 TypeVariableBinding[] typeVariables = this.genericType.typeVariables(); 881 if (this.rank < typeVariables.length) 882 this.typeVariable = typeVariables[this.rank]; 883 } 884 return this.typeVariable; 885 } 886 unannotated(boolean removeOnlyNullAnnotations)887 public TypeBinding unannotated(boolean removeOnlyNullAnnotations) { 888 if (!hasTypeAnnotations()) 889 return this; 890 if (removeOnlyNullAnnotations && !hasNullTypeAnnotations()) 891 return this; 892 ReferenceBinding unannotatedGenericType = (ReferenceBinding) this.genericType.unannotated(removeOnlyNullAnnotations); 893 if (removeOnlyNullAnnotations) { 894 // cf. structure of uncapture(): 895 TypeBinding unannotatedBound = this.bound != null ? this.bound.unannotated(removeOnlyNullAnnotations) : null; 896 int length = 0; 897 TypeBinding [] unannotatedOtherBounds = this.otherBounds == null ? null : new TypeBinding[length = this.otherBounds.length]; 898 for (int i = 0; i < length; i++) { 899 unannotatedOtherBounds[i] = this.otherBounds[i] == null ? null : this.otherBounds[i].unannotated(removeOnlyNullAnnotations); 900 } 901 AnnotationBinding[] newAnnotations = this.environment.filterNullTypeAnnotations(getTypeAnnotations()); 902 return this.environment.createWildcard(unannotatedGenericType, this.rank, unannotatedBound, unannotatedOtherBounds, this.boundKind, newAnnotations); 903 } 904 return unannotatedGenericType; 905 } 906 @Override uncapture(Scope scope)907 public TypeBinding uncapture(Scope scope) { 908 if ((this.tagBits & TagBits.HasCapturedWildcard) == 0) 909 return this; 910 TypeBinding freeBound = this.bound != null ? this.bound.uncapture(scope) : null; 911 int length = 0; 912 TypeBinding [] freeOtherBounds = this.otherBounds == null ? null : new TypeBinding[length = this.otherBounds.length]; 913 for (int i = 0; i < length; i++) { 914 freeOtherBounds[i] = this.otherBounds[i] == null ? null : this.otherBounds[i].uncapture(scope); 915 } 916 return scope.environment().createWildcard(this.genericType, this.rank, freeBound, freeOtherBounds, this.boundKind, getTypeAnnotations()); 917 } 918 @Override collectInferenceVariables(Set<InferenceVariable> variables)919 void collectInferenceVariables(Set<InferenceVariable> variables) { 920 if (this.bound != null) 921 this.bound.collectInferenceVariables(variables); 922 if (this.otherBounds != null) 923 for (int i = 0, length = this.otherBounds.length; i < length; i++) 924 this.otherBounds[i].collectInferenceVariables(variables); 925 } 926 @Override mentionsAny(TypeBinding[] parameters, int idx)927 public boolean mentionsAny(TypeBinding[] parameters, int idx) { 928 if (this.inRecursiveFunction) 929 return false; 930 this.inRecursiveFunction = true; 931 try { 932 if (super.mentionsAny(parameters, idx)) 933 return true; 934 if (this.bound != null && this.bound.mentionsAny(parameters, -1)) 935 return true; 936 if (this.otherBounds != null) { 937 for (int i = 0, length = this.otherBounds.length; i < length; i++) 938 if (this.otherBounds[i].mentionsAny(parameters, -1)) 939 return true; 940 } 941 } finally { 942 this.inRecursiveFunction = false; 943 } 944 return false; 945 } 946 } 947