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