code: private void addReturnTypeNarrowingDeclarations(AbstractTypeDeclaration node) {
      TypeElement type = node.getTypeElement();
  
      // No need to run this if the entire class is dead.
      if (deadCodeMap != null && deadCodeMap.containsClass(type, elementUtil)) {
        return;
      }
  
      Map<String, ExecutablePair> newDeclarations = new HashMap<>();
      Map<String, TypeMirror> resolvedReturnTypes = new HashMap<>();
      for (DeclaredType inheritedType : typeUtil.getObjcOrderedInheritedTypes(type.asType())) {
        TypeElement inheritedElem = (TypeElement) inheritedType.asElement();
        for (ExecutableElement methodElem : ElementUtil.getMethods(inheritedElem)) {
          if (ElementUtil.isPrivate(methodElem)) {
            continue;
          }
          TypeMirror declaredReturnType = typeUtil.erasure(methodElem.getReturnType());
          if (!TypeUtil.isReferenceType(declaredReturnType)) {
            continue;  // Short circuit
          }
          String selector = nameTable.getMethodSelector(methodElem);
          ExecutableType methodType = typeUtil.asMemberOf(inheritedType, methodElem);
          TypeMirror returnType = typeUtil.erasure(methodType.getReturnType());
          TypeMirror resolvedReturnType = resolvedReturnTypes.get(selector);
          if (resolvedReturnType == null) {
            resolvedReturnType = declaredReturnType;
            resolvedReturnTypes.put(selector, resolvedReturnType);
          } else if (!typeUtil.isSubtype(returnType, resolvedReturnType)) {
            continue;
          }
          if (resolvedReturnType != returnType
              && !nameTable.getObjCType(resolvedReturnType).equals(
                  nameTable.getObjCType(returnType))) {
            newDeclarations.put(selector, new ExecutablePair(methodElem, methodType));
            resolvedReturnTypes.put(selector, returnType);
          }
        }
      }
  
      for (Map.Entry<String, ExecutablePair> newDecl : newDeclarations.entrySet()) {
        if (deadCodeMap != null
            && deadCodeMap.containsMethod(newDecl.getValue().element(), typeUtil)) {
          continue;
        }
        node.addBodyDeclaration(newReturnTypeNarrowingDeclaration(
            newDecl.getKey(), newDecl.getValue(), type));
      }
    }
docs: specific than what is already declared in inherited types.