docs: @Override
      public boolean equalsIgnoringTypeParams(final TypeSignature other) {
          if (other instanceof ClassRefTypeSignature) {
              if (((ClassRefTypeSignature) other).className.equals("java.lang.Object")) {
                  // java.lang.Object can be reconciled with any type, so it can be reconciled with
                  // any type variable
                  return true;
              }
              // Resolve the type variable against the containing class' type parameters
              TypeParameter typeParameter;
              try {
                  typeParameter = resolve();
              } catch (final IllegalArgumentException e) {
                  // If the corresponding type parameter cannot be resolved:
                  // unknown type variables can always be reconciled with a concrete class
                  return true;
              }
              if (typeParameter.classBound == null
                      && (typeParameter.interfaceBounds == null || typeParameter.interfaceBounds.isEmpty())) {
                  // If the type parameter has no bounds, just assume the type variable can be reconciled
                  // to the class by type inference
                  return true;
              }
              if (typeParameter.classBound != null) {
                  if (typeParameter.classBound instanceof ClassRefTypeSignature) {
                      if (typeParameter.classBound.equals(other)) {
                          // T extends X, and X == other
                          return true;
                      }
                  } else if (typeParameter.classBound instanceof TypeVariableSignature) {
                      // "X" is reconcilable with "Y extends X"
                      return this.equalsIgnoringTypeParams(typeParameter.classBound);
                  } else /* if (typeParameter.classBound instanceof ArrayTypeSignature) */ {
                      return false;
                  }
              }
              if (typeParameter.interfaceBounds != null) {
                  for (final ReferenceTypeSignature interfaceBound : typeParameter.interfaceBounds) {
                      if (interfaceBound instanceof ClassRefTypeSignature) {
                          if (interfaceBound.equals(other)) {
                              // T implements X, and X == other
                              return true;
                          }
                      } else if (interfaceBound instanceof TypeVariableSignature) {
                          // "X" is reconcilable with "Y implements X"
                          return this.equalsIgnoringTypeParams(interfaceBound);
                      } else /* if (interfaceBound instanceof ArrayTypeSignature) */ {
                          return false;
                      }
                  }
              }
              // Type variable has a concrete bound that is not reconcilable with 'other'
              // (we don't follow the class hierarchy to compare the bound against the class reference,
              // since the compiler should only use the bound during type erasure, not some other class
              // in the class hierarchy)
              return false;
          }
          // Technically I think type variables are never equal to each other, due to capturing,
          // but just compare the variable name for equality here (this should never get
          // triggered in general, since we only compare type-erased signatures to
          // non-type-erased signatures currently).
          return this.equals(other);
      }