}
	private boolean compareTypes(Type parmType, Type argType) {		// XXX equality not implemented for GenericObjectType		// if (parmType.equals(argType)) return true;		// Compare type signatures instead		String parmString = GenericUtilities.getString(parmType);		String argString = GenericUtilities.getString(argType);		if (parmString.equals(argString)) return true;				// if either type is java.lang.Object, then automatically true!		// again compare strings...		String objString = GenericUtilities.getString(Type.OBJECT);		if ( parmString.equals(objString) || 			 argString.equals(objString) ) {			return true;		}				// get a category for each type		TypeCategory parmCat = GenericUtilities.getTypeCategory(parmType);		TypeCategory argCat  = GenericUtilities.getTypeCategory(argType);				// -~- plain objects are easy		if ( parmCat == TypeCategory.PLAIN_OBJECT_TYPE && 			 argCat == TypeCategory.PLAIN_OBJECT_TYPE ) {			try {						String parmName = ((ObjectType)parmType).getClassName();				String argName  = ((ObjectType)argType) .getClassName();								// e.g. List<String>.contains(CharSequence)				if (Repository.instanceOf(parmName, argName)) return true;								// e.g. List<CharSequence>.contains(String)				return Repository.instanceOf(argName, parmName);							} catch (ClassNotFoundException e) { return true; }					}				// -~- parmType is: "? extends Another Type" OR "? super Another Type"		if ( parmCat == TypeCategory.WILDCARD_EXTENDS || 			 parmCat == TypeCategory.WILDCARD_SUPER ) {			return compareTypes( 					((GenericObjectType)parmType).getExtension(), argType);		}				// -~- Not handling type variables		if ( parmCat == TypeCategory.TYPE_VARIABLE || 			 argCat == TypeCategory.TYPE_VARIABLE ) {			return true;		}				// -~- Array Types: compare dimensions, then base type		if ( parmCat == TypeCategory.ARRAY_TYPE && 			 argCat  == TypeCategory.ARRAY_TYPE ) {			ArrayType parmArray = (ArrayType) parmType;			ArrayType argArray  = (ArrayType) argType;						if (parmArray.getDimensions() != argArray.getDimensions())				return false;						return compareTypes(parmArray.getBasicType(), argArray.getBasicType());		}		//     If one is an Array Type and the other is not, then they		//     are incompatible. (We already know neither is java.lang.Object)		if ( parmCat == TypeCategory.ARRAY_TYPE ^ 			 argCat  == TypeCategory.ARRAY_TYPE ) {			return false;		}				// -~- Parameter Types: compare base type then parameters		if ( parmCat == TypeCategory.PARAMETERS && 			 argCat  == TypeCategory.PARAMETERS ) {			GenericObjectType parmGeneric = (GenericObjectType) parmType;			GenericObjectType argGeneric  = (GenericObjectType) argType;						// base types should be related			if (!compareTypes( parmGeneric.getObjectType(), 					argGeneric.getObjectType()) )				return false;						// XXX More to come		}		//     If one is a Parameter Type and the other is not, then they		//     are incompatible. (We already know neither is java.lang.Object)		if (false) {			// not true. Consider class Foo extends ArrayList<String>			if ( parmCat == TypeCategory.PARAMETERS ^ 				 argCat  == TypeCategory.PARAMETERS ) {				return false;			}		}				// -~- Wildcard e.g. List<*>.contains(...)				if (parmCat == TypeCategory.WILDCARD) // No Way to know 			return true;				// -~- Non Reference types		// if ( parmCat == TypeCategory.NON_REFERENCE_TYPE || 		// 	    argCat == TypeCategory.NON_REFERENCE_TYPE )		if (parmType instanceof BasicType || argType instanceof BasicType) {			// this should not be possible, compiler will complain (pre 1.5) 			// or autobox primitive types (1.5 +)			assert false;		}				return true;	}