@@ -206,37 +206,56 @@ public Boolean visitDeclared_Declared(
206206 if (!arePrimeAnnosEqual (type1 , type2 )) {
207207 return false ;
208208 }
209-
210209 // Prevent infinite recursion e.g. in Issue1587b
211210 visitHistory .put (type1 , type2 , currentTop , true );
212211
213- boolean result = visitTypeArgs (type1 , type2 );
214- visitHistory .put (type1 , type2 , currentTop , result );
215- return result ;
216- }
217-
218- /**
219- * A helper class for visitDeclared_Declared. There are subtypes of DefaultTypeHierarchy that need
220- * to customize the handling of type arguments. This method provides a convenient extension point.
221- */
222- protected boolean visitTypeArgs (AnnotatedDeclaredType type1 , AnnotatedDeclaredType type2 ) {
223-
224- // TODO: ANYTHING WITH RAW TYPES? SHOULD WE HANDLE THEM LIKE DefaultTypeHierarchy, i.e. use
225- // ignoreRawTypes
226- List <? extends AnnotatedTypeMirror > type1Args = type1 .getTypeArguments ();
227- List <? extends AnnotatedTypeMirror > type2Args = type2 .getTypeArguments ();
228-
229- if (type1Args .isEmpty () && type2Args .isEmpty ()) {
230- return true ;
212+ List <AnnotatedTypeMirror > type1Args = type1 .getTypeArguments ();
213+ List <AnnotatedTypeMirror > type2Args = type2 .getTypeArguments ();
214+
215+ // Capture the types because the wildcards are only not equal if they are provably distinct.
216+ // Provably distinct is computed using the captured and erased upper bounds of wildcards.
217+ // See JLS 4.5.1. Type Arguments of Parameterized Types.
218+ AnnotatedTypeFactory atypeFactory = type1 .atypeFactory ;
219+ AnnotatedDeclaredType capturedType1 =
220+ (AnnotatedDeclaredType ) atypeFactory .applyCaptureConversion (type1 );
221+ AnnotatedDeclaredType capturedType2 =
222+ (AnnotatedDeclaredType ) atypeFactory .applyCaptureConversion (type2 );
223+ visitHistory .put (capturedType1 , capturedType2 , currentTop , true );
224+
225+ List <AnnotatedTypeMirror > capturedType1Args = capturedType1 .getTypeArguments ();
226+ List <AnnotatedTypeMirror > capturedType2Args = capturedType2 .getTypeArguments ();
227+ boolean result = true ;
228+ for (int i = 0 ; i < type1 .getTypeArguments ().size (); i ++) {
229+ AnnotatedTypeMirror type1Arg = type1Args .get (i );
230+ AnnotatedTypeMirror type2Arg = type2Args .get (i );
231+ Boolean pastResultTA = visitHistory .get (type1Arg , type2Arg , currentTop );
232+ if (pastResultTA != null ) {
233+ result = pastResultTA ;
234+ } else {
235+ if (type1Arg .getKind () != TypeKind .WILDCARD || type2Arg .getKind () != TypeKind .WILDCARD ) {
236+ result = areEqual (type1Arg , type2Arg );
237+ } else {
238+ AnnotatedWildcardType wildcardType1 = (AnnotatedWildcardType ) type1Arg ;
239+ AnnotatedWildcardType wildcardType2 = (AnnotatedWildcardType ) type2Arg ;
240+ if (type1 .atypeFactory .ignoreUninferredTypeArguments
241+ && (wildcardType1 .isUninferredTypeArgument ()
242+ || wildcardType2 .isUninferredTypeArgument ())) {
243+ result = true ;
244+ } else {
245+ AnnotatedTypeMirror capturedType1Arg = capturedType1Args .get (i );
246+ AnnotatedTypeMirror capturedType2Arg = capturedType2Args .get (i );
247+ result = areEqual (capturedType1Arg .getErased (), capturedType2Arg .getErased ());
248+ }
249+ }
250+ }
251+ if (!result ) {
252+ break ;
253+ }
231254 }
232255
233- if (type1Args .size () == type2Args .size ()) {
234- return areAllEqual (type1Args , type2Args );
235- } else {
236- throw new BugInCF (
237- "Mismatching type argument sizes:%n type 1: %s (%d)%n type 2: %s (%d)" ,
238- type1 , type1Args .size (), type2 , type2Args .size ());
239- }
256+ visitHistory .put (capturedType1 , capturedType2 , currentTop , result );
257+ visitHistory .put (type1 , type2 , currentTop , result );
258+ return result ;
240259 }
241260
242261 /**
0 commit comments