Index: lib/StaticAnalyzer/Checkers/CMakeLists.txt
===================================================================
--- lib/StaticAnalyzer/Checkers/CMakeLists.txt
+++ lib/StaticAnalyzer/Checkers/CMakeLists.txt
@@ -53,7 +53,6 @@
   ObjCAtSyncChecker.cpp
   ObjCContainersASTChecker.cpp
   ObjCContainersChecker.cpp
-  ObjCGenericsChecker.cpp
   ObjCMissingSuperCallChecker.cpp
   ObjCSelfInitChecker.cpp
   ObjCUnusedIVarsChecker.cpp
Index: lib/StaticAnalyzer/Checkers/Checkers.td
===================================================================
--- lib/StaticAnalyzer/Checkers/Checkers.td
+++ lib/StaticAnalyzer/Checkers/Checkers.td
@@ -478,8 +478,8 @@
   DescFile<"DirectIvarAssignment.cpp">;
 
 def ObjCGenericsChecker : Checker<"ObjCGenerics">,
-  HelpText<"Check for incorrect usages of parameterized types.">,
-  DescFile<"ObjCGenericsChecker.cpp">;
+  HelpText<"Check for type errors when using Objective-C generics.">,
+  DescFile<"DynamicTypePropagation.cpp">;
 
 def NonLocalizedStringChecker : Checker<"NonLocalizedStringChecker">,
   HelpText<"Warns about uses of non-localized NSStrings passed to UI methods expecting localized NSStrings">,
Index: lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp
===================================================================
--- lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp
+++ lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp
@@ -7,11 +7,23 @@
 //
 //===----------------------------------------------------------------------===//
 //
+// This file contains two checkers. One helps the static analyzer core to track
+// types, the other does type inference on Obj-C generics and report type
+// errors.
+//
+// Dynamic Type Propagation:
 // This checker defines the rules for dynamic type gathering and propagation.
 //
+// Generics Checker for Objective-C:
+// This checker tries to find type errors that the compiler is not able to catch
+// due to the implicit conversions that were introduced for backward
+// compatibility.
+//
 //===----------------------------------------------------------------------===//
 
 #include "ClangSACheckers.h"
+#include "clang/AST/ParentMap.h"
+#include "clang/AST/RecursiveASTVisitor.h"
 #include "clang/Basic/Builtins.h"
 #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
 #include "clang/StaticAnalyzer/Core/Checker.h"
@@ -23,26 +35,84 @@
 using namespace clang;
 using namespace ento;
 
+// ProgramState trait - a map from symbol to its specialized type to trak type
+// information that is related to generics.
+REGISTER_MAP_WITH_PROGRAMSTATE(TypeParamMap, SymbolRef,
+                               const ObjCObjectPointerType *)
+
 namespace {
-class DynamicTypePropagation:
-    public Checker< check::PreCall,
-                    check::PostCall,
-                    check::PostStmt<ImplicitCastExpr>,
-                    check::PostStmt<CXXNewExpr> > {
-  const ObjCObjectType *getObjectTypeForAllocAndNew(const ObjCMessageExpr *MsgE,
-                                                    CheckerContext &C) const;
-
-  /// \brief Return a better dynamic type if one can be derived from the cast.
-  const ObjCObjectPointerType *getBetterObjCType(const Expr *CastE,
-                                                 CheckerContext &C) const;
+class DynamicTypePropagation
+    : public Checker<check::PreCall, check::PostCall, check::PreObjCMessage,
+                     check::PostObjCMessage, check::DeadSymbols,
+                     check::PostStmt<CastExpr>, check::PostStmt<CXXNewExpr>> {
+  mutable std::unique_ptr<BugType> ObjCGenericsBugType;
+
+  void initBugType() const {
+    if (!ObjCGenericsBugType)
+      ObjCGenericsBugType.reset(
+          new BugType(this, "Generics", categories::CoreFoundationObjectiveC));
+  }
+
+  class GenericsBugVisitor : public BugReporterVisitorImpl<GenericsBugVisitor> {
+  public:
+    GenericsBugVisitor(SymbolRef S) : Sym(S) {}
+
+    void Profile(llvm::FoldingSetNodeID &ID) const override {
+      static int X = 0;
+      ID.AddPointer(&X);
+      ID.AddPointer(Sym);
+    }
+
+    PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
+                                   const ExplodedNode *PrevN,
+                                   BugReporterContext &BRC,
+                                   BugReport &BR) override;
+
+  private:
+    // The tracked symbol.
+    SymbolRef Sym;
+  };
+
+  void reportGenericsBug(const ObjCObjectPointerType *From,
+                         const ObjCObjectPointerType *To, ExplodedNode *N,
+                         SymbolRef Sym, CheckerContext &C,
+                         const Stmt *ReportedNode = nullptr) const;
+
 public:
   void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
   void checkPostCall(const CallEvent &Call, CheckerContext &C) const;
-  void checkPostStmt(const ImplicitCastExpr *CastE, CheckerContext &C) const;
   void checkPostStmt(const CXXNewExpr *NewE, CheckerContext &C) const;
+  void checkPreObjCMessage(const ObjCMethodCall &M, CheckerContext &C) const;
+  void checkPostObjCMessage(const ObjCMethodCall &M, CheckerContext &C) const;
+  void checkPostStmt(const CastExpr *CE, CheckerContext &C) const;
+  void checkDeadSymbols(SymbolReaper &SR, CheckerContext &C) const;
+
+  /// This value is set to true, when the Generics checker is turned on.
+  DefaultBool CheckGenerics;
 };
 }
 
+void DynamicTypePropagation::reportGenericsBug(
+    const ObjCObjectPointerType *From, const ObjCObjectPointerType *To,
+    ExplodedNode *N, SymbolRef Sym, CheckerContext &C,
+    const Stmt *ReportedNode) const {
+  initBugType();
+  SmallString<64> Buf;
+  llvm::raw_svector_ostream OS(Buf);
+  OS << "Conversion from value of type '";
+  QualType::print(From, Qualifiers(), OS, C.getLangOpts(), llvm::Twine());
+  OS << "' to incompatible type '";
+  QualType::print(To, Qualifiers(), OS, C.getLangOpts(), llvm::Twine());
+  OS << "'";
+  std::unique_ptr<BugReport> R(
+      new BugReport(*ObjCGenericsBugType, OS.str(), N));
+  R->markInteresting(Sym);
+  R->addVisitor(llvm::make_unique<GenericsBugVisitor>(Sym));
+  if (ReportedNode)
+    R->addRange(ReportedNode->getSourceRange());
+  C.emitReport(std::move(R));
+}
+
 static void recordFixedType(const MemRegion *Region, const CXXMethodDecl *MD,
                             CheckerContext &C) {
   assert(Region);
@@ -57,6 +127,97 @@
   return;
 }
 
+static const ObjCObjectType *
+getObjectTypeForAllocAndNew(const ObjCMessageExpr *MsgE, CheckerContext &C) {
+  if (MsgE->getReceiverKind() == ObjCMessageExpr::Class) {
+    if (const ObjCObjectType *ObjTy =
+            MsgE->getClassReceiver()->getAs<ObjCObjectType>())
+      return ObjTy;
+  }
+
+  if (MsgE->getReceiverKind() == ObjCMessageExpr::SuperClass) {
+    if (const ObjCObjectType *ObjTy =
+            MsgE->getSuperType()->getAs<ObjCObjectType>())
+      return ObjTy;
+  }
+
+  const Expr *RecE = MsgE->getInstanceReceiver();
+  if (!RecE)
+    return nullptr;
+
+  RecE = RecE->IgnoreParenImpCasts();
+  if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(RecE)) {
+    const StackFrameContext *SFCtx = C.getStackFrame();
+    // Are we calling [self alloc]? If this is self, get the type of the
+    // enclosing ObjC class.
+    if (DRE->getDecl() == SFCtx->getSelfDecl()) {
+      if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(SFCtx->getDecl()))
+        if (const ObjCObjectType *ObjTy = dyn_cast<ObjCObjectType>(
+                MD->getClassInterface()->getTypeForDecl()))
+          return ObjTy;
+    }
+  }
+  return nullptr;
+}
+
+/// \brief Return a better dynamic type if one can be derived from the cast.
+///
+/// Return a better dynamic type if one can be derived from the cast.
+/// Compare the current dynamic type of the region and the new type to which we
+/// are casting. If the new type is lower in the inheritance hierarchy, pick it.
+static const ObjCObjectPointerType *getBetterObjCType(const Expr *CastE,
+                                                      CheckerContext &C) {
+  const MemRegion *ToR = C.getSVal(CastE).getAsRegion();
+  assert(ToR);
+
+  // Get the old and new types.
+  const ObjCObjectPointerType *NewTy =
+      CastE->getType()->getAs<ObjCObjectPointerType>();
+  if (!NewTy)
+    return nullptr;
+  QualType OldDTy = C.getState()->getDynamicTypeInfo(ToR).getType();
+  if (OldDTy.isNull()) {
+    return NewTy;
+  }
+  const ObjCObjectPointerType *OldTy = OldDTy->getAs<ObjCObjectPointerType>();
+  if (!OldTy)
+    return nullptr;
+
+  // Id the old type is 'id', the new one is more precise.
+  if (OldTy->isObjCIdType() && !NewTy->isObjCIdType())
+    return NewTy;
+
+  // Return new if it's a subclass of old.
+  const ObjCInterfaceDecl *ToI = NewTy->getInterfaceDecl();
+  const ObjCInterfaceDecl *FromI = OldTy->getInterfaceDecl();
+  if (ToI && FromI && FromI->isSuperClassOf(ToI))
+    return NewTy;
+
+  return nullptr;
+}
+
+/// TODO: Handle explicit casts.
+///       Handle C++ casts.
+///
+/// Precondition: the cast is between ObjCObjectPointers.
+static ExplodedNode *dynamicTypePropagationOnCasts(const CastExpr *CE,
+                                                   ProgramStateRef &State,
+                                                   CheckerContext &C) {
+  // We only track type info for regions.
+  const MemRegion *ToR = C.getSVal(CE).getAsRegion();
+  if (!ToR)
+    return C.getPredecessor();
+
+  if (isa<ExplicitCastExpr>(CE))
+    return C.getPredecessor();
+
+  if (const Type *NewTy = getBetterObjCType(CE, C)) {
+    State = State->setDynamicTypeInfo(ToR, QualType(NewTy, 0));
+    return C.addTransition(State);
+  }
+  return C.getPredecessor();
+}
+
 void DynamicTypePropagation::checkPreCall(const CallEvent &Call,
                                           CheckerContext &C) const {
   if (const CXXConstructorCall *Ctor = dyn_cast<CXXConstructorCall>(&Call)) {
@@ -113,7 +274,7 @@
 
     ProgramStateRef State = C.getState();
     const ObjCMethodDecl *D = Msg->getDecl();
-    
+
     if (D && D->hasRelatedResultType()) {
       switch (Msg->getMethodFamily()) {
       default:
@@ -130,7 +291,7 @@
         if (!ObjTy)
           return;
         QualType DynResTy =
-                 C.getASTContext().getObjCObjectPointerType(QualType(ObjTy, 0));
+            C.getASTContext().getObjCObjectPointerType(QualType(ObjTy, 0));
         C.addTransition(State->setDynamicTypeInfo(RetReg, DynResTy, false));
         break;
       }
@@ -173,25 +334,6 @@
   }
 }
 
-void DynamicTypePropagation::checkPostStmt(const ImplicitCastExpr *CastE,
-                                           CheckerContext &C) const {
-  // We only track dynamic type info for regions.
-  const MemRegion *ToR = C.getSVal(CastE).getAsRegion();
-  if (!ToR)
-    return;
-
-  switch (CastE->getCastKind()) {
-  default:
-    break;
-  case CK_BitCast:
-    // Only handle ObjCObjects for now.
-    if (const Type *NewTy = getBetterObjCType(CastE, C))
-      C.addTransition(C.getState()->setDynamicTypeInfo(ToR, QualType(NewTy,0)));
-    break;
-  }
-  return;
-}
-
 void DynamicTypePropagation::checkPostStmt(const CXXNewExpr *NewE,
                                            CheckerContext &C) const {
   if (NewE->isArray())
@@ -201,79 +343,543 @@
   const MemRegion *MR = C.getSVal(NewE).getAsRegion();
   if (!MR)
     return;
-  
+
   C.addTransition(C.getState()->setDynamicTypeInfo(MR, NewE->getType(),
                                                    /*CanBeSubclass=*/false));
 }
 
-const ObjCObjectType *
-DynamicTypePropagation::getObjectTypeForAllocAndNew(const ObjCMessageExpr *MsgE,
-                                                    CheckerContext &C) const {
-  if (MsgE->getReceiverKind() == ObjCMessageExpr::Class) {
-    if (const ObjCObjectType *ObjTy
-          = MsgE->getClassReceiver()->getAs<ObjCObjectType>())
-    return ObjTy;
-  }
+PathDiagnosticPiece *DynamicTypePropagation::GenericsBugVisitor::VisitNode(
+    const ExplodedNode *N, const ExplodedNode *PrevN, BugReporterContext &BRC,
+    BugReport &BR) {
+  ProgramStateRef state = N->getState();
+  ProgramStateRef statePrev = PrevN->getState();
+
+  const ObjCObjectPointerType *const *TrackedType =
+      state->get<TypeParamMap>(Sym);
+  const ObjCObjectPointerType *const *TrackedTypePrev =
+      statePrev->get<TypeParamMap>(Sym);
+  if (!TrackedType)
+    return nullptr;
 
-  if (MsgE->getReceiverKind() == ObjCMessageExpr::SuperClass) {
-    if (const ObjCObjectType *ObjTy
-          = MsgE->getSuperType()->getAs<ObjCObjectType>())
-      return ObjTy;
+  if (TrackedTypePrev && *TrackedTypePrev == *TrackedType)
+    return nullptr;
+
+  // Retrieve the associated statement.
+  const Stmt *S = nullptr;
+  ProgramPoint ProgLoc = N->getLocation();
+  if (Optional<StmtPoint> SP = ProgLoc.getAs<StmtPoint>()) {
+    S = SP->getStmt();
   }
 
-  const Expr *RecE = MsgE->getInstanceReceiver();
-  if (!RecE)
+  if (!S)
     return nullptr;
 
-  RecE= RecE->IgnoreParenImpCasts();
-  if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(RecE)) {
-    const StackFrameContext *SFCtx = C.getStackFrame();
-    // Are we calling [self alloc]? If this is self, get the type of the
-    // enclosing ObjC class.
-    if (DRE->getDecl() == SFCtx->getSelfDecl()) {
-      if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(SFCtx->getDecl()))
-        if (const ObjCObjectType *ObjTy =
-            dyn_cast<ObjCObjectType>(MD->getClassInterface()->getTypeForDecl()))
-          return ObjTy;
+  const LangOptions &LangOpts = BRC.getASTContext().getLangOpts();
+
+  SmallString<64> Buf;
+  llvm::raw_svector_ostream OS(Buf);
+  OS << "Type '";
+  QualType::print(*TrackedType, Qualifiers(), OS, LangOpts, llvm::Twine());
+  OS << "' is inferred from ";
+
+  if (const auto *ExplicitCast = dyn_cast<ExplicitCastExpr>(S)) {
+    OS << "explicit cast (from '";
+    QualType::print(ExplicitCast->getSubExpr()->getType().getTypePtr(),
+                    Qualifiers(), OS, LangOpts, llvm::Twine());
+    OS << "' to '";
+    QualType::print(ExplicitCast->getType().getTypePtr(), Qualifiers(), OS,
+                    LangOpts, llvm::Twine());
+    OS << "')";
+  } else if (const auto *ImplicitCast = dyn_cast<ImplicitCastExpr>(S)) {
+    OS << "implicit cast (from '";
+    QualType::print(ImplicitCast->getSubExpr()->getType().getTypePtr(),
+                    Qualifiers(), OS, LangOpts, llvm::Twine());
+    OS << "' to '";
+    QualType::print(ImplicitCast->getType().getTypePtr(), Qualifiers(), OS,
+                    LangOpts, llvm::Twine());
+    OS << "')";
+  } else {
+    OS << "this context";
+  }
+
+  // Generate the extra diagnostic.
+  PathDiagnosticLocation Pos(S, BRC.getSourceManager(),
+                             N->getLocationContext());
+  return new PathDiagnosticEventPiece(Pos, OS.str(), true, nullptr);
+}
+
+// Clean up the states stored by the generics checker.
+void DynamicTypePropagation::checkDeadSymbols(SymbolReaper &SR,
+                                              CheckerContext &C) const {
+  if (!SR.hasDeadSymbols())
+    return;
+
+  ProgramStateRef State = C.getState();
+  TypeParamMapTy TyParMap = State->get<TypeParamMap>();
+  for (TypeParamMapTy::iterator I = TyParMap.begin(), E = TyParMap.end();
+       I != E; ++I) {
+    if (SR.isDead(I->first)) {
+      State = State->remove<TypeParamMap>(I->first);
     }
   }
-  return nullptr;
 }
 
-// Return a better dynamic type if one can be derived from the cast.
-// Compare the current dynamic type of the region and the new type to which we
-// are casting. If the new type is lower in the inheritance hierarchy, pick it.
-const ObjCObjectPointerType *
-DynamicTypePropagation::getBetterObjCType(const Expr *CastE,
-                                          CheckerContext &C) const {
-  const MemRegion *ToR = C.getSVal(CastE).getAsRegion();
-  assert(ToR);
+static const ObjCObjectPointerType *getMostInformativeDerivedClassImpl(
+    const ObjCObjectPointerType *From, const ObjCObjectPointerType *To,
+    const ObjCObjectPointerType *MostInformativeCandidate, ASTContext &C) {
+  // Checking if from and to are the same classes modulo specialization.
+  if (From->getInterfaceDecl()->getCanonicalDecl() ==
+      To->getInterfaceDecl()->getCanonicalDecl()) {
+    if (To->isSpecialized()) {
+      assert(MostInformativeCandidate->isSpecialized());
+      return MostInformativeCandidate;
+    }
+    return From;
+  }
+  const auto *SuperOfTo =
+      To->getObjectType()->getSuperClassType()->getAs<ObjCObjectType>();
+  assert(SuperOfTo);
+  QualType SuperPtrOfToQual =
+      C.getObjCObjectPointerType(QualType(SuperOfTo, 0));
+  const auto *SuperPtrOfTo = SuperPtrOfToQual->getAs<ObjCObjectPointerType>();
+  if (To->isUnspecialized())
+    return getMostInformativeDerivedClassImpl(From, SuperPtrOfTo, SuperPtrOfTo,
+                                              C);
+  else
+    return getMostInformativeDerivedClassImpl(From, SuperPtrOfTo,
+                                              MostInformativeCandidate, C);
+}
 
-  // Get the old and new types.
-  const ObjCObjectPointerType *NewTy =
-      CastE->getType()->getAs<ObjCObjectPointerType>();
-  if (!NewTy)
-    return nullptr;
-  QualType OldDTy = C.getState()->getDynamicTypeInfo(ToR).getType();
-  if (OldDTy.isNull()) {
-    return NewTy;
+/// A downcast may loose specialization information. E. g.:
+///   MutableMap<T, U> : Map
+/// The downcast to MutableMap looses the information about the types of the
+/// Map (due to the type parameters are not being forwarded to Map), and in
+/// general there is no way to recover that information from the
+/// declaration. In order to have to most information, lets find the most
+/// derived type that has all the type parameters forwarded.
+///
+/// Get the a subclass of \p From (which has a lower bound \p To) that do not
+/// loose information about type parameters. \p To has to be a subclass of
+/// \p From. From has to be specialized.
+static const ObjCObjectPointerType *
+getMostInformativeDerivedClass(const ObjCObjectPointerType *From,
+                               const ObjCObjectPointerType *To, ASTContext &C) {
+  return getMostInformativeDerivedClassImpl(From, To, To, C);
+}
+
+/// Semantic inputs:
+///   There is a static lower bound (SL)
+///   There is a static upper bound (SL <: SU)
+///   There is a current type.
+/// Precondition:
+///   SL or SU is specialized. If current is not null, it is specialized.
+/// Possible cases:
+///   (1) The current type is null (unknown) and SL <: SU
+///   (2) SL <: CurrentType <: SU
+///   (3) CurrentType <: SL <: SU
+///   (4) SL <: SU <: CurrentType
+/// Effect:
+///   Use getMostInformativeDerivedClass with the upper and lower bound of (SL,
+///   CurrentType, SU). The computed lower bound must be specialized. If the
+///   result differs from CurrentType or CurrentType is null, store the result.
+static bool
+storeWhenMoreInformative(ProgramStateRef &State, SymbolRef Sym,
+                         const ObjCObjectPointerType *const *Current,
+                         const ObjCObjectPointerType *StaticLowerBound,
+                         const ObjCObjectPointerType *StaticUpperBound,
+                         ASTContext &C) {
+  // If the static upper bound is id, then the lower bound must be specialized.
+  if (StaticUpperBound->isObjCIdType()) {
+    assert(StaticLowerBound->isSpecialized());
+    StaticUpperBound = StaticLowerBound;
   }
-  const ObjCObjectPointerType *OldTy =
-    OldDTy->getAs<ObjCObjectPointerType>();
-  if (!OldTy)
-    return nullptr;
 
-  // Id the old type is 'id', the new one is more precise.
-  if (OldTy->isObjCIdType() && !NewTy->isObjCIdType())
-    return NewTy;
+  // Case (1)
+  if (!Current) {
+    if (StaticUpperBound->isUnspecialized()) {
+      State = State->set<TypeParamMap>(Sym, StaticLowerBound);
+      return true;
+    }
+    // Lower bound is specialized.
+    const ObjCObjectPointerType *WithMostInfo =
+        getMostInformativeDerivedClass(StaticUpperBound, StaticLowerBound, C);
+    State = State->set<TypeParamMap>(Sym, WithMostInfo);
+    return true;
+  }
 
-  // Return new if it's a subclass of old.
-  const ObjCInterfaceDecl *ToI = NewTy->getInterfaceDecl();
-  const ObjCInterfaceDecl *FromI = OldTy->getInterfaceDecl();
-  if (ToI && FromI && FromI->isSuperClassOf(ToI))
-    return NewTy;
+  // Case (3)
+  if (C.canAssignObjCInterfaces(StaticLowerBound, *Current)) {
+    return false;
+  }
 
-  return nullptr;
+  // Case (4)
+  if (C.canAssignObjCInterfaces(*Current, StaticUpperBound)) {
+    // The type arguments might not be forwarded at any point of inheritance.
+    const ObjCObjectPointerType *WithMostInfo =
+        getMostInformativeDerivedClass(*Current, StaticUpperBound, C);
+    WithMostInfo =
+        getMostInformativeDerivedClass(WithMostInfo, StaticLowerBound, C);
+    if (WithMostInfo == *Current)
+      return false;
+    State = State->set<TypeParamMap>(Sym, WithMostInfo);
+    return true;
+  }
+
+  // Case (2)
+  const ObjCObjectPointerType *WithMostInfo =
+      getMostInformativeDerivedClass(*Current, StaticLowerBound, C);
+  if (WithMostInfo != *Current) {
+    State = State->set<TypeParamMap>(Sym, WithMostInfo);
+    return true;
+  }
+
+  return false;
+}
+
+void DynamicTypePropagation::checkPostStmt(const CastExpr *CE,
+                                           CheckerContext &C) const {
+  if (CE->getCastKind() != CK_BitCast)
+    return;
+
+  QualType OriginType = CE->getSubExpr()->getType();
+  QualType DestType = CE->getType();
+
+  const auto *OrigObjectPtrType = OriginType->getAs<ObjCObjectPointerType>();
+  const auto *DestObjectPtrType = DestType->getAs<ObjCObjectPointerType>();
+
+  if (!OrigObjectPtrType || !DestObjectPtrType)
+    return;
+
+  ProgramStateRef State = C.getState();
+  ExplodedNode *AfterTypeProp = dynamicTypePropagationOnCasts(CE, State, C);
+
+  ASTContext &ASTCtxt = C.getASTContext();
+
+  // This checker detects the subtyping relationships using the assignment
+  // rules. In order to be able to do this the kindofness must be stripped
+  // first. The checker treats every type as kindof type anyways: when the
+  // tracked type is the subtype of the static type it tries to look up the
+  // methods in the tracked type first.
+  OrigObjectPtrType = OrigObjectPtrType->stripObjCKindOfTypeAndQuals(ASTCtxt);
+  DestObjectPtrType = DestObjectPtrType->stripObjCKindOfTypeAndQuals(ASTCtxt);
+
+  const ObjCObjectType *OrigObjectType = OrigObjectPtrType->getObjectType();
+  const ObjCObjectType *DestObjectType = DestObjectPtrType->getObjectType();
+
+  // TODO: erase tracked information when there is a cast to unrelated type
+  //       and everything is unspecialized statically.
+  if (OrigObjectType->isUnspecialized() && DestObjectType->isUnspecialized())
+    return;
+
+  SymbolRef Sym = State->getSVal(CE, C.getLocationContext()).getAsSymbol();
+  if (!Sym)
+    return;
+
+  // Check which assignments are legal.
+  bool OrigToDest =
+      ASTCtxt.canAssignObjCInterfaces(DestObjectPtrType, OrigObjectPtrType);
+  bool DestToOrig =
+      ASTCtxt.canAssignObjCInterfaces(OrigObjectPtrType, DestObjectPtrType);
+  const ObjCObjectPointerType *const *TrackedType =
+      State->get<TypeParamMap>(Sym);
+
+  // If OrigObjectType could convert to DestObjectType, this could be an
+  // implicit cast. Do not treat that cast as explicit in that case.
+  if (isa<ExplicitCastExpr>(CE) && !OrigToDest) {
+    if (DestToOrig) {
+      // Trust explicit downcasts.
+      if (storeWhenMoreInformative(State, Sym, TrackedType, DestObjectPtrType,
+                                   OrigObjectPtrType, ASTCtxt))
+        C.addTransition(State, AfterTypeProp);
+      return;
+    }
+    // Mismatched types. If the DestType specialized, store it. Forget the
+    // tracked type otherwise.
+    if (DestObjectPtrType->isSpecialized()) {
+      State = State->set<TypeParamMap>(Sym, DestObjectPtrType);
+      C.addTransition(State, AfterTypeProp);
+    } else if (TrackedType) {
+      State = State->remove<TypeParamMap>(Sym);
+      C.addTransition(State, AfterTypeProp);
+    }
+    return;
+  }
+
+  // Handle casts that could be done implicitly.
+
+  if (DestObjectType->isUnspecialized()) {
+    assert(OrigObjectType->isSpecialized());
+    // In case we already have some type information for this symbol from a
+    // Specialized -> Specialized conversion, do not record the OrigType,
+    // because it might contain less type information than the tracked type.
+    if (!TrackedType) {
+      State = State->set<TypeParamMap>(Sym, OrigObjectPtrType);
+      C.addTransition(State, AfterTypeProp);
+    }
+    return;
+  }
+
+  // The destination type is specialized.
+
+  // The tracked type should be the sub or super class of the static destination
+  // type. When an (implicit) upcast or a downcast happens according to static
+  // types, and there is no subtyping relationship between the tracked and the
+  // static destination types, it indicates an error.
+  if (TrackedType &&
+      !ASTCtxt.canAssignObjCInterfaces(DestObjectPtrType, *TrackedType) &&
+      !ASTCtxt.canAssignObjCInterfaces(*TrackedType, DestObjectPtrType)) {
+    static CheckerProgramPointTag IllegalConv(this, "IllegalConversion");
+    ExplodedNode *N = C.addTransition(State, AfterTypeProp, &IllegalConv);
+    reportGenericsBug(*TrackedType, DestObjectPtrType, N, Sym, C);
+    return;
+  }
+
+  if (OrigToDest && !DestToOrig) {
+    // When upcast happens, store the type with the most information about the
+    // type parameters.
+    if (storeWhenMoreInformative(State, Sym, TrackedType, OrigObjectPtrType,
+                                 DestObjectPtrType, ASTCtxt))
+      C.addTransition(State, AfterTypeProp);
+    return;
+  }
+
+  // Downcast happens.
+
+  // Trust tracked type on unspecialized value -> specialized implicit
+  // downcasts.
+  if (storeWhenMoreInformative(State, Sym, TrackedType, DestObjectPtrType,
+                               OrigObjectPtrType, ASTCtxt)) {
+    C.addTransition(State, AfterTypeProp);
+  }
+}
+
+static const Expr *stripCastsAndSugar(const Expr *E) {
+  E = E->IgnoreParenImpCasts();
+  if (const PseudoObjectExpr *POE = dyn_cast<PseudoObjectExpr>(E))
+    E = POE->getSyntacticForm()->IgnoreParenImpCasts();
+  if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(E))
+    E = OVE->getSourceExpr()->IgnoreParenImpCasts();
+  return E;
+}
+
+// This callback is used to infer the types for Class variables. This info is
+// used later to validate messages that sent to classes. Class variables are
+// initialized with by invoking the 'class' method on a class.
+void DynamicTypePropagation::checkPostObjCMessage(const ObjCMethodCall &M,
+                                                  CheckerContext &C) const {
+  const ObjCMessageExpr *MessageExpr = M.getOriginExpr();
+
+  SymbolRef Sym = M.getReturnValue().getAsSymbol();
+  if (!Sym)
+    return;
+
+  Selector Sel = MessageExpr->getSelector();
+  // We are only interested in cases where the class method is invoked on a
+  // class. This method is provided by the runtime and available on all classes.
+  if (MessageExpr->getReceiverKind() != ObjCMessageExpr::Class ||
+      Sel.getAsString() != "class")
+    return;
+
+  QualType ReceiverType = MessageExpr->getClassReceiver();
+  const auto *ReceiverClassType = ReceiverType->getAs<ObjCObjectType>();
+  QualType ReceiverClassPointerType =
+      C.getASTContext().getObjCObjectPointerType(
+          QualType(ReceiverClassType, 0));
+
+  if (!ReceiverClassType->isSpecialized())
+    return;
+  const auto *InferredType =
+      ReceiverClassPointerType->getAs<ObjCObjectPointerType>();
+  assert(InferredType);
+
+  ProgramStateRef State = C.getState();
+  State = State->set<TypeParamMap>(Sym, InferredType);
+  C.addTransition(State);
+}
+
+static bool isObjCTypeParamDependent(QualType Type) {
+  // It is illegal to typedef parameterized types inside an interface. Therfore
+  // an
+  // Objective-C type can only be dependent on a type parameter when the type
+  // parameter structurally present in the type itself.
+  class IsObjCTypeParamDependentTypeVisitor
+      : public RecursiveASTVisitor<IsObjCTypeParamDependentTypeVisitor> {
+  public:
+    IsObjCTypeParamDependentTypeVisitor() : Result(false) {}
+    bool VisitTypedefType(const TypedefType *Type) {
+      if (isa<ObjCTypeParamDecl>(Type->getDecl())) {
+        Result = true;
+        return false;
+      }
+      return true;
+    }
+    bool getResult() { return Result; }
+
+  private:
+    bool Result;
+  };
+
+  IsObjCTypeParamDependentTypeVisitor Visitor;
+  Visitor.TraverseType(Type);
+  return Visitor.getResult();
+}
+
+// A method might not be available in the interface indicated by the static
+// type. However it might be available in the tracked type. In order to properly
+// substitute the type parameters we need the declaration context of the method.
+// The more specialized the enclosing class of the method is, the more likely
+// that the parameter substitution will be successful.
+static const ObjCMethodDecl *
+findMethodDecl(const ObjCMessageExpr *MessageExpr,
+               const ObjCObjectPointerType *TrackedType, ASTContext &ASTCtxt) {
+  const ObjCMethodDecl *Method = nullptr;
+
+  QualType ReceiverType = MessageExpr->getReceiverType();
+  const auto *ReceiverObjectPtrType =
+      ReceiverType->getAs<ObjCObjectPointerType>();
+
+  // Do this "devirtualization" on instance and class methods only. Trust the
+  // static type on super and super class calls.
+  if (MessageExpr->getReceiverKind() == ObjCMessageExpr::Instance ||
+      MessageExpr->getReceiverKind() == ObjCMessageExpr::Class) {
+    // When the receiver type is id, Class, or some super class of the tracked
+    // type, look up the method in the tracked type, not in the receiver type.
+    // This way we preserve more information.
+    if (ReceiverType->isObjCIdType() || ReceiverType->isObjCClassType() ||
+        ASTCtxt.canAssignObjCInterfaces(ReceiverObjectPtrType, TrackedType)) {
+      const ObjCInterfaceDecl *InterfaceDecl = TrackedType->getInterfaceDecl();
+      // The method might not be found.
+      Selector Sel = MessageExpr->getSelector();
+      Method = InterfaceDecl->lookupInstanceMethod(Sel);
+      if (!Method)
+        Method = InterfaceDecl->lookupClassMethod(Sel);
+    }
+  }
+
+  // Fallback to statick method lookup when the one based on the tracked type
+  // failed.
+  return Method ? Method : MessageExpr->getMethodDecl();
+}
+
+// When the receiver has a tracked type, use that type to validate the
+// argumments of the message expression and the return value.
+void DynamicTypePropagation::checkPreObjCMessage(const ObjCMethodCall &M,
+                                                 CheckerContext &C) const {
+  ProgramStateRef State = C.getState();
+  SymbolRef Sym = M.getReceiverSVal().getAsSymbol();
+  if (!Sym)
+    return;
+
+  const ObjCObjectPointerType *const *TrackedType =
+      State->get<TypeParamMap>(Sym);
+  if (!TrackedType)
+    return;
+
+  // Get the type arguments from tracked type and substitute type arguments
+  // before do the semantic check.
+
+  ASTContext &ASTCtxt = C.getASTContext();
+  const ObjCMessageExpr *MessageExpr = M.getOriginExpr();
+  const ObjCMethodDecl *Method =
+      findMethodDecl(MessageExpr, *TrackedType, ASTCtxt);
+
+  // It is possible to call non-existent methods in Obj-C.
+  if (!Method)
+    return;
+
+  Optional<ArrayRef<QualType>> TypeArgs =
+      (*TrackedType)->getObjCSubstitutions(Method->getDeclContext());
+  // This case might happen when there is an unspecialized override of a
+  // specialized method.
+  if (!TypeArgs)
+    return;
+
+  for (unsigned i = 0; i < Method->param_size(); i++) {
+    const Expr *Arg = MessageExpr->getArg(i);
+    const ParmVarDecl *Param = Method->parameters()[i];
+
+    QualType OrigParamType = Param->getType();
+    if (!isObjCTypeParamDependent(OrigParamType))
+      continue;
+
+    QualType ParamType = OrigParamType.substObjCTypeArgs(
+        ASTCtxt, *TypeArgs, ObjCSubstitutionContext::Parameter);
+    // Check if it can be assigned
+    const auto *ParamObjectPtrType = ParamType->getAs<ObjCObjectPointerType>();
+    const auto *ArgObjectPtrType =
+        stripCastsAndSugar(Arg)->getType()->getAs<ObjCObjectPointerType>();
+    if (!ParamObjectPtrType || !ArgObjectPtrType)
+      continue;
+
+    // Check if we have more concrete tracked type that is not a super type of
+    // the static argument type.
+    SVal ArgSVal = M.getArgSVal(i);
+    SymbolRef ArgSym = ArgSVal.getAsSymbol();
+    if (ArgSym) {
+      const ObjCObjectPointerType *const *TrackedArgType =
+          State->get<TypeParamMap>(ArgSym);
+      if (TrackedArgType &&
+          ASTCtxt.canAssignObjCInterfaces(ArgObjectPtrType, *TrackedArgType)) {
+        ArgObjectPtrType = *TrackedArgType;
+      }
+    }
+
+    // Warn when argument is incompatible with the parameter.
+    if (!ASTCtxt.canAssignObjCInterfaces(ParamObjectPtrType,
+                                         ArgObjectPtrType)) {
+      static CheckerProgramPointTag Tag(this, "ArgTypeMismatch");
+      ExplodedNode *N = C.addTransition(State, &Tag);
+      reportGenericsBug(ArgObjectPtrType, ParamObjectPtrType, N, Sym, C, Arg);
+      return;
+    }
+  }
+  QualType StaticResultType = Method->getReturnType();
+  // Check whether the result type was a type parameter.
+  bool IsDeclaredAsInstanceType =
+      StaticResultType == ASTCtxt.getObjCInstanceType();
+  if (!isObjCTypeParamDependent(StaticResultType) && !IsDeclaredAsInstanceType)
+    return;
+
+  QualType ResultType = Method->getReturnType().substObjCTypeArgs(
+      ASTCtxt, *TypeArgs, ObjCSubstitutionContext::Result);
+  if (IsDeclaredAsInstanceType)
+    ResultType = QualType(*TrackedType, 0);
+
+  const Stmt *Parent =
+      C.getCurrentAnalysisDeclContext()->getParentMap().getParent(MessageExpr);
+  if (M.getMessageKind() != OCM_Message) {
+    // Properties and subscripts are not direct parents.
+    Parent =
+        C.getCurrentAnalysisDeclContext()->getParentMap().getParent(Parent);
+  }
+
+  const auto *ImplicitCast = dyn_cast_or_null<ImplicitCastExpr>(Parent);
+  if (!ImplicitCast || ImplicitCast->getCastKind() != CK_BitCast)
+    return;
+
+  const auto *ExprTypeAboveCast =
+      ImplicitCast->getType()->getAs<ObjCObjectPointerType>();
+  const auto *ResultPtrType = ResultType->getAs<ObjCObjectPointerType>();
+
+  if (!ExprTypeAboveCast || !ResultPtrType)
+    return;
+
+  // Only warn on unrelated types to avoid too many false positives on
+  // downcasts.
+  if (!ASTCtxt.canAssignObjCInterfaces(ExprTypeAboveCast, ResultPtrType) &&
+      !ASTCtxt.canAssignObjCInterfaces(ResultPtrType, ExprTypeAboveCast)) {
+    static CheckerProgramPointTag Tag(this, "ReturnTypeMismatch");
+    ExplodedNode *N = C.addTransition(State, &Tag);
+    reportGenericsBug(ResultPtrType, ExprTypeAboveCast, N, Sym, C);
+    return;
+  }
+}
+
+/// Register checkers.
+void ento::registerObjCGenericsChecker(CheckerManager &mgr) {
+  DynamicTypePropagation *checker =
+      mgr.registerChecker<DynamicTypePropagation>();
+  checker->CheckGenerics = true;
 }
 
 void ento::registerDynamicTypePropagation(CheckerManager &mgr) {
Index: lib/StaticAnalyzer/Checkers/ObjCGenericsChecker.cpp
===================================================================
--- lib/StaticAnalyzer/Checkers/ObjCGenericsChecker.cpp
+++ /dev/null
@@ -1,569 +0,0 @@
-//=== ObjCGenericsChecker.cpp - Path sensitive checker for Generics *- C++ -*=//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This checker tries to find type errors that the compiler is not able to catch
-// due to the implicit conversions that were introduced for backward
-// compatibility.
-//
-//===----------------------------------------------------------------------===//
-
-#include "ClangSACheckers.h"
-#include "clang/AST/ParentMap.h"
-#include "clang/AST/RecursiveASTVisitor.h"
-#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
-#include "clang/StaticAnalyzer/Core/Checker.h"
-#include "clang/StaticAnalyzer/Core/CheckerManager.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
-
-using namespace clang;
-using namespace ento;
-
-// ProgramState trait - a map from symbol to its specialized type.
-REGISTER_MAP_WITH_PROGRAMSTATE(TypeParamMap, SymbolRef,
-                               const ObjCObjectPointerType *)
-
-namespace {
-class ObjCGenericsChecker
-    : public Checker<check::DeadSymbols, check::PreObjCMessage,
-                     check::PostObjCMessage, check::PostStmt<CastExpr>> {
-public:
-  ProgramStateRef checkPointerEscape(ProgramStateRef State,
-                                     const InvalidatedSymbols &Escaped,
-                                     const CallEvent *Call,
-                                     PointerEscapeKind Kind) const;
-
-  void checkPreObjCMessage(const ObjCMethodCall &M, CheckerContext &C) const;
-  void checkPostObjCMessage(const ObjCMethodCall &M, CheckerContext &C) const;
-  void checkPostStmt(const CastExpr *CE, CheckerContext &C) const;
-  void checkDeadSymbols(SymbolReaper &SR, CheckerContext &C) const;
-
-private:
-  mutable std::unique_ptr<BugType> BT;
-  void initBugType() const {
-    if (!BT)
-      BT.reset(
-          new BugType(this, "Generics", categories::CoreFoundationObjectiveC));
-  }
-
-  class GenericsBugVisitor : public BugReporterVisitorImpl<GenericsBugVisitor> {
-  public:
-    GenericsBugVisitor(SymbolRef S) : Sym(S) {}
-    ~GenericsBugVisitor() override {}
-
-    void Profile(llvm::FoldingSetNodeID &ID) const override {
-      static int X = 0;
-      ID.AddPointer(&X);
-      ID.AddPointer(Sym);
-    }
-
-    PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
-                                   const ExplodedNode *PrevN,
-                                   BugReporterContext &BRC,
-                                   BugReport &BR) override;
-
-  private:
-    // The tracked symbol.
-    SymbolRef Sym;
-  };
-
-  void reportBug(const ObjCObjectPointerType *From,
-                 const ObjCObjectPointerType *To, ExplodedNode *N,
-                 SymbolRef Sym, CheckerContext &C,
-                 const Stmt *ReportedNode = nullptr) const {
-    initBugType();
-    SmallString<64> Buf;
-    llvm::raw_svector_ostream OS(Buf);
-    OS << "Incompatible pointer types assigning to '";
-    QualType::print(To, Qualifiers(), OS, C.getLangOpts(), llvm::Twine());
-    OS << "' from '";
-    QualType::print(From, Qualifiers(), OS, C.getLangOpts(), llvm::Twine());
-    OS << "'";
-    std::unique_ptr<BugReport> R(new BugReport(*BT, OS.str(), N));
-    R->markInteresting(Sym);
-    R->addVisitor(llvm::make_unique<GenericsBugVisitor>(Sym));
-    if (ReportedNode)
-      R->addRange(ReportedNode->getSourceRange());
-    C.emitReport(std::move(R));
-  }
-};
-} // end anonymous namespace
-
-PathDiagnosticPiece *ObjCGenericsChecker::GenericsBugVisitor::VisitNode(
-    const ExplodedNode *N, const ExplodedNode *PrevN, BugReporterContext &BRC,
-    BugReport &BR) {
-  ProgramStateRef state = N->getState();
-  ProgramStateRef statePrev = PrevN->getState();
-
-  const ObjCObjectPointerType *const *TrackedType =
-      state->get<TypeParamMap>(Sym);
-  const ObjCObjectPointerType *const *TrackedTypePrev =
-      statePrev->get<TypeParamMap>(Sym);
-  if (!TrackedType)
-    return nullptr;
-
-  if (TrackedTypePrev && *TrackedTypePrev == *TrackedType)
-    return nullptr;
-
-  // Retrieve the associated statement.
-  const Stmt *S = nullptr;
-  ProgramPoint ProgLoc = N->getLocation();
-  if (Optional<StmtPoint> SP = ProgLoc.getAs<StmtPoint>()) {
-    S = SP->getStmt();
-  }
-
-  if (!S)
-    return nullptr;
-
-  const LangOptions &LangOpts = BRC.getASTContext().getLangOpts();
-
-  SmallString<64> Buf;
-  llvm::raw_svector_ostream OS(Buf);
-  OS << "Type '";
-  QualType::print(*TrackedType, Qualifiers(), OS, LangOpts, llvm::Twine());
-  OS << "' is inferred from ";
-
-  if (const auto *ExplicitCast = dyn_cast<ExplicitCastExpr>(S)) {
-    OS << "explicit cast (from '";
-    QualType::print(ExplicitCast->getSubExpr()->getType().getTypePtr(),
-                    Qualifiers(), OS, LangOpts, llvm::Twine());
-    OS << "' to '";
-    QualType::print(ExplicitCast->getType().getTypePtr(), Qualifiers(), OS,
-                    LangOpts, llvm::Twine());
-    OS << "')";
-  } else if (const auto *ImplicitCast = dyn_cast<ImplicitCastExpr>(S)) {
-    OS << "implicit cast (from '";
-    QualType::print(ImplicitCast->getSubExpr()->getType().getTypePtr(),
-                    Qualifiers(), OS, LangOpts, llvm::Twine());
-    OS << "' to '";
-    QualType::print(ImplicitCast->getType().getTypePtr(), Qualifiers(), OS,
-                    LangOpts, llvm::Twine());
-    OS << "')";
-  } else {
-    OS << "this context";
-  }
-
-  // Generate the extra diagnostic.
-  PathDiagnosticLocation Pos(S, BRC.getSourceManager(),
-                             N->getLocationContext());
-  return new PathDiagnosticEventPiece(Pos, OS.str(), true, nullptr);
-}
-
-void ObjCGenericsChecker::checkDeadSymbols(SymbolReaper &SR,
-                                           CheckerContext &C) const {
-  if (!SR.hasDeadSymbols())
-    return;
-
-  ProgramStateRef State = C.getState();
-  TypeParamMapTy TyParMap = State->get<TypeParamMap>();
-  for (TypeParamMapTy::iterator I = TyParMap.begin(), E = TyParMap.end();
-       I != E; ++I) {
-    if (SR.isDead(I->first)) {
-      State = State->remove<TypeParamMap>(I->first);
-    }
-  }
-}
-
-static const ObjCObjectPointerType *getMostInformativeDerivedClassImpl(
-    const ObjCObjectPointerType *From, const ObjCObjectPointerType *To,
-    const ObjCObjectPointerType *MostInformativeCandidate, ASTContext &C) {
-  // Checking if from and to are the same classes modulo specialization.
-  if (From->getInterfaceDecl()->getCanonicalDecl() ==
-      To->getInterfaceDecl()->getCanonicalDecl()) {
-    if (To->isSpecialized()) {
-      assert(MostInformativeCandidate->isSpecialized());
-      return MostInformativeCandidate;
-    }
-    return From;
-  }
-  const auto *SuperOfTo =
-      To->getObjectType()->getSuperClassType()->getAs<ObjCObjectType>();
-  assert(SuperOfTo);
-  QualType SuperPtrOfToQual =
-      C.getObjCObjectPointerType(QualType(SuperOfTo, 0));
-  const auto *SuperPtrOfTo = SuperPtrOfToQual->getAs<ObjCObjectPointerType>();
-  if (To->isUnspecialized())
-    return getMostInformativeDerivedClassImpl(From, SuperPtrOfTo, SuperPtrOfTo,
-                                              C);
-  else
-    return getMostInformativeDerivedClassImpl(From, SuperPtrOfTo,
-                                              MostInformativeCandidate, C);
-}
-
-/// Get the most derived class if From that do not loose information about type
-/// parameters. To has to be a subclass of From. From has to be specialized.
-static const ObjCObjectPointerType *
-getMostInformativeDerivedClass(const ObjCObjectPointerType *From,
-                               const ObjCObjectPointerType *To, ASTContext &C) {
-  return getMostInformativeDerivedClassImpl(From, To, To, C);
-}
-
-static bool storeWhenMoreInformative(ProgramStateRef &State, SymbolRef Sym,
-                                     const ObjCObjectPointerType *const *Old,
-                                     const ObjCObjectPointerType *New,
-                                     ASTContext &C) {
-  if (!Old || C.canAssignObjCInterfaces(*Old, New)) {
-    State = State->set<TypeParamMap>(Sym, New);
-    return true;
-  }
-  return false;
-}
-
-void ObjCGenericsChecker::checkPostStmt(const CastExpr *CE,
-                                        CheckerContext &C) const {
-  if (CE->getCastKind() != CK_BitCast)
-    return;
-
-  QualType OriginType = CE->getSubExpr()->getType();
-  QualType DestType = CE->getType();
-
-  const auto *OrigObjectPtrType = OriginType->getAs<ObjCObjectPointerType>();
-  const auto *DestObjectPtrType = DestType->getAs<ObjCObjectPointerType>();
-
-  if (!OrigObjectPtrType || !DestObjectPtrType)
-    return;
-
-  ASTContext &ASTCtxt = C.getASTContext();
-
-  // This checker detects the subtyping relationships using the assignment
-  // rules. In order to be able to do this the kindofness must be stripped
-  // first. The checker treats every type as kindof type anyways: when the
-  // tracked type is the subtype of the static type it tries to look up the
-  // methods in the tracked type first.
-  OrigObjectPtrType = OrigObjectPtrType->stripObjCKindOfTypeAndQuals(ASTCtxt);
-  DestObjectPtrType = DestObjectPtrType->stripObjCKindOfTypeAndQuals(ASTCtxt);
-
-  const ObjCObjectType *OrigObjectType = OrigObjectPtrType->getObjectType();
-  const ObjCObjectType *DestObjectType = DestObjectPtrType->getObjectType();
-
-  if (OrigObjectType->isUnspecialized() && DestObjectType->isUnspecialized())
-    return;
-
-  ProgramStateRef State = C.getState();
-  SymbolRef Sym = State->getSVal(CE, C.getLocationContext()).getAsSymbol();
-  if (!Sym)
-    return;
-
-  // Check which assignments are legal.
-  bool OrigToDest =
-      ASTCtxt.canAssignObjCInterfaces(DestObjectPtrType, OrigObjectPtrType);
-  bool DestToOrig =
-      ASTCtxt.canAssignObjCInterfaces(OrigObjectPtrType, DestObjectPtrType);
-  const ObjCObjectPointerType *const *TrackedType =
-      State->get<TypeParamMap>(Sym);
-
-  // If OrigObjectType could convert to DestObjectType, this could be an
-  // implicit cast. Do not treat that cast as explicit in that case.
-  if (isa<ExplicitCastExpr>(CE) && !OrigToDest) {
-    if (DestToOrig) {
-      // Trust explicit downcasts.
-      // However a downcast may also lose information. E. g.:
-      //   MutableMap<T, U> : Map
-      // The downcast to MutableMap loses the information about the types of the
-      // Map (due to the type parameters are not being forwarded to Map), and in
-      // general there is no way to recover that information from the
-      // declaration. In order to have to most information, lets find the most
-      // derived type that has all the type parameters forwarded.
-      const ObjCObjectPointerType *WithMostInfo =
-          getMostInformativeDerivedClass(OrigObjectPtrType, DestObjectPtrType,
-                                         C.getASTContext());
-      if (storeWhenMoreInformative(State, Sym, TrackedType, WithMostInfo,
-                                   ASTCtxt))
-        C.addTransition(State);
-      return;
-    }
-    // Mismatched types. If the DestType specialized, store it. Forget the
-    // tracked type otherwise.
-    if (DestObjectPtrType->isSpecialized()) {
-      State = State->set<TypeParamMap>(Sym, DestObjectPtrType);
-      C.addTransition(State);
-    } else if (TrackedType) {
-      State = State->remove<TypeParamMap>(Sym);
-      C.addTransition(State);
-    }
-    return;
-  }
-
-  // Handle implicit casts and explicit upcasts.
-
-  if (DestObjectType->isUnspecialized()) {
-    assert(OrigObjectType->isSpecialized());
-    // In case we already have some type information for this symbol from a
-    // Specialized -> Specialized conversion, do not record the OrigType,
-    // because it might contain less type information than the tracked type.
-    if (!TrackedType) {
-      State = State->set<TypeParamMap>(Sym, OrigObjectPtrType);
-      C.addTransition(State);
-    }
-    return;
-  }
-
-  // The destination type is specialized.
-
-  // The tracked type should be the sub or super class of the static destination
-  // type. When an (implicit) upcast or a downcast happens according to static
-  // types, and there is no subtyping relationship between the tracked and the
-  // static destination types, it indicates an error.
-  if (TrackedType &&
-      !ASTCtxt.canAssignObjCInterfaces(DestObjectPtrType, *TrackedType) &&
-      !ASTCtxt.canAssignObjCInterfaces(*TrackedType, DestObjectPtrType)) {
-    static CheckerProgramPointTag IllegalConv(this, "IllegalConversion");
-    ExplodedNode *N = C.addTransition(State, C.getPredecessor(), &IllegalConv);
-    reportBug(*TrackedType, DestObjectPtrType, N, Sym, C);
-    return;
-  }
-
-  if (OrigToDest && !DestToOrig) {
-    // When upcast happens, store the type with the most information about the
-    // type parameters.
-    const ObjCObjectPointerType *WithMostInfo = getMostInformativeDerivedClass(
-        DestObjectPtrType, OrigObjectPtrType, ASTCtxt);
-    if (storeWhenMoreInformative(State, Sym, TrackedType, WithMostInfo,
-                                 ASTCtxt))
-      C.addTransition(State);
-    return;
-  }
-
-  // Downcast happens.
-
-  // Trust tracked type on unspecialized value -> specialized implicit
-  // downcasts.
-  if (storeWhenMoreInformative(State, Sym, TrackedType, DestObjectPtrType,
-                               ASTCtxt)) {
-    C.addTransition(State);
-  }
-}
-
-static const Expr *stripCastsAndSugar(const Expr *E) {
-  E = E->IgnoreParenImpCasts();
-  if (const PseudoObjectExpr *POE = dyn_cast<PseudoObjectExpr>(E))
-    E = POE->getSyntacticForm()->IgnoreParenImpCasts();
-  if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(E))
-    E = OVE->getSourceExpr()->IgnoreParenImpCasts();
-  return E;
-}
-
-// This callback is used to infer the types for Class variables. This info is
-// used later to validate messages that sent to classes. Class variables are
-// initialized with by invoking the 'class' method on a class.
-void ObjCGenericsChecker::checkPostObjCMessage(const ObjCMethodCall &M,
-                                               CheckerContext &C) const {
-  const ObjCMessageExpr *MessageExpr = M.getOriginExpr();
-
-  SymbolRef Sym = M.getReturnValue().getAsSymbol();
-  if (!Sym)
-    return;
-
-  Selector Sel = MessageExpr->getSelector();
-  // We are only interested in cases where the class method is invoked on a
-  // class. This method is provided by the runtime and available on all classes.
-  if (MessageExpr->getReceiverKind() != ObjCMessageExpr::Class ||
-      Sel.getAsString() != "class")
-    return;
-
-  QualType ReceiverType = MessageExpr->getClassReceiver();
-  const auto *ReceiverClassType = ReceiverType->getAs<ObjCObjectType>();
-  QualType ReceiverClassPointerType =
-      C.getASTContext().getObjCObjectPointerType(
-          QualType(ReceiverClassType, 0));
-
-  if (!ReceiverClassType->isSpecialized())
-    return;
-  const auto *InferredType =
-      ReceiverClassPointerType->getAs<ObjCObjectPointerType>();
-  assert(InferredType);
-
-  ProgramStateRef State = C.getState();
-  State = State->set<TypeParamMap>(Sym, InferredType);
-  C.addTransition(State);
-}
-
-static bool isObjCTypeParamDependent(QualType Type) {
-  // It is illegal to typedef parameterized types inside an interface. Therfore
-  // an
-  // Objective-C type can only be dependent on a type parameter when the type
-  // parameter structurally present in the type itself.
-  class IsObjCTypeParamDependentTypeVisitor
-      : public RecursiveASTVisitor<IsObjCTypeParamDependentTypeVisitor> {
-  public:
-    IsObjCTypeParamDependentTypeVisitor() : Result(false) {}
-    bool VisitTypedefType(const TypedefType *Type) {
-      if (isa<ObjCTypeParamDecl>(Type->getDecl())) {
-        Result = true;
-        return false;
-      }
-      return true;
-    }
-    bool getResult() { return Result; }
-
-  private:
-    bool Result;
-  };
-
-  IsObjCTypeParamDependentTypeVisitor Visitor;
-  Visitor.TraverseType(Type);
-  return Visitor.getResult();
-}
-
-// A method might not be available in the interface indicated by the static
-// type. However it might be available in the tracked type. In order to properly
-// substitute the type parameters we need the declaration context of the method.
-// The more specialized the enclosing class of the method is, the more likely
-// that the parameter substitution will be successful.
-static const ObjCMethodDecl *
-findMethodDecl(const ObjCMessageExpr *MessageExpr,
-               const ObjCObjectPointerType *TrackedType, ASTContext &ASTCtxt) {
-  const ObjCMethodDecl *Method = nullptr;
-
-  QualType ReceiverType = MessageExpr->getReceiverType();
-  const auto *ReceiverObjectPtrType =
-      ReceiverType->getAs<ObjCObjectPointerType>();
-
-  // Do this "devirtualization" on instance and class methods only. Trust the
-  // static type on super and super class calls.
-  if (MessageExpr->getReceiverKind() == ObjCMessageExpr::Instance ||
-      MessageExpr->getReceiverKind() == ObjCMessageExpr::Class) {
-    // When the receiver type is id, Class, or some super class of the tracked
-    // type, look up the method in the tracked type, not in the receiver type.
-    // This way we preserve more information.
-    if (ReceiverType->isObjCIdType() || ReceiverType->isObjCClassType() ||
-        ASTCtxt.canAssignObjCInterfaces(ReceiverObjectPtrType, TrackedType)) {
-      const ObjCInterfaceDecl *InterfaceDecl = TrackedType->getInterfaceDecl();
-      // The method might not be found.
-      Selector Sel = MessageExpr->getSelector();
-      Method = InterfaceDecl->lookupInstanceMethod(Sel);
-      if (!Method)
-        Method = InterfaceDecl->lookupClassMethod(Sel);
-    }
-  }
-
-  // Fallback to statick method lookup when the one based on the tracked type
-  // failed.
-  return Method ? Method : MessageExpr->getMethodDecl();
-}
-
-// When the receiver has a tracked type, use that type to validate the
-// argumments of the message expression and the return value.
-void ObjCGenericsChecker::checkPreObjCMessage(const ObjCMethodCall &M,
-                                              CheckerContext &C) const {
-  ProgramStateRef State = C.getState();
-  SymbolRef Sym = M.getReceiverSVal().getAsSymbol();
-  if (!Sym)
-    return;
-
-  const ObjCObjectPointerType *const *TrackedType =
-      State->get<TypeParamMap>(Sym);
-  if (!TrackedType)
-    return;
-
-  // Get the type arguments from tracked type and substitute type arguments
-  // before do the semantic check.
-
-  ASTContext &ASTCtxt = C.getASTContext();
-  const ObjCMessageExpr *MessageExpr = M.getOriginExpr();
-  const ObjCMethodDecl *Method =
-      findMethodDecl(MessageExpr, *TrackedType, ASTCtxt);
-
-  // It is possible to call non-existent methods in Obj-C.
-  if (!Method)
-    return;
-
-  Optional<ArrayRef<QualType>> TypeArgs =
-      (*TrackedType)->getObjCSubstitutions(Method->getDeclContext());
-  // This case might happen when there is an unspecialized override of a
-  // specialized method.
-  if (!TypeArgs)
-    return;
-
-  for (unsigned i = 0; i < Method->param_size(); i++) {
-    const Expr *Arg = MessageExpr->getArg(i);
-    const ParmVarDecl *Param = Method->parameters()[i];
-
-    QualType OrigParamType = Param->getType();
-    if (!isObjCTypeParamDependent(OrigParamType))
-      continue;
-
-    QualType ParamType = OrigParamType.substObjCTypeArgs(
-        ASTCtxt, *TypeArgs, ObjCSubstitutionContext::Parameter);
-    // Check if it can be assigned
-    const auto *ParamObjectPtrType = ParamType->getAs<ObjCObjectPointerType>();
-    const auto *ArgObjectPtrType =
-        stripCastsAndSugar(Arg)->getType()->getAs<ObjCObjectPointerType>();
-    if (!ParamObjectPtrType || !ArgObjectPtrType)
-      continue;
-
-    // Check if we have more concrete tracked type that is not a super type of
-    // the static argument type.
-    SVal ArgSVal = M.getArgSVal(i);
-    SymbolRef ArgSym = ArgSVal.getAsSymbol();
-    if (ArgSym) {
-      const ObjCObjectPointerType *const *TrackedArgType =
-          State->get<TypeParamMap>(ArgSym);
-      if (TrackedArgType &&
-          ASTCtxt.canAssignObjCInterfaces(ArgObjectPtrType, *TrackedArgType)) {
-        ArgObjectPtrType = *TrackedArgType;
-      }
-    }
-
-    // Warn when argument is incompatible with the parameter.
-    if (!ASTCtxt.canAssignObjCInterfaces(ParamObjectPtrType,
-                                         ArgObjectPtrType)) {
-      static CheckerProgramPointTag Tag(this, "ArgTypeMismatch");
-      ExplodedNode *N = C.addTransition(State, C.getPredecessor(), &Tag);
-      reportBug(ArgObjectPtrType, ParamObjectPtrType, N, Sym, C, Arg);
-      return;
-    }
-  }
-  QualType StaticResultType = Method->getReturnType();
-  // Check whether the result type was a type parameter.
-  bool IsDeclaredAsInstanceType =
-      StaticResultType == ASTCtxt.getObjCInstanceType();
-  if (!isObjCTypeParamDependent(StaticResultType) && !IsDeclaredAsInstanceType)
-    return;
-
-  QualType ResultType = Method->getReturnType().substObjCTypeArgs(
-      ASTCtxt, *TypeArgs, ObjCSubstitutionContext::Result);
-  if (IsDeclaredAsInstanceType)
-    ResultType = QualType(*TrackedType, 0);
-
-  const Stmt *Parent =
-      C.getCurrentAnalysisDeclContext()->getParentMap().getParent(MessageExpr);
-  if (M.getMessageKind() != OCM_Message) {
-    // Properties and subscripts are not direct parents.
-    Parent =
-        C.getCurrentAnalysisDeclContext()->getParentMap().getParent(Parent);
-  }
-
-  const auto *ImplicitCast = dyn_cast_or_null<ImplicitCastExpr>(Parent);
-  if (!ImplicitCast || ImplicitCast->getCastKind() != CK_BitCast)
-    return;
-
-  const auto *ExprTypeAboveCast =
-      ImplicitCast->getType()->getAs<ObjCObjectPointerType>();
-  const auto *ResultPtrType = ResultType->getAs<ObjCObjectPointerType>();
-
-  if (!ExprTypeAboveCast || !ResultPtrType)
-    return;
-
-  // Only warn on unrelated types to avoid too many false positives on
-  // downcasts.
-  if (!ASTCtxt.canAssignObjCInterfaces(ExprTypeAboveCast, ResultPtrType) &&
-      !ASTCtxt.canAssignObjCInterfaces(ResultPtrType, ExprTypeAboveCast)) {
-    static CheckerProgramPointTag Tag(this, "ReturnTypeMismatch");
-    ExplodedNode *N = C.addTransition(State, C.getPredecessor(), &Tag);
-    reportBug(ResultPtrType, ExprTypeAboveCast, N, Sym, C);
-    return;
-  }
-}
-
-/// Register checker.
-void ento::registerObjCGenericsChecker(CheckerManager &mgr) {
-  mgr.registerChecker<ObjCGenericsChecker>();
-}
Index: test/Analysis/generics.m
===================================================================
--- test/Analysis/generics.m
+++ test/Analysis/generics.m
@@ -87,38 +87,38 @@
 void incompatibleTypesErased(NSArray *a, NSArray<NSString *> *b,
                              NSArray<NSNumber *> *c) {
   a = b;
-  c = a; // expected-warning  {{Incompatible pointer types assigning to 'NSArray<NSNumber *> *' from 'NSArray<NSString *> *'}}
-  [a contains: [[NSNumber alloc] init]]; // expected-warning {{Incompatible}}
+  c = a; // expected-warning  {{Conversion from value of type 'NSArray<NSString *> *' to incompatible type 'NSArray<NSNumber *> *'}}
+  [a contains: [[NSNumber alloc] init]]; // expected-warning {{Conversion}}
   [a contains: [[NSString alloc] init]];
-  doStuff(a); // expected-warning {{Incompatible}}
+  doStuff(a); // expected-warning {{Conversion}}
 }
 
 void crossProceduralErasedTypes() {
-  NSArray<NSString *> *a = getTypedStuff(); // expected-warning {{Incompatible}}
+  NSArray<NSString *> *a = getTypedStuff(); // expected-warning {{Conversion}}
 }
 
 void incompatibleTypesErasedReverseConversion(NSArray *a,
                                               NSArray<NSString *> *b) {
   b = a;
-  [a contains: [[NSNumber alloc] init]]; // expected-warning {{Incompatible}}
+  [a contains: [[NSNumber alloc] init]]; // expected-warning {{Conversion}}
   [a contains: [[NSString alloc] init]];
-  doStuff(a); // expected-warning {{Incompatible}}
+  doStuff(a); // expected-warning {{Conversion}}
 }
 
 void idErasedIncompatibleTypesReverseConversion(id a, NSArray<NSString *> *b) {
   b = a;
-  [a contains: [[NSNumber alloc] init]]; // expected-warning {{Incompatible}}
+  [a contains: [[NSNumber alloc] init]]; // expected-warning {{Conversion}}
   [a contains: [[NSString alloc] init]];
-  doStuff(a); // expected-warning {{Incompatible}}
+  doStuff(a); // expected-warning {{Conversion}}
 }
 
 void idErasedIncompatibleTypes(id a, NSArray<NSString *> *b,
                                NSArray<NSNumber *> *c) {
   a = b;
-  c = a; // expected-warning {{Incompatible}}
-  [a contains: [[NSNumber alloc] init]]; // expected-warning {{Incompatible}}
+  c = a; // expected-warning {{Conversion}}
+  [a contains: [[NSNumber alloc] init]]; // expected-warning {{Conversion}}
   [a contains: [[NSString alloc] init]];
-  doStuff(a); // expected-warning {{Incompatible}}
+  doStuff(a); // expected-warning {{Conversion}}
 }
 
 void pathSensitiveInference(MutableArray *m, MutableArray<NSString *> *a,
@@ -130,19 +130,19 @@
     m = b;
     [m contains: [[NSMutableString alloc] init]];
   }
-  [m addObject: [[NSString alloc] init]]; // expected-warning {{Incompatible}}
+  [m addObject: [[NSString alloc] init]]; // expected-warning {{Conversion}}
   [m addObject: [[NSMutableString alloc] init]];
 }
 
 void verifyAPIusage(id a, MutableArray<NSString *> *b) {
   b = a;
-  doStuff(a); // expected-warning {{Incompatible}}
+  doStuff(a); // expected-warning {{Conversion}}
 }
 
 void trustExplicitCasts(MutableArray *a,
                         MutableArray<NSMutableString *> *b) {
   b = (MutableArray<NSMutableString *> *)a;
-  [a addObject: [[NSString alloc] init]]; // expected-warning {{Incompatible}}
+  [a addObject: [[NSString alloc] init]]; // expected-warning {{Conversion}}
 }
 
 void subtypeOfGeneric(id d, MyMutableStringArray *a,
@@ -150,7 +150,7 @@
                        MutableArray<NSNumber *> *c) {
   d = a;
   b = d;
-  c = d; // expected-warning {{Incompatible}}
+  c = d; // expected-warning {{Conversion}}
 }
 
 void genericSubtypeOfGeneric(id d, ExceptionalArray<NSString *> *a,
@@ -158,9 +158,9 @@
                              MutableArray<NSNumber *> *c) {
   d = a;
   [d contains: [[NSString alloc] init]];
-  [d contains: [[NSNumber alloc] init]]; // expected-warning {{Incompatible}}
+  [d contains: [[NSNumber alloc] init]]; // expected-warning {{Conversion}}
   b = d;
-  c = d; // expected-warning {{Incompatible}}
+  c = d; // expected-warning {{Conversion}}
 }
 
 void genericSubtypeOfGenericReverse(id d, ExceptionalArray<NSString *> *a,
@@ -168,41 +168,59 @@
                                     MutableArray<NSNumber *> *c) {
   a = d;
   [d contains: [[NSString alloc] init]];
-  [d contains: [[NSNumber alloc] init]]; // expected-warning {{Incompatible}}
+  [d contains: [[NSNumber alloc] init]]; // expected-warning {{Conversion}}
   b = d;
-  c = d; // expected-warning {{Incompatible}}
+  c = d; // expected-warning {{Conversion}}
 }
 
 void inferenceFromAPI(id a) {
   // Here the type parameter is invariant. There should be a warning every time
   // when the type parameter changes during the conversions.
   withMutArrString(a);
-  withMutArrMutableString(a); // expected-warning {{Incompatible}}
+  withMutArrMutableString(a); // expected-warning {{Conversion}}
 }
 
 void inferenceFromAPI2(id a) {
   withMutArrMutableString(a);
-  withMutArrString(a); // expected-warning {{Incompatible}}
+  withMutArrString(a); // expected-warning {{Conversion}}
 }
 
 void inferenceFromAPIWithLegacyTypes(LegacyMutableArray *a) {
   withMutArrMutableString(a);
-  withMutArrString(a); // expected-warning {{Incompatible}}
+  withMutArrString(a); // expected-warning {{Conversion}}
 }
 
 void inferenceFromAPIWithLegacyTypes2(LegacySpecialMutableArray *a) {
   withMutArrString(a);
-  withMutArrMutableString(a); // expected-warning {{Incompatible}}
+  withMutArrMutableString(a); // expected-warning {{Conversion}}
+}
+
+void inferenceFromAPIWithLegacyTypes3(__kindof NSArray<NSString *> *a) {
+  LegacyMutableArray *b = a;
+  withMutArrString(b);
+  withMutArrMutableString(b); // expected-warning {{Conversion}}
 }
 
 void inferenceFromAPIWithBuggyTypes(BuggyMutableArray<NSMutableString *> *a) {
   withMutArrString(a);
-  withMutArrMutableString(a); // expected-warning {{Incompatible}}
+  withMutArrMutableString(a); // expected-warning {{Conversion}}
 }
 
 void InferenceFromAPIWithBuggyTypes2(BuggySpecialMutableArray<NSMutableString *> *a) {
   withMutArrMutableString(a);
-  withMutArrString(a); // expected-warning {{Incompatible}}
+  withMutArrString(a); // expected-warning {{Conversion}}
+}
+
+void InferenceFromAPIWithBuggyTypes3(MutableArray<NSMutableString *> *a) {
+  id b = a;
+  withMutArrMutableString((BuggyMutableArray<NSMutableString *> *)b);
+  withMutArrString(b); // expected-warning {{Conversion}}
+}
+
+void InferenceFromAPIWithBuggyTypes4(__kindof NSArray<NSString *> *a) {
+  BuggyMutableArray<NSMutableString *> *b = a;
+  withMutArrString(b);
+  withMutArrMutableString(b); // expected-warning {{Conversion}}
 }
 
 NSArray<NSString *> *getStrings();
@@ -215,13 +233,13 @@
 
 void workWithProperties(NSArray<NSNumber *> *a) {
   NSArray *b = a;
-  NSString *str = [b getObjAtIndex: 0]; // expected-warning {{Incompatible}}
+  NSString *str = [b getObjAtIndex: 0]; // expected-warning {{Conversion}}
   NSNumber *num = [b getObjAtIndex: 0];
-  str = [b firstObject]; // expected-warning {{Incompatible}}
+  str = [b firstObject]; // expected-warning {{Conversion}}
   num = [b firstObject];
-  str = b.firstObject; // expected-warning {{Incompatible}}
+  str = b.firstObject; // expected-warning {{Conversion}}
   num = b.firstObject;
-  str = b[0]; // expected-warning {{Incompatible}}
+  str = b[0]; // expected-warning {{Conversion}}
   num = b[0];
 }
 
@@ -230,7 +248,7 @@
   a = b;
   if (getUnknown() == 5) {
     m = a;  
-    [m addObject: [[NSString alloc] init]]; // expected-warning {{Incompatible}}
+    [m addObject: [[NSString alloc] init]]; // expected-warning {{Conversion}}
   } else {
     m = b;
     [m addObject: [[NSMutableString alloc] init]];
@@ -241,7 +259,7 @@
                                   MutableArray<NSMutableString *> *b) {
   a = b;
   if (getUnknown() == 5) {
-    [a addObject: [[NSString alloc] init]]; // expected-warning {{Incompatible}}
+    [a addObject: [[NSString alloc] init]]; // expected-warning {{Conversion}}
   } else {
     [a addObject: [[NSMutableString alloc] init]];
   }
@@ -256,7 +274,7 @@
 void testAnnotatedLiterals() {
   NSArray<NSString *> *arr = @[@"A", @"B"];
   NSArray *arr2 = arr;
-  [arr2 contains: [[NSNumber alloc] init]]; // expected-warning {{Incompatible}}
+  [arr2 contains: [[NSNumber alloc] init]]; // expected-warning {{Conversion}}
 }
 
 void nonExistentMethodDoesNotCrash(id a, MutableArray<NSMutableString *> *b) {
@@ -266,13 +284,13 @@
 
 void trackedClassVariables() {
   Class c = [NSArray<NSString *> class];
-  NSArray<NSNumber *> *a = [c getEmpty]; // expected-warning {{Incompatible}}
-  a = [c getEmpty2]; // expected-warning {{Incompatible}}
+  NSArray<NSNumber *> *a = [c getEmpty]; // expected-warning {{Conversion}}
+  a = [c getEmpty2]; // expected-warning {{Conversion}}
 }
 
 void nestedCollections(NSArray<NSArray<NSNumber *> *> *mat, NSArray<NSString *> *row) {
   id temp = row;
-  [mat contains: temp]; // expected-warning {{Incompatible}}
+  [mat contains: temp]; // expected-warning {{Conversion}}
 }
 
 void testMistmatchedTypeCast(MutableArray<NSMutableString *> *a) {
@@ -283,7 +301,6 @@
   [c addObject: [[NSString alloc] init]];
 }
 
-// CHECK:  <key>diagnostics</key>
 // CHECK:  <array>
 // CHECK:   <dict>
 // CHECK:    <key>path</key>
@@ -410,15 +427,15 @@
 // CHECK:      </array>
 // CHECK:      <key>depth</key><integer>0</integer>
 // CHECK:      <key>extended_message</key>
-// CHECK:      <string>Incompatible pointer types assigning to &apos;NSArray&lt;NSNumber *&gt; *&apos; from &apos;NSArray&lt;NSString *&gt; *&apos;</string>
+// CHECK:      <string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
 // CHECK:      <key>message</key>
-// CHECK:      <string>Incompatible pointer types assigning to &apos;NSArray&lt;NSNumber *&gt; *&apos; from &apos;NSArray&lt;NSString *&gt; *&apos;</string>
+// CHECK:      <string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
 // CHECK:     </dict>
 // CHECK:    </array>
-// CHECK:    <key>description</key><string>Incompatible pointer types assigning to &apos;NSArray&lt;NSNumber *&gt; *&apos; from &apos;NSArray&lt;NSString *&gt; *&apos;</string>
+// CHECK:    <key>description</key><string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
 // CHECK:    <key>category</key><string>Core Foundation/Objective-C</string>
 // CHECK:    <key>type</key><string>Generics</string>
-// CHECK:    <key>check_name</key><string>alpha.osx.cocoa.ObjCGenerics</string>
+// CHECK:    <key>check_name</key><string>core.DynamicTypePropagation</string>
 // CHECK:   <key>issue_context_kind</key><string>function</string>
 // CHECK:   <key>issue_context</key><string>incompatibleTypesErased</string>
 // CHECK:   <key>issue_hash</key><string>2</string>
@@ -520,15 +537,15 @@
 // CHECK:      </array>
 // CHECK:      <key>depth</key><integer>0</integer>
 // CHECK:      <key>extended_message</key>
-// CHECK:      <string>Incompatible pointer types assigning to &apos;NSString *&apos; from &apos;NSNumber *&apos;</string>
+// CHECK:      <string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
 // CHECK:      <key>message</key>
-// CHECK:      <string>Incompatible pointer types assigning to &apos;NSString *&apos; from &apos;NSNumber *&apos;</string>
+// CHECK:      <string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
 // CHECK:     </dict>
 // CHECK:    </array>
-// CHECK:    <key>description</key><string>Incompatible pointer types assigning to &apos;NSString *&apos; from &apos;NSNumber *&apos;</string>
+// CHECK:    <key>description</key><string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
 // CHECK:    <key>category</key><string>Core Foundation/Objective-C</string>
 // CHECK:    <key>type</key><string>Generics</string>
-// CHECK:    <key>check_name</key><string>alpha.osx.cocoa.ObjCGenerics</string>
+// CHECK:    <key>check_name</key><string>core.DynamicTypePropagation</string>
 // CHECK:   <key>issue_context_kind</key><string>function</string>
 // CHECK:   <key>issue_context</key><string>incompatibleTypesErased</string>
 // CHECK:   <key>issue_hash</key><string>3</string>
@@ -664,15 +681,15 @@
 // CHECK:      </array>
 // CHECK:      <key>depth</key><integer>0</integer>
 // CHECK:      <key>extended_message</key>
-// CHECK:      <string>Incompatible pointer types assigning to &apos;NSArray&lt;NSNumber *&gt; *&apos; from &apos;NSArray&lt;NSString *&gt; *&apos;</string>
+// CHECK:      <string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
 // CHECK:      <key>message</key>
-// CHECK:      <string>Incompatible pointer types assigning to &apos;NSArray&lt;NSNumber *&gt; *&apos; from &apos;NSArray&lt;NSString *&gt; *&apos;</string>
+// CHECK:      <string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
 // CHECK:     </dict>
 // CHECK:    </array>
-// CHECK:    <key>description</key><string>Incompatible pointer types assigning to &apos;NSArray&lt;NSNumber *&gt; *&apos; from &apos;NSArray&lt;NSString *&gt; *&apos;</string>
+// CHECK:    <key>description</key><string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
 // CHECK:    <key>category</key><string>Core Foundation/Objective-C</string>
 // CHECK:    <key>type</key><string>Generics</string>
-// CHECK:    <key>check_name</key><string>alpha.osx.cocoa.ObjCGenerics</string>
+// CHECK:    <key>check_name</key><string>core.DynamicTypePropagation</string>
 // CHECK:   <key>issue_context_kind</key><string>function</string>
 // CHECK:   <key>issue_context</key><string>incompatibleTypesErased</string>
 // CHECK:   <key>issue_hash</key><string>5</string>
@@ -914,15 +931,15 @@
 // CHECK:      </array>
 // CHECK:      <key>depth</key><integer>0</integer>
 // CHECK:      <key>extended_message</key>
-// CHECK:      <string>Incompatible pointer types assigning to &apos;NSArray&lt;NSString *&gt; *&apos; from &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
+// CHECK:      <string>Conversion from value of type &apos;NSArray&lt;NSNumber *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSString *&gt; *&apos;</string>
 // CHECK:      <key>message</key>
-// CHECK:      <string>Incompatible pointer types assigning to &apos;NSArray&lt;NSString *&gt; *&apos; from &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
+// CHECK:      <string>Conversion from value of type &apos;NSArray&lt;NSNumber *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSString *&gt; *&apos;</string>
 // CHECK:     </dict>
 // CHECK:    </array>
-// CHECK:    <key>description</key><string>Incompatible pointer types assigning to &apos;NSArray&lt;NSString *&gt; *&apos; from &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
+// CHECK:    <key>description</key><string>Conversion from value of type &apos;NSArray&lt;NSNumber *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSString *&gt; *&apos;</string>
 // CHECK:    <key>category</key><string>Core Foundation/Objective-C</string>
 // CHECK:    <key>type</key><string>Generics</string>
-// CHECK:    <key>check_name</key><string>alpha.osx.cocoa.ObjCGenerics</string>
+// CHECK:    <key>check_name</key><string>core.DynamicTypePropagation</string>
 // CHECK:   <key>issue_context_kind</key><string>function</string>
 // CHECK:   <key>issue_context</key><string>crossProceduralErasedTypes</string>
 // CHECK:   <key>issue_hash</key><string>1</string>
@@ -1024,15 +1041,15 @@
 // CHECK:      </array>
 // CHECK:      <key>depth</key><integer>0</integer>
 // CHECK:      <key>extended_message</key>
-// CHECK:      <string>Incompatible pointer types assigning to &apos;NSString *&apos; from &apos;NSNumber *&apos;</string>
+// CHECK:      <string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
 // CHECK:      <key>message</key>
-// CHECK:      <string>Incompatible pointer types assigning to &apos;NSString *&apos; from &apos;NSNumber *&apos;</string>
+// CHECK:      <string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
 // CHECK:     </dict>
 // CHECK:    </array>
-// CHECK:    <key>description</key><string>Incompatible pointer types assigning to &apos;NSString *&apos; from &apos;NSNumber *&apos;</string>
+// CHECK:    <key>description</key><string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
 // CHECK:    <key>category</key><string>Core Foundation/Objective-C</string>
 // CHECK:    <key>type</key><string>Generics</string>
-// CHECK:    <key>check_name</key><string>alpha.osx.cocoa.ObjCGenerics</string>
+// CHECK:    <key>check_name</key><string>core.DynamicTypePropagation</string>
 // CHECK:   <key>issue_context_kind</key><string>function</string>
 // CHECK:   <key>issue_context</key><string>incompatibleTypesErasedReverseConversion</string>
 // CHECK:   <key>issue_hash</key><string>2</string>
@@ -1168,15 +1185,15 @@
 // CHECK:      </array>
 // CHECK:      <key>depth</key><integer>0</integer>
 // CHECK:      <key>extended_message</key>
-// CHECK:      <string>Incompatible pointer types assigning to &apos;NSArray&lt;NSNumber *&gt; *&apos; from &apos;NSArray&lt;NSString *&gt; *&apos;</string>
+// CHECK:      <string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
 // CHECK:      <key>message</key>
-// CHECK:      <string>Incompatible pointer types assigning to &apos;NSArray&lt;NSNumber *&gt; *&apos; from &apos;NSArray&lt;NSString *&gt; *&apos;</string>
+// CHECK:      <string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
 // CHECK:     </dict>
 // CHECK:    </array>
-// CHECK:    <key>description</key><string>Incompatible pointer types assigning to &apos;NSArray&lt;NSNumber *&gt; *&apos; from &apos;NSArray&lt;NSString *&gt; *&apos;</string>
+// CHECK:    <key>description</key><string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
 // CHECK:    <key>category</key><string>Core Foundation/Objective-C</string>
 // CHECK:    <key>type</key><string>Generics</string>
-// CHECK:    <key>check_name</key><string>alpha.osx.cocoa.ObjCGenerics</string>
+// CHECK:    <key>check_name</key><string>core.DynamicTypePropagation</string>
 // CHECK:   <key>issue_context_kind</key><string>function</string>
 // CHECK:   <key>issue_context</key><string>incompatibleTypesErasedReverseConversion</string>
 // CHECK:   <key>issue_hash</key><string>4</string>
@@ -1278,15 +1295,15 @@
 // CHECK:      </array>
 // CHECK:      <key>depth</key><integer>0</integer>
 // CHECK:      <key>extended_message</key>
-// CHECK:      <string>Incompatible pointer types assigning to &apos;NSString *&apos; from &apos;NSNumber *&apos;</string>
+// CHECK:      <string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
 // CHECK:      <key>message</key>
-// CHECK:      <string>Incompatible pointer types assigning to &apos;NSString *&apos; from &apos;NSNumber *&apos;</string>
+// CHECK:      <string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
 // CHECK:     </dict>
 // CHECK:    </array>
-// CHECK:    <key>description</key><string>Incompatible pointer types assigning to &apos;NSString *&apos; from &apos;NSNumber *&apos;</string>
+// CHECK:    <key>description</key><string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
 // CHECK:    <key>category</key><string>Core Foundation/Objective-C</string>
 // CHECK:    <key>type</key><string>Generics</string>
-// CHECK:    <key>check_name</key><string>alpha.osx.cocoa.ObjCGenerics</string>
+// CHECK:    <key>check_name</key><string>core.DynamicTypePropagation</string>
 // CHECK:   <key>issue_context_kind</key><string>function</string>
 // CHECK:   <key>issue_context</key><string>idErasedIncompatibleTypesReverseConversion</string>
 // CHECK:   <key>issue_hash</key><string>2</string>
@@ -1422,15 +1439,15 @@
 // CHECK:      </array>
 // CHECK:      <key>depth</key><integer>0</integer>
 // CHECK:      <key>extended_message</key>
-// CHECK:      <string>Incompatible pointer types assigning to &apos;NSArray&lt;NSNumber *&gt; *&apos; from &apos;NSArray&lt;NSString *&gt; *&apos;</string>
+// CHECK:      <string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
 // CHECK:      <key>message</key>
-// CHECK:      <string>Incompatible pointer types assigning to &apos;NSArray&lt;NSNumber *&gt; *&apos; from &apos;NSArray&lt;NSString *&gt; *&apos;</string>
+// CHECK:      <string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
 // CHECK:     </dict>
 // CHECK:    </array>
-// CHECK:    <key>description</key><string>Incompatible pointer types assigning to &apos;NSArray&lt;NSNumber *&gt; *&apos; from &apos;NSArray&lt;NSString *&gt; *&apos;</string>
+// CHECK:    <key>description</key><string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
 // CHECK:    <key>category</key><string>Core Foundation/Objective-C</string>
 // CHECK:    <key>type</key><string>Generics</string>
-// CHECK:    <key>check_name</key><string>alpha.osx.cocoa.ObjCGenerics</string>
+// CHECK:    <key>check_name</key><string>core.DynamicTypePropagation</string>
 // CHECK:   <key>issue_context_kind</key><string>function</string>
 // CHECK:   <key>issue_context</key><string>idErasedIncompatibleTypesReverseConversion</string>
 // CHECK:   <key>issue_hash</key><string>4</string>
@@ -1566,15 +1583,15 @@
 // CHECK:      </array>
 // CHECK:      <key>depth</key><integer>0</integer>
 // CHECK:      <key>extended_message</key>
-// CHECK:      <string>Incompatible pointer types assigning to &apos;NSArray&lt;NSNumber *&gt; *&apos; from &apos;NSArray&lt;NSString *&gt; *&apos;</string>
+// CHECK:      <string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
 // CHECK:      <key>message</key>
-// CHECK:      <string>Incompatible pointer types assigning to &apos;NSArray&lt;NSNumber *&gt; *&apos; from &apos;NSArray&lt;NSString *&gt; *&apos;</string>
+// CHECK:      <string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
 // CHECK:     </dict>
 // CHECK:    </array>
-// CHECK:    <key>description</key><string>Incompatible pointer types assigning to &apos;NSArray&lt;NSNumber *&gt; *&apos; from &apos;NSArray&lt;NSString *&gt; *&apos;</string>
+// CHECK:    <key>description</key><string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
 // CHECK:    <key>category</key><string>Core Foundation/Objective-C</string>
 // CHECK:    <key>type</key><string>Generics</string>
-// CHECK:    <key>check_name</key><string>alpha.osx.cocoa.ObjCGenerics</string>
+// CHECK:    <key>check_name</key><string>core.DynamicTypePropagation</string>
 // CHECK:   <key>issue_context_kind</key><string>function</string>
 // CHECK:   <key>issue_context</key><string>idErasedIncompatibleTypes</string>
 // CHECK:   <key>issue_hash</key><string>2</string>
@@ -1676,15 +1693,15 @@
 // CHECK:      </array>
 // CHECK:      <key>depth</key><integer>0</integer>
 // CHECK:      <key>extended_message</key>
-// CHECK:      <string>Incompatible pointer types assigning to &apos;NSString *&apos; from &apos;NSNumber *&apos;</string>
+// CHECK:      <string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
 // CHECK:      <key>message</key>
-// CHECK:      <string>Incompatible pointer types assigning to &apos;NSString *&apos; from &apos;NSNumber *&apos;</string>
+// CHECK:      <string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
 // CHECK:     </dict>
 // CHECK:    </array>
-// CHECK:    <key>description</key><string>Incompatible pointer types assigning to &apos;NSString *&apos; from &apos;NSNumber *&apos;</string>
+// CHECK:    <key>description</key><string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
 // CHECK:    <key>category</key><string>Core Foundation/Objective-C</string>
 // CHECK:    <key>type</key><string>Generics</string>
-// CHECK:    <key>check_name</key><string>alpha.osx.cocoa.ObjCGenerics</string>
+// CHECK:    <key>check_name</key><string>core.DynamicTypePropagation</string>
 // CHECK:   <key>issue_context_kind</key><string>function</string>
 // CHECK:   <key>issue_context</key><string>idErasedIncompatibleTypes</string>
 // CHECK:   <key>issue_hash</key><string>3</string>
@@ -1820,15 +1837,15 @@
 // CHECK:      </array>
 // CHECK:      <key>depth</key><integer>0</integer>
 // CHECK:      <key>extended_message</key>
-// CHECK:      <string>Incompatible pointer types assigning to &apos;NSArray&lt;NSNumber *&gt; *&apos; from &apos;NSArray&lt;NSString *&gt; *&apos;</string>
+// CHECK:      <string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
 // CHECK:      <key>message</key>
-// CHECK:      <string>Incompatible pointer types assigning to &apos;NSArray&lt;NSNumber *&gt; *&apos; from &apos;NSArray&lt;NSString *&gt; *&apos;</string>
+// CHECK:      <string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
 // CHECK:     </dict>
 // CHECK:    </array>
-// CHECK:    <key>description</key><string>Incompatible pointer types assigning to &apos;NSArray&lt;NSNumber *&gt; *&apos; from &apos;NSArray&lt;NSString *&gt; *&apos;</string>
+// CHECK:    <key>description</key><string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
 // CHECK:    <key>category</key><string>Core Foundation/Objective-C</string>
 // CHECK:    <key>type</key><string>Generics</string>
-// CHECK:    <key>check_name</key><string>alpha.osx.cocoa.ObjCGenerics</string>
+// CHECK:    <key>check_name</key><string>core.DynamicTypePropagation</string>
 // CHECK:   <key>issue_context_kind</key><string>function</string>
 // CHECK:   <key>issue_context</key><string>idErasedIncompatibleTypes</string>
 // CHECK:   <key>issue_hash</key><string>5</string>
@@ -1998,15 +2015,15 @@
 // CHECK:      </array>
 // CHECK:      <key>depth</key><integer>0</integer>
 // CHECK:      <key>extended_message</key>
-// CHECK:      <string>Incompatible pointer types assigning to &apos;NSMutableString *&apos; from &apos;NSString *&apos;</string>
+// CHECK:      <string>Conversion from value of type &apos;NSString *&apos; to incompatible type &apos;NSMutableString *&apos;</string>
 // CHECK:      <key>message</key>
-// CHECK:      <string>Incompatible pointer types assigning to &apos;NSMutableString *&apos; from &apos;NSString *&apos;</string>
+// CHECK:      <string>Conversion from value of type &apos;NSString *&apos; to incompatible type &apos;NSMutableString *&apos;</string>
 // CHECK:     </dict>
 // CHECK:    </array>
-// CHECK:    <key>description</key><string>Incompatible pointer types assigning to &apos;NSMutableString *&apos; from &apos;NSString *&apos;</string>
+// CHECK:    <key>description</key><string>Conversion from value of type &apos;NSString *&apos; to incompatible type &apos;NSMutableString *&apos;</string>
 // CHECK:    <key>category</key><string>Core Foundation/Objective-C</string>
 // CHECK:    <key>type</key><string>Generics</string>
-// CHECK:    <key>check_name</key><string>alpha.osx.cocoa.ObjCGenerics</string>
+// CHECK:    <key>check_name</key><string>core.DynamicTypePropagation</string>
 // CHECK:   <key>issue_context_kind</key><string>function</string>
 // CHECK:   <key>issue_context</key><string>pathSensitiveInference</string>
 // CHECK:   <key>issue_hash</key><string>8</string>
@@ -2142,15 +2159,15 @@
 // CHECK:      </array>
 // CHECK:      <key>depth</key><integer>0</integer>
 // CHECK:      <key>extended_message</key>
-// CHECK:      <string>Incompatible pointer types assigning to &apos;NSArray&lt;NSNumber *&gt; *&apos; from &apos;MutableArray&lt;NSString *&gt; *&apos;</string>
+// CHECK:      <string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
 // CHECK:      <key>message</key>
-// CHECK:      <string>Incompatible pointer types assigning to &apos;NSArray&lt;NSNumber *&gt; *&apos; from &apos;MutableArray&lt;NSString *&gt; *&apos;</string>
+// CHECK:      <string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
 // CHECK:     </dict>
 // CHECK:    </array>
-// CHECK:    <key>description</key><string>Incompatible pointer types assigning to &apos;NSArray&lt;NSNumber *&gt; *&apos; from &apos;MutableArray&lt;NSString *&gt; *&apos;</string>
+// CHECK:    <key>description</key><string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
 // CHECK:    <key>category</key><string>Core Foundation/Objective-C</string>
 // CHECK:    <key>type</key><string>Generics</string>
-// CHECK:    <key>check_name</key><string>alpha.osx.cocoa.ObjCGenerics</string>
+// CHECK:    <key>check_name</key><string>core.DynamicTypePropagation</string>
 // CHECK:   <key>issue_context_kind</key><string>function</string>
 // CHECK:   <key>issue_context</key><string>verifyAPIusage</string>
 // CHECK:   <key>issue_hash</key><string>2</string>
@@ -2252,15 +2269,15 @@
 // CHECK:      </array>
 // CHECK:      <key>depth</key><integer>0</integer>
 // CHECK:      <key>extended_message</key>
-// CHECK:      <string>Incompatible pointer types assigning to &apos;NSMutableString *&apos; from &apos;NSString *&apos;</string>
+// CHECK:      <string>Conversion from value of type &apos;NSString *&apos; to incompatible type &apos;NSMutableString *&apos;</string>
 // CHECK:      <key>message</key>
-// CHECK:      <string>Incompatible pointer types assigning to &apos;NSMutableString *&apos; from &apos;NSString *&apos;</string>
+// CHECK:      <string>Conversion from value of type &apos;NSString *&apos; to incompatible type &apos;NSMutableString *&apos;</string>
 // CHECK:     </dict>
 // CHECK:    </array>
-// CHECK:    <key>description</key><string>Incompatible pointer types assigning to &apos;NSMutableString *&apos; from &apos;NSString *&apos;</string>
+// CHECK:    <key>description</key><string>Conversion from value of type &apos;NSString *&apos; to incompatible type &apos;NSMutableString *&apos;</string>
 // CHECK:    <key>category</key><string>Core Foundation/Objective-C</string>
 // CHECK:    <key>type</key><string>Generics</string>
-// CHECK:    <key>check_name</key><string>alpha.osx.cocoa.ObjCGenerics</string>
+// CHECK:    <key>check_name</key><string>core.DynamicTypePropagation</string>
 // CHECK:   <key>issue_context_kind</key><string>function</string>
 // CHECK:   <key>issue_context</key><string>trustExplicitCasts</string>
 // CHECK:   <key>issue_hash</key><string>2</string>
@@ -2430,15 +2447,15 @@
 // CHECK:      </array>
 // CHECK:      <key>depth</key><integer>0</integer>
 // CHECK:      <key>extended_message</key>
-// CHECK:      <string>Incompatible pointer types assigning to &apos;MutableArray&lt;NSNumber *&gt; *&apos; from &apos;MutableArray&lt;NSString *&gt; *&apos;</string>
+// CHECK:      <string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSNumber *&gt; *&apos;</string>
 // CHECK:      <key>message</key>
-// CHECK:      <string>Incompatible pointer types assigning to &apos;MutableArray&lt;NSNumber *&gt; *&apos; from &apos;MutableArray&lt;NSString *&gt; *&apos;</string>
+// CHECK:      <string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSNumber *&gt; *&apos;</string>
 // CHECK:     </dict>
 // CHECK:    </array>
-// CHECK:    <key>description</key><string>Incompatible pointer types assigning to &apos;MutableArray&lt;NSNumber *&gt; *&apos; from &apos;MutableArray&lt;NSString *&gt; *&apos;</string>
+// CHECK:    <key>description</key><string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSNumber *&gt; *&apos;</string>
 // CHECK:    <key>category</key><string>Core Foundation/Objective-C</string>
 // CHECK:    <key>type</key><string>Generics</string>
-// CHECK:    <key>check_name</key><string>alpha.osx.cocoa.ObjCGenerics</string>
+// CHECK:    <key>check_name</key><string>core.DynamicTypePropagation</string>
 // CHECK:   <key>issue_context_kind</key><string>function</string>
 // CHECK:   <key>issue_context</key><string>subtypeOfGeneric</string>
 // CHECK:   <key>issue_hash</key><string>3</string>
@@ -2540,15 +2557,15 @@
 // CHECK:      </array>
 // CHECK:      <key>depth</key><integer>0</integer>
 // CHECK:      <key>extended_message</key>
-// CHECK:      <string>Incompatible pointer types assigning to &apos;NSString *&apos; from &apos;NSNumber *&apos;</string>
+// CHECK:      <string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
 // CHECK:      <key>message</key>
-// CHECK:      <string>Incompatible pointer types assigning to &apos;NSString *&apos; from &apos;NSNumber *&apos;</string>
+// CHECK:      <string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
 // CHECK:     </dict>
 // CHECK:    </array>
-// CHECK:    <key>description</key><string>Incompatible pointer types assigning to &apos;NSString *&apos; from &apos;NSNumber *&apos;</string>
+// CHECK:    <key>description</key><string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
 // CHECK:    <key>category</key><string>Core Foundation/Objective-C</string>
 // CHECK:    <key>type</key><string>Generics</string>
-// CHECK:    <key>check_name</key><string>alpha.osx.cocoa.ObjCGenerics</string>
+// CHECK:    <key>check_name</key><string>core.DynamicTypePropagation</string>
 // CHECK:   <key>issue_context_kind</key><string>function</string>
 // CHECK:   <key>issue_context</key><string>genericSubtypeOfGeneric</string>
 // CHECK:   <key>issue_hash</key><string>3</string>
@@ -2684,15 +2701,15 @@
 // CHECK:      </array>
 // CHECK:      <key>depth</key><integer>0</integer>
 // CHECK:      <key>extended_message</key>
-// CHECK:      <string>Incompatible pointer types assigning to &apos;MutableArray&lt;NSNumber *&gt; *&apos; from &apos;ExceptionalArray&lt;NSString *&gt; *&apos;</string>
+// CHECK:      <string>Conversion from value of type &apos;ExceptionalArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSNumber *&gt; *&apos;</string>
 // CHECK:      <key>message</key>
-// CHECK:      <string>Incompatible pointer types assigning to &apos;MutableArray&lt;NSNumber *&gt; *&apos; from &apos;ExceptionalArray&lt;NSString *&gt; *&apos;</string>
+// CHECK:      <string>Conversion from value of type &apos;ExceptionalArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSNumber *&gt; *&apos;</string>
 // CHECK:     </dict>
 // CHECK:    </array>
-// CHECK:    <key>description</key><string>Incompatible pointer types assigning to &apos;MutableArray&lt;NSNumber *&gt; *&apos; from &apos;ExceptionalArray&lt;NSString *&gt; *&apos;</string>
+// CHECK:    <key>description</key><string>Conversion from value of type &apos;ExceptionalArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSNumber *&gt; *&apos;</string>
 // CHECK:    <key>category</key><string>Core Foundation/Objective-C</string>
 // CHECK:    <key>type</key><string>Generics</string>
-// CHECK:    <key>check_name</key><string>alpha.osx.cocoa.ObjCGenerics</string>
+// CHECK:    <key>check_name</key><string>core.DynamicTypePropagation</string>
 // CHECK:   <key>issue_context_kind</key><string>function</string>
 // CHECK:   <key>issue_context</key><string>genericSubtypeOfGeneric</string>
 // CHECK:   <key>issue_hash</key><string>5</string>
@@ -2794,15 +2811,15 @@
 // CHECK:      </array>
 // CHECK:      <key>depth</key><integer>0</integer>
 // CHECK:      <key>extended_message</key>
-// CHECK:      <string>Incompatible pointer types assigning to &apos;NSString *&apos; from &apos;NSNumber *&apos;</string>
+// CHECK:      <string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
 // CHECK:      <key>message</key>
-// CHECK:      <string>Incompatible pointer types assigning to &apos;NSString *&apos; from &apos;NSNumber *&apos;</string>
+// CHECK:      <string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
 // CHECK:     </dict>
 // CHECK:    </array>
-// CHECK:    <key>description</key><string>Incompatible pointer types assigning to &apos;NSString *&apos; from &apos;NSNumber *&apos;</string>
+// CHECK:    <key>description</key><string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
 // CHECK:    <key>category</key><string>Core Foundation/Objective-C</string>
 // CHECK:    <key>type</key><string>Generics</string>
-// CHECK:    <key>check_name</key><string>alpha.osx.cocoa.ObjCGenerics</string>
+// CHECK:    <key>check_name</key><string>core.DynamicTypePropagation</string>
 // CHECK:   <key>issue_context_kind</key><string>function</string>
 // CHECK:   <key>issue_context</key><string>genericSubtypeOfGenericReverse</string>
 // CHECK:   <key>issue_hash</key><string>3</string>
@@ -2938,15 +2955,15 @@
 // CHECK:      </array>
 // CHECK:      <key>depth</key><integer>0</integer>
 // CHECK:      <key>extended_message</key>
-// CHECK:      <string>Incompatible pointer types assigning to &apos;MutableArray&lt;NSNumber *&gt; *&apos; from &apos;ExceptionalArray&lt;NSString *&gt; *&apos;</string>
+// CHECK:      <string>Conversion from value of type &apos;ExceptionalArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSNumber *&gt; *&apos;</string>
 // CHECK:      <key>message</key>
-// CHECK:      <string>Incompatible pointer types assigning to &apos;MutableArray&lt;NSNumber *&gt; *&apos; from &apos;ExceptionalArray&lt;NSString *&gt; *&apos;</string>
+// CHECK:      <string>Conversion from value of type &apos;ExceptionalArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSNumber *&gt; *&apos;</string>
 // CHECK:     </dict>
 // CHECK:    </array>
-// CHECK:    <key>description</key><string>Incompatible pointer types assigning to &apos;MutableArray&lt;NSNumber *&gt; *&apos; from &apos;ExceptionalArray&lt;NSString *&gt; *&apos;</string>
+// CHECK:    <key>description</key><string>Conversion from value of type &apos;ExceptionalArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSNumber *&gt; *&apos;</string>
 // CHECK:    <key>category</key><string>Core Foundation/Objective-C</string>
 // CHECK:    <key>type</key><string>Generics</string>
-// CHECK:    <key>check_name</key><string>alpha.osx.cocoa.ObjCGenerics</string>
+// CHECK:    <key>check_name</key><string>core.DynamicTypePropagation</string>
 // CHECK:   <key>issue_context_kind</key><string>function</string>
 // CHECK:   <key>issue_context</key><string>genericSubtypeOfGenericReverse</string>
 // CHECK:   <key>issue_hash</key><string>5</string>
@@ -3082,15 +3099,15 @@
 // CHECK:      </array>
 // CHECK:      <key>depth</key><integer>0</integer>
 // CHECK:      <key>extended_message</key>
-// CHECK:      <string>Incompatible pointer types assigning to &apos;MutableArray&lt;NSMutableString *&gt; *&apos; from &apos;MutableArray&lt;NSString *&gt; *&apos;</string>
+// CHECK:      <string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
 // CHECK:      <key>message</key>
-// CHECK:      <string>Incompatible pointer types assigning to &apos;MutableArray&lt;NSMutableString *&gt; *&apos; from &apos;MutableArray&lt;NSString *&gt; *&apos;</string>
+// CHECK:      <string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
 // CHECK:     </dict>
 // CHECK:    </array>
-// CHECK:    <key>description</key><string>Incompatible pointer types assigning to &apos;MutableArray&lt;NSMutableString *&gt; *&apos; from &apos;MutableArray&lt;NSString *&gt; *&apos;</string>
+// CHECK:    <key>description</key><string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
 // CHECK:    <key>category</key><string>Core Foundation/Objective-C</string>
 // CHECK:    <key>type</key><string>Generics</string>
-// CHECK:    <key>check_name</key><string>alpha.osx.cocoa.ObjCGenerics</string>
+// CHECK:    <key>check_name</key><string>core.DynamicTypePropagation</string>
 // CHECK:   <key>issue_context_kind</key><string>function</string>
 // CHECK:   <key>issue_context</key><string>inferenceFromAPI</string>
 // CHECK:   <key>issue_hash</key><string>4</string>
@@ -3226,15 +3243,15 @@
 // CHECK:      </array>
 // CHECK:      <key>depth</key><integer>0</integer>
 // CHECK:      <key>extended_message</key>
-// CHECK:      <string>Incompatible pointer types assigning to &apos;MutableArray&lt;NSString *&gt; *&apos; from &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
+// CHECK:      <string>Conversion from value of type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSString *&gt; *&apos;</string>
 // CHECK:      <key>message</key>
-// CHECK:      <string>Incompatible pointer types assigning to &apos;MutableArray&lt;NSString *&gt; *&apos; from &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
+// CHECK:      <string>Conversion from value of type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSString *&gt; *&apos;</string>
 // CHECK:     </dict>
 // CHECK:    </array>
-// CHECK:    <key>description</key><string>Incompatible pointer types assigning to &apos;MutableArray&lt;NSString *&gt; *&apos; from &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
+// CHECK:    <key>description</key><string>Conversion from value of type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSString *&gt; *&apos;</string>
 // CHECK:    <key>category</key><string>Core Foundation/Objective-C</string>
 // CHECK:    <key>type</key><string>Generics</string>
-// CHECK:    <key>check_name</key><string>alpha.osx.cocoa.ObjCGenerics</string>
+// CHECK:    <key>check_name</key><string>core.DynamicTypePropagation</string>
 // CHECK:   <key>issue_context_kind</key><string>function</string>
 // CHECK:   <key>issue_context</key><string>inferenceFromAPI2</string>
 // CHECK:   <key>issue_hash</key><string>2</string>
@@ -3370,15 +3387,15 @@
 // CHECK:      </array>
 // CHECK:      <key>depth</key><integer>0</integer>
 // CHECK:      <key>extended_message</key>
-// CHECK:      <string>Incompatible pointer types assigning to &apos;MutableArray&lt;NSString *&gt; *&apos; from &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
+// CHECK:      <string>Conversion from value of type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSString *&gt; *&apos;</string>
 // CHECK:      <key>message</key>
-// CHECK:      <string>Incompatible pointer types assigning to &apos;MutableArray&lt;NSString *&gt; *&apos; from &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
+// CHECK:      <string>Conversion from value of type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSString *&gt; *&apos;</string>
 // CHECK:     </dict>
 // CHECK:    </array>
-// CHECK:    <key>description</key><string>Incompatible pointer types assigning to &apos;MutableArray&lt;NSString *&gt; *&apos; from &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
+// CHECK:    <key>description</key><string>Conversion from value of type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSString *&gt; *&apos;</string>
 // CHECK:    <key>category</key><string>Core Foundation/Objective-C</string>
 // CHECK:    <key>type</key><string>Generics</string>
-// CHECK:    <key>check_name</key><string>alpha.osx.cocoa.ObjCGenerics</string>
+// CHECK:    <key>check_name</key><string>core.DynamicTypePropagation</string>
 // CHECK:   <key>issue_context_kind</key><string>function</string>
 // CHECK:   <key>issue_context</key><string>inferenceFromAPIWithLegacyTypes</string>
 // CHECK:   <key>issue_hash</key><string>2</string>
@@ -3514,15 +3531,15 @@
 // CHECK:      </array>
 // CHECK:      <key>depth</key><integer>0</integer>
 // CHECK:      <key>extended_message</key>
-// CHECK:      <string>Incompatible pointer types assigning to &apos;MutableArray&lt;NSMutableString *&gt; *&apos; from &apos;MutableArray&lt;NSString *&gt; *&apos;</string>
+// CHECK:      <string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
 // CHECK:      <key>message</key>
-// CHECK:      <string>Incompatible pointer types assigning to &apos;MutableArray&lt;NSMutableString *&gt; *&apos; from &apos;MutableArray&lt;NSString *&gt; *&apos;</string>
+// CHECK:      <string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
 // CHECK:     </dict>
 // CHECK:    </array>
-// CHECK:    <key>description</key><string>Incompatible pointer types assigning to &apos;MutableArray&lt;NSMutableString *&gt; *&apos; from &apos;MutableArray&lt;NSString *&gt; *&apos;</string>
+// CHECK:    <key>description</key><string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
 // CHECK:    <key>category</key><string>Core Foundation/Objective-C</string>
 // CHECK:    <key>type</key><string>Generics</string>
-// CHECK:    <key>check_name</key><string>alpha.osx.cocoa.ObjCGenerics</string>
+// CHECK:    <key>check_name</key><string>core.DynamicTypePropagation</string>
 // CHECK:   <key>issue_context_kind</key><string>function</string>
 // CHECK:   <key>issue_context</key><string>inferenceFromAPIWithLegacyTypes2</string>
 // CHECK:   <key>issue_hash</key><string>2</string>
@@ -3541,7 +3558,7 @@
 // CHECK:      <key>location</key>
 // CHECK:      <dict>
 // CHECK:       <key>line</key><integer>199</integer>
-// CHECK:       <key>col</key><integer>20</integer>
+// CHECK:       <key>col</key><integer>27</integer>
 // CHECK:       <key>file</key><integer>0</integer>
 // CHECK:      </dict>
 // CHECK:      <key>ranges</key>
@@ -3549,21 +3566,21 @@
 // CHECK:        <array>
 // CHECK:         <dict>
 // CHECK:          <key>line</key><integer>199</integer>
-// CHECK:          <key>col</key><integer>20</integer>
+// CHECK:          <key>col</key><integer>27</integer>
 // CHECK:          <key>file</key><integer>0</integer>
 // CHECK:         </dict>
 // CHECK:         <dict>
 // CHECK:          <key>line</key><integer>199</integer>
-// CHECK:          <key>col</key><integer>20</integer>
+// CHECK:          <key>col</key><integer>27</integer>
 // CHECK:          <key>file</key><integer>0</integer>
 // CHECK:         </dict>
 // CHECK:        </array>
 // CHECK:      </array>
 // CHECK:      <key>depth</key><integer>0</integer>
 // CHECK:      <key>extended_message</key>
-// CHECK:      <string>Type &apos;MutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;BuggyMutableArray&lt;NSMutableString *&gt; *&apos; to &apos;MutableArray&lt;NSString *&gt; *&apos;)</string>
+// CHECK:      <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;__kindof NSArray&lt;NSString *&gt; *&apos; to &apos;LegacyMutableArray *&apos;)</string>
 // CHECK:      <key>message</key>
-// CHECK:      <string>Type &apos;MutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;BuggyMutableArray&lt;NSMutableString *&gt; *&apos; to &apos;MutableArray&lt;NSString *&gt; *&apos;)</string>
+// CHECK:      <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;__kindof NSArray&lt;NSString *&gt; *&apos; to &apos;LegacyMutableArray *&apos;)</string>
 // CHECK:     </dict>
 // CHECK:     <dict>
 // CHECK:      <key>kind</key><string>control</string>
@@ -3579,7 +3596,7 @@
 // CHECK:           </dict>
 // CHECK:           <dict>
 // CHECK:            <key>line</key><integer>199</integer>
-// CHECK:            <key>col</key><integer>18</integer>
+// CHECK:            <key>col</key><integer>20</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
 // CHECK:          </array>
@@ -3592,7 +3609,7 @@
 // CHECK:           </dict>
 // CHECK:           <dict>
 // CHECK:            <key>line</key><integer>200</integer>
-// CHECK:            <key>col</key><integer>25</integer>
+// CHECK:            <key>col</key><integer>18</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
 // CHECK:          </array>
@@ -3600,6 +3617,35 @@
 // CHECK:       </array>
 // CHECK:     </dict>
 // CHECK:     <dict>
+// CHECK:      <key>kind</key><string>event</string>
+// CHECK:      <key>location</key>
+// CHECK:      <dict>
+// CHECK:       <key>line</key><integer>200</integer>
+// CHECK:       <key>col</key><integer>20</integer>
+// CHECK:       <key>file</key><integer>0</integer>
+// CHECK:      </dict>
+// CHECK:      <key>ranges</key>
+// CHECK:      <array>
+// CHECK:        <array>
+// CHECK:         <dict>
+// CHECK:          <key>line</key><integer>200</integer>
+// CHECK:          <key>col</key><integer>20</integer>
+// CHECK:          <key>file</key><integer>0</integer>
+// CHECK:         </dict>
+// CHECK:         <dict>
+// CHECK:          <key>line</key><integer>200</integer>
+// CHECK:          <key>col</key><integer>20</integer>
+// CHECK:          <key>file</key><integer>0</integer>
+// CHECK:         </dict>
+// CHECK:        </array>
+// CHECK:      </array>
+// CHECK:      <key>depth</key><integer>0</integer>
+// CHECK:      <key>extended_message</key>
+// CHECK:      <string>Type &apos;MutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;LegacyMutableArray *&apos; to &apos;MutableArray&lt;NSString *&gt; *&apos;)</string>
+// CHECK:      <key>message</key>
+// CHECK:      <string>Type &apos;MutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;LegacyMutableArray *&apos; to &apos;MutableArray&lt;NSString *&gt; *&apos;)</string>
+// CHECK:     </dict>
+// CHECK:     <dict>
 // CHECK:      <key>kind</key><string>control</string>
 // CHECK:      <key>edges</key>
 // CHECK:       <array>
@@ -3613,6 +3659,40 @@
 // CHECK:           </dict>
 // CHECK:           <dict>
 // CHECK:            <key>line</key><integer>200</integer>
+// CHECK:            <key>col</key><integer>18</integer>
+// CHECK:            <key>file</key><integer>0</integer>
+// CHECK:           </dict>
+// CHECK:          </array>
+// CHECK:         <key>end</key>
+// CHECK:          <array>
+// CHECK:           <dict>
+// CHECK:            <key>line</key><integer>201</integer>
+// CHECK:            <key>col</key><integer>3</integer>
+// CHECK:            <key>file</key><integer>0</integer>
+// CHECK:           </dict>
+// CHECK:           <dict>
+// CHECK:            <key>line</key><integer>201</integer>
+// CHECK:            <key>col</key><integer>25</integer>
+// CHECK:            <key>file</key><integer>0</integer>
+// CHECK:           </dict>
+// CHECK:          </array>
+// CHECK:        </dict>
+// CHECK:       </array>
+// CHECK:     </dict>
+// CHECK:     <dict>
+// CHECK:      <key>kind</key><string>control</string>
+// CHECK:      <key>edges</key>
+// CHECK:       <array>
+// CHECK:        <dict>
+// CHECK:         <key>start</key>
+// CHECK:          <array>
+// CHECK:           <dict>
+// CHECK:            <key>line</key><integer>201</integer>
+// CHECK:            <key>col</key><integer>3</integer>
+// CHECK:            <key>file</key><integer>0</integer>
+// CHECK:           </dict>
+// CHECK:           <dict>
+// CHECK:            <key>line</key><integer>201</integer>
 // CHECK:            <key>col</key><integer>25</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
@@ -3620,12 +3700,12 @@
 // CHECK:         <key>end</key>
 // CHECK:          <array>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>200</integer>
+// CHECK:            <key>line</key><integer>201</integer>
 // CHECK:            <key>col</key><integer>27</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>200</integer>
+// CHECK:            <key>line</key><integer>201</integer>
 // CHECK:            <key>col</key><integer>27</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
@@ -3637,7 +3717,7 @@
 // CHECK:      <key>kind</key><string>event</string>
 // CHECK:      <key>location</key>
 // CHECK:      <dict>
-// CHECK:       <key>line</key><integer>200</integer>
+// CHECK:       <key>line</key><integer>201</integer>
 // CHECK:       <key>col</key><integer>27</integer>
 // CHECK:       <key>file</key><integer>0</integer>
 // CHECK:      </dict>
@@ -3645,12 +3725,12 @@
 // CHECK:      <array>
 // CHECK:        <array>
 // CHECK:         <dict>
-// CHECK:          <key>line</key><integer>200</integer>
+// CHECK:          <key>line</key><integer>201</integer>
 // CHECK:          <key>col</key><integer>27</integer>
 // CHECK:          <key>file</key><integer>0</integer>
 // CHECK:         </dict>
 // CHECK:         <dict>
-// CHECK:          <key>line</key><integer>200</integer>
+// CHECK:          <key>line</key><integer>201</integer>
 // CHECK:          <key>col</key><integer>27</integer>
 // CHECK:          <key>file</key><integer>0</integer>
 // CHECK:         </dict>
@@ -3658,21 +3738,21 @@
 // CHECK:      </array>
 // CHECK:      <key>depth</key><integer>0</integer>
 // CHECK:      <key>extended_message</key>
-// CHECK:      <string>Incompatible pointer types assigning to &apos;MutableArray&lt;NSMutableString *&gt; *&apos; from &apos;MutableArray&lt;NSString *&gt; *&apos;</string>
+// CHECK:      <string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
 // CHECK:      <key>message</key>
-// CHECK:      <string>Incompatible pointer types assigning to &apos;MutableArray&lt;NSMutableString *&gt; *&apos; from &apos;MutableArray&lt;NSString *&gt; *&apos;</string>
+// CHECK:      <string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
 // CHECK:     </dict>
 // CHECK:    </array>
-// CHECK:    <key>description</key><string>Incompatible pointer types assigning to &apos;MutableArray&lt;NSMutableString *&gt; *&apos; from &apos;MutableArray&lt;NSString *&gt; *&apos;</string>
+// CHECK:    <key>description</key><string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
 // CHECK:    <key>category</key><string>Core Foundation/Objective-C</string>
 // CHECK:    <key>type</key><string>Generics</string>
-// CHECK:    <key>check_name</key><string>alpha.osx.cocoa.ObjCGenerics</string>
+// CHECK:    <key>check_name</key><string>core.DynamicTypePropagation</string>
 // CHECK:   <key>issue_context_kind</key><string>function</string>
-// CHECK:   <key>issue_context</key><string>inferenceFromAPIWithBuggyTypes</string>
-// CHECK:   <key>issue_hash</key><string>2</string>
+// CHECK:   <key>issue_context</key><string>inferenceFromAPIWithLegacyTypes3</string>
+// CHECK:   <key>issue_hash</key><string>3</string>
 // CHECK:   <key>location</key>
 // CHECK:   <dict>
-// CHECK:    <key>line</key><integer>200</integer>
+// CHECK:    <key>line</key><integer>201</integer>
 // CHECK:    <key>col</key><integer>27</integer>
 // CHECK:    <key>file</key><integer>0</integer>
 // CHECK:   </dict>
@@ -3684,30 +3764,30 @@
 // CHECK:      <key>kind</key><string>event</string>
 // CHECK:      <key>location</key>
 // CHECK:      <dict>
-// CHECK:       <key>line</key><integer>204</integer>
-// CHECK:       <key>col</key><integer>27</integer>
+// CHECK:       <key>line</key><integer>205</integer>
+// CHECK:       <key>col</key><integer>20</integer>
 // CHECK:       <key>file</key><integer>0</integer>
 // CHECK:      </dict>
 // CHECK:      <key>ranges</key>
 // CHECK:      <array>
 // CHECK:        <array>
 // CHECK:         <dict>
-// CHECK:          <key>line</key><integer>204</integer>
-// CHECK:          <key>col</key><integer>27</integer>
+// CHECK:          <key>line</key><integer>205</integer>
+// CHECK:          <key>col</key><integer>20</integer>
 // CHECK:          <key>file</key><integer>0</integer>
 // CHECK:         </dict>
 // CHECK:         <dict>
-// CHECK:          <key>line</key><integer>204</integer>
-// CHECK:          <key>col</key><integer>27</integer>
+// CHECK:          <key>line</key><integer>205</integer>
+// CHECK:          <key>col</key><integer>20</integer>
 // CHECK:          <key>file</key><integer>0</integer>
 // CHECK:         </dict>
 // CHECK:        </array>
 // CHECK:      </array>
 // CHECK:      <key>depth</key><integer>0</integer>
 // CHECK:      <key>extended_message</key>
-// CHECK:      <string>Type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; is inferred from implicit cast (from &apos;BuggySpecialMutableArray&lt;NSMutableString *&gt; *&apos; to &apos;MutableArray&lt;NSMutableString *&gt; *&apos;)</string>
+// CHECK:      <string>Type &apos;MutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;BuggyMutableArray&lt;NSMutableString *&gt; *&apos; to &apos;MutableArray&lt;NSString *&gt; *&apos;)</string>
 // CHECK:      <key>message</key>
-// CHECK:      <string>Type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; is inferred from implicit cast (from &apos;BuggySpecialMutableArray&lt;NSMutableString *&gt; *&apos; to &apos;MutableArray&lt;NSMutableString *&gt; *&apos;)</string>
+// CHECK:      <string>Type &apos;MutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;BuggyMutableArray&lt;NSMutableString *&gt; *&apos; to &apos;MutableArray&lt;NSString *&gt; *&apos;)</string>
 // CHECK:     </dict>
 // CHECK:     <dict>
 // CHECK:      <key>kind</key><string>control</string>
@@ -3717,26 +3797,26 @@
 // CHECK:         <key>start</key>
 // CHECK:          <array>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>204</integer>
+// CHECK:            <key>line</key><integer>205</integer>
 // CHECK:            <key>col</key><integer>3</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>204</integer>
-// CHECK:            <key>col</key><integer>25</integer>
+// CHECK:            <key>line</key><integer>205</integer>
+// CHECK:            <key>col</key><integer>18</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
 // CHECK:          </array>
 // CHECK:         <key>end</key>
 // CHECK:          <array>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>205</integer>
+// CHECK:            <key>line</key><integer>206</integer>
 // CHECK:            <key>col</key><integer>3</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>205</integer>
-// CHECK:            <key>col</key><integer>18</integer>
+// CHECK:            <key>line</key><integer>206</integer>
+// CHECK:            <key>col</key><integer>25</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
 // CHECK:          </array>
@@ -3751,26 +3831,26 @@
 // CHECK:         <key>start</key>
 // CHECK:          <array>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>205</integer>
+// CHECK:            <key>line</key><integer>206</integer>
 // CHECK:            <key>col</key><integer>3</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>205</integer>
-// CHECK:            <key>col</key><integer>18</integer>
+// CHECK:            <key>line</key><integer>206</integer>
+// CHECK:            <key>col</key><integer>25</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
 // CHECK:          </array>
 // CHECK:         <key>end</key>
 // CHECK:          <array>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>205</integer>
-// CHECK:            <key>col</key><integer>20</integer>
+// CHECK:            <key>line</key><integer>206</integer>
+// CHECK:            <key>col</key><integer>27</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>205</integer>
-// CHECK:            <key>col</key><integer>20</integer>
+// CHECK:            <key>line</key><integer>206</integer>
+// CHECK:            <key>col</key><integer>27</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
 // CHECK:          </array>
@@ -3781,43 +3861,43 @@
 // CHECK:      <key>kind</key><string>event</string>
 // CHECK:      <key>location</key>
 // CHECK:      <dict>
-// CHECK:       <key>line</key><integer>205</integer>
-// CHECK:       <key>col</key><integer>20</integer>
+// CHECK:       <key>line</key><integer>206</integer>
+// CHECK:       <key>col</key><integer>27</integer>
 // CHECK:       <key>file</key><integer>0</integer>
 // CHECK:      </dict>
 // CHECK:      <key>ranges</key>
 // CHECK:      <array>
 // CHECK:        <array>
 // CHECK:         <dict>
-// CHECK:          <key>line</key><integer>205</integer>
-// CHECK:          <key>col</key><integer>20</integer>
+// CHECK:          <key>line</key><integer>206</integer>
+// CHECK:          <key>col</key><integer>27</integer>
 // CHECK:          <key>file</key><integer>0</integer>
 // CHECK:         </dict>
 // CHECK:         <dict>
-// CHECK:          <key>line</key><integer>205</integer>
-// CHECK:          <key>col</key><integer>20</integer>
+// CHECK:          <key>line</key><integer>206</integer>
+// CHECK:          <key>col</key><integer>27</integer>
 // CHECK:          <key>file</key><integer>0</integer>
 // CHECK:         </dict>
 // CHECK:        </array>
 // CHECK:      </array>
 // CHECK:      <key>depth</key><integer>0</integer>
 // CHECK:      <key>extended_message</key>
-// CHECK:      <string>Incompatible pointer types assigning to &apos;MutableArray&lt;NSString *&gt; *&apos; from &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
+// CHECK:      <string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
 // CHECK:      <key>message</key>
-// CHECK:      <string>Incompatible pointer types assigning to &apos;MutableArray&lt;NSString *&gt; *&apos; from &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
+// CHECK:      <string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
 // CHECK:     </dict>
 // CHECK:    </array>
-// CHECK:    <key>description</key><string>Incompatible pointer types assigning to &apos;MutableArray&lt;NSString *&gt; *&apos; from &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
+// CHECK:    <key>description</key><string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
 // CHECK:    <key>category</key><string>Core Foundation/Objective-C</string>
 // CHECK:    <key>type</key><string>Generics</string>
-// CHECK:    <key>check_name</key><string>alpha.osx.cocoa.ObjCGenerics</string>
+// CHECK:    <key>check_name</key><string>core.DynamicTypePropagation</string>
 // CHECK:   <key>issue_context_kind</key><string>function</string>
-// CHECK:   <key>issue_context</key><string>InferenceFromAPIWithBuggyTypes2</string>
+// CHECK:   <key>issue_context</key><string>inferenceFromAPIWithBuggyTypes</string>
 // CHECK:   <key>issue_hash</key><string>2</string>
 // CHECK:   <key>location</key>
 // CHECK:   <dict>
-// CHECK:    <key>line</key><integer>205</integer>
-// CHECK:    <key>col</key><integer>20</integer>
+// CHECK:    <key>line</key><integer>206</integer>
+// CHECK:    <key>col</key><integer>27</integer>
 // CHECK:    <key>file</key><integer>0</integer>
 // CHECK:   </dict>
 // CHECK:   </dict>
@@ -3828,30 +3908,30 @@
 // CHECK:      <key>kind</key><string>event</string>
 // CHECK:      <key>location</key>
 // CHECK:      <dict>
-// CHECK:       <key>line</key><integer>217</integer>
-// CHECK:       <key>col</key><integer>16</integer>
+// CHECK:       <key>line</key><integer>210</integer>
+// CHECK:       <key>col</key><integer>27</integer>
 // CHECK:       <key>file</key><integer>0</integer>
 // CHECK:      </dict>
 // CHECK:      <key>ranges</key>
 // CHECK:      <array>
 // CHECK:        <array>
 // CHECK:         <dict>
-// CHECK:          <key>line</key><integer>217</integer>
-// CHECK:          <key>col</key><integer>16</integer>
+// CHECK:          <key>line</key><integer>210</integer>
+// CHECK:          <key>col</key><integer>27</integer>
 // CHECK:          <key>file</key><integer>0</integer>
 // CHECK:         </dict>
 // CHECK:         <dict>
-// CHECK:          <key>line</key><integer>217</integer>
-// CHECK:          <key>col</key><integer>16</integer>
+// CHECK:          <key>line</key><integer>210</integer>
+// CHECK:          <key>col</key><integer>27</integer>
 // CHECK:          <key>file</key><integer>0</integer>
 // CHECK:         </dict>
 // CHECK:        </array>
 // CHECK:      </array>
 // CHECK:      <key>depth</key><integer>0</integer>
 // CHECK:      <key>extended_message</key>
-// CHECK:      <string>Type &apos;NSArray&lt;NSNumber *&gt; *&apos; is inferred from implicit cast (from &apos;NSArray&lt;NSNumber *&gt; *&apos; to &apos;NSArray *&apos;)</string>
+// CHECK:      <string>Type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; is inferred from implicit cast (from &apos;BuggySpecialMutableArray&lt;NSMutableString *&gt; *&apos; to &apos;MutableArray&lt;NSMutableString *&gt; *&apos;)</string>
 // CHECK:      <key>message</key>
-// CHECK:      <string>Type &apos;NSArray&lt;NSNumber *&gt; *&apos; is inferred from implicit cast (from &apos;NSArray&lt;NSNumber *&gt; *&apos; to &apos;NSArray *&apos;)</string>
+// CHECK:      <string>Type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; is inferred from implicit cast (from &apos;BuggySpecialMutableArray&lt;NSMutableString *&gt; *&apos; to &apos;MutableArray&lt;NSMutableString *&gt; *&apos;)</string>
 // CHECK:     </dict>
 // CHECK:     <dict>
 // CHECK:      <key>kind</key><string>control</string>
@@ -3861,26 +3941,26 @@
 // CHECK:         <key>start</key>
 // CHECK:          <array>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>217</integer>
+// CHECK:            <key>line</key><integer>210</integer>
 // CHECK:            <key>col</key><integer>3</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>217</integer>
-// CHECK:            <key>col</key><integer>9</integer>
+// CHECK:            <key>line</key><integer>210</integer>
+// CHECK:            <key>col</key><integer>25</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
 // CHECK:          </array>
 // CHECK:         <key>end</key>
 // CHECK:          <array>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>218</integer>
+// CHECK:            <key>line</key><integer>211</integer>
 // CHECK:            <key>col</key><integer>3</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>218</integer>
-// CHECK:            <key>col</key><integer>10</integer>
+// CHECK:            <key>line</key><integer>211</integer>
+// CHECK:            <key>col</key><integer>18</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
 // CHECK:          </array>
@@ -3895,26 +3975,26 @@
 // CHECK:         <key>start</key>
 // CHECK:          <array>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>218</integer>
+// CHECK:            <key>line</key><integer>211</integer>
 // CHECK:            <key>col</key><integer>3</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>218</integer>
-// CHECK:            <key>col</key><integer>10</integer>
+// CHECK:            <key>line</key><integer>211</integer>
+// CHECK:            <key>col</key><integer>18</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
 // CHECK:          </array>
 // CHECK:         <key>end</key>
 // CHECK:          <array>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>218</integer>
-// CHECK:            <key>col</key><integer>19</integer>
+// CHECK:            <key>line</key><integer>211</integer>
+// CHECK:            <key>col</key><integer>20</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>218</integer>
-// CHECK:            <key>col</key><integer>19</integer>
+// CHECK:            <key>line</key><integer>211</integer>
+// CHECK:            <key>col</key><integer>20</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
 // CHECK:          </array>
@@ -3925,43 +4005,43 @@
 // CHECK:      <key>kind</key><string>event</string>
 // CHECK:      <key>location</key>
 // CHECK:      <dict>
-// CHECK:       <key>line</key><integer>218</integer>
-// CHECK:       <key>col</key><integer>19</integer>
+// CHECK:       <key>line</key><integer>211</integer>
+// CHECK:       <key>col</key><integer>20</integer>
 // CHECK:       <key>file</key><integer>0</integer>
 // CHECK:      </dict>
 // CHECK:      <key>ranges</key>
 // CHECK:      <array>
 // CHECK:        <array>
 // CHECK:         <dict>
-// CHECK:          <key>line</key><integer>218</integer>
-// CHECK:          <key>col</key><integer>19</integer>
+// CHECK:          <key>line</key><integer>211</integer>
+// CHECK:          <key>col</key><integer>20</integer>
 // CHECK:          <key>file</key><integer>0</integer>
 // CHECK:         </dict>
 // CHECK:         <dict>
-// CHECK:          <key>line</key><integer>218</integer>
-// CHECK:          <key>col</key><integer>38</integer>
+// CHECK:          <key>line</key><integer>211</integer>
+// CHECK:          <key>col</key><integer>20</integer>
 // CHECK:          <key>file</key><integer>0</integer>
 // CHECK:         </dict>
 // CHECK:        </array>
 // CHECK:      </array>
 // CHECK:      <key>depth</key><integer>0</integer>
 // CHECK:      <key>extended_message</key>
-// CHECK:      <string>Incompatible pointer types assigning to &apos;NSString *&apos; from &apos;NSNumber *&apos;</string>
+// CHECK:      <string>Conversion from value of type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSString *&gt; *&apos;</string>
 // CHECK:      <key>message</key>
-// CHECK:      <string>Incompatible pointer types assigning to &apos;NSString *&apos; from &apos;NSNumber *&apos;</string>
+// CHECK:      <string>Conversion from value of type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSString *&gt; *&apos;</string>
 // CHECK:     </dict>
 // CHECK:    </array>
-// CHECK:    <key>description</key><string>Incompatible pointer types assigning to &apos;NSString *&apos; from &apos;NSNumber *&apos;</string>
+// CHECK:    <key>description</key><string>Conversion from value of type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSString *&gt; *&apos;</string>
 // CHECK:    <key>category</key><string>Core Foundation/Objective-C</string>
 // CHECK:    <key>type</key><string>Generics</string>
-// CHECK:    <key>check_name</key><string>alpha.osx.cocoa.ObjCGenerics</string>
+// CHECK:    <key>check_name</key><string>core.DynamicTypePropagation</string>
 // CHECK:   <key>issue_context_kind</key><string>function</string>
-// CHECK:   <key>issue_context</key><string>workWithProperties</string>
+// CHECK:   <key>issue_context</key><string>InferenceFromAPIWithBuggyTypes2</string>
 // CHECK:   <key>issue_hash</key><string>2</string>
 // CHECK:   <key>location</key>
 // CHECK:   <dict>
-// CHECK:    <key>line</key><integer>218</integer>
-// CHECK:    <key>col</key><integer>19</integer>
+// CHECK:    <key>line</key><integer>211</integer>
+// CHECK:    <key>col</key><integer>20</integer>
 // CHECK:    <key>file</key><integer>0</integer>
 // CHECK:   </dict>
 // CHECK:   </dict>
@@ -3972,30 +4052,30 @@
 // CHECK:      <key>kind</key><string>event</string>
 // CHECK:      <key>location</key>
 // CHECK:      <dict>
-// CHECK:       <key>line</key><integer>217</integer>
-// CHECK:       <key>col</key><integer>16</integer>
+// CHECK:       <key>line</key><integer>215</integer>
+// CHECK:       <key>col</key><integer>10</integer>
 // CHECK:       <key>file</key><integer>0</integer>
 // CHECK:      </dict>
 // CHECK:      <key>ranges</key>
 // CHECK:      <array>
 // CHECK:        <array>
 // CHECK:         <dict>
-// CHECK:          <key>line</key><integer>217</integer>
-// CHECK:          <key>col</key><integer>16</integer>
+// CHECK:          <key>line</key><integer>215</integer>
+// CHECK:          <key>col</key><integer>10</integer>
 // CHECK:          <key>file</key><integer>0</integer>
 // CHECK:         </dict>
 // CHECK:         <dict>
-// CHECK:          <key>line</key><integer>217</integer>
-// CHECK:          <key>col</key><integer>16</integer>
+// CHECK:          <key>line</key><integer>215</integer>
+// CHECK:          <key>col</key><integer>10</integer>
 // CHECK:          <key>file</key><integer>0</integer>
 // CHECK:         </dict>
 // CHECK:        </array>
 // CHECK:      </array>
 // CHECK:      <key>depth</key><integer>0</integer>
 // CHECK:      <key>extended_message</key>
-// CHECK:      <string>Type &apos;NSArray&lt;NSNumber *&gt; *&apos; is inferred from implicit cast (from &apos;NSArray&lt;NSNumber *&gt; *&apos; to &apos;NSArray *&apos;)</string>
+// CHECK:      <string>Type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; is inferred from implicit cast (from &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to &apos;id&apos;)</string>
 // CHECK:      <key>message</key>
-// CHECK:      <string>Type &apos;NSArray&lt;NSNumber *&gt; *&apos; is inferred from implicit cast (from &apos;NSArray&lt;NSNumber *&gt; *&apos; to &apos;NSArray *&apos;)</string>
+// CHECK:      <string>Type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; is inferred from implicit cast (from &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to &apos;id&apos;)</string>
 // CHECK:     </dict>
 // CHECK:     <dict>
 // CHECK:      <key>kind</key><string>control</string>
@@ -4005,26 +4085,26 @@
 // CHECK:         <key>start</key>
 // CHECK:          <array>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>217</integer>
+// CHECK:            <key>line</key><integer>215</integer>
 // CHECK:            <key>col</key><integer>3</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>217</integer>
-// CHECK:            <key>col</key><integer>9</integer>
+// CHECK:            <key>line</key><integer>215</integer>
+// CHECK:            <key>col</key><integer>4</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
 // CHECK:          </array>
 // CHECK:         <key>end</key>
 // CHECK:          <array>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>220</integer>
+// CHECK:            <key>line</key><integer>217</integer>
 // CHECK:            <key>col</key><integer>3</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>220</integer>
-// CHECK:            <key>col</key><integer>5</integer>
+// CHECK:            <key>line</key><integer>217</integer>
+// CHECK:            <key>col</key><integer>18</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
 // CHECK:          </array>
@@ -4039,26 +4119,26 @@
 // CHECK:         <key>start</key>
 // CHECK:          <array>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>220</integer>
+// CHECK:            <key>line</key><integer>217</integer>
 // CHECK:            <key>col</key><integer>3</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>220</integer>
-// CHECK:            <key>col</key><integer>5</integer>
+// CHECK:            <key>line</key><integer>217</integer>
+// CHECK:            <key>col</key><integer>18</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
 // CHECK:          </array>
 // CHECK:         <key>end</key>
 // CHECK:          <array>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>220</integer>
-// CHECK:            <key>col</key><integer>9</integer>
+// CHECK:            <key>line</key><integer>217</integer>
+// CHECK:            <key>col</key><integer>20</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>220</integer>
-// CHECK:            <key>col</key><integer>9</integer>
+// CHECK:            <key>line</key><integer>217</integer>
+// CHECK:            <key>col</key><integer>20</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
 // CHECK:          </array>
@@ -4069,43 +4149,43 @@
 // CHECK:      <key>kind</key><string>event</string>
 // CHECK:      <key>location</key>
 // CHECK:      <dict>
-// CHECK:       <key>line</key><integer>220</integer>
-// CHECK:       <key>col</key><integer>9</integer>
+// CHECK:       <key>line</key><integer>217</integer>
+// CHECK:       <key>col</key><integer>20</integer>
 // CHECK:       <key>file</key><integer>0</integer>
 // CHECK:      </dict>
 // CHECK:      <key>ranges</key>
 // CHECK:      <array>
 // CHECK:        <array>
 // CHECK:         <dict>
-// CHECK:          <key>line</key><integer>220</integer>
-// CHECK:          <key>col</key><integer>9</integer>
+// CHECK:          <key>line</key><integer>217</integer>
+// CHECK:          <key>col</key><integer>20</integer>
 // CHECK:          <key>file</key><integer>0</integer>
 // CHECK:         </dict>
 // CHECK:         <dict>
-// CHECK:          <key>line</key><integer>220</integer>
-// CHECK:          <key>col</key><integer>23</integer>
+// CHECK:          <key>line</key><integer>217</integer>
+// CHECK:          <key>col</key><integer>20</integer>
 // CHECK:          <key>file</key><integer>0</integer>
 // CHECK:         </dict>
 // CHECK:        </array>
 // CHECK:      </array>
 // CHECK:      <key>depth</key><integer>0</integer>
 // CHECK:      <key>extended_message</key>
-// CHECK:      <string>Incompatible pointer types assigning to &apos;NSString *&apos; from &apos;NSNumber *&apos;</string>
+// CHECK:      <string>Conversion from value of type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSString *&gt; *&apos;</string>
 // CHECK:      <key>message</key>
-// CHECK:      <string>Incompatible pointer types assigning to &apos;NSString *&apos; from &apos;NSNumber *&apos;</string>
+// CHECK:      <string>Conversion from value of type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSString *&gt; *&apos;</string>
 // CHECK:     </dict>
 // CHECK:    </array>
-// CHECK:    <key>description</key><string>Incompatible pointer types assigning to &apos;NSString *&apos; from &apos;NSNumber *&apos;</string>
+// CHECK:    <key>description</key><string>Conversion from value of type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSString *&gt; *&apos;</string>
 // CHECK:    <key>category</key><string>Core Foundation/Objective-C</string>
 // CHECK:    <key>type</key><string>Generics</string>
-// CHECK:    <key>check_name</key><string>alpha.osx.cocoa.ObjCGenerics</string>
+// CHECK:    <key>check_name</key><string>core.DynamicTypePropagation</string>
 // CHECK:   <key>issue_context_kind</key><string>function</string>
-// CHECK:   <key>issue_context</key><string>workWithProperties</string>
-// CHECK:   <key>issue_hash</key><string>4</string>
+// CHECK:   <key>issue_context</key><string>InferenceFromAPIWithBuggyTypes3</string>
+// CHECK:   <key>issue_hash</key><string>3</string>
 // CHECK:   <key>location</key>
 // CHECK:   <dict>
-// CHECK:    <key>line</key><integer>220</integer>
-// CHECK:    <key>col</key><integer>9</integer>
+// CHECK:    <key>line</key><integer>217</integer>
+// CHECK:    <key>col</key><integer>20</integer>
 // CHECK:    <key>file</key><integer>0</integer>
 // CHECK:   </dict>
 // CHECK:   </dict>
@@ -4116,30 +4196,30 @@
 // CHECK:      <key>kind</key><string>event</string>
 // CHECK:      <key>location</key>
 // CHECK:      <dict>
-// CHECK:       <key>line</key><integer>217</integer>
-// CHECK:       <key>col</key><integer>16</integer>
+// CHECK:       <key>line</key><integer>221</integer>
+// CHECK:       <key>col</key><integer>45</integer>
 // CHECK:       <key>file</key><integer>0</integer>
 // CHECK:      </dict>
 // CHECK:      <key>ranges</key>
 // CHECK:      <array>
 // CHECK:        <array>
 // CHECK:         <dict>
-// CHECK:          <key>line</key><integer>217</integer>
-// CHECK:          <key>col</key><integer>16</integer>
+// CHECK:          <key>line</key><integer>221</integer>
+// CHECK:          <key>col</key><integer>45</integer>
 // CHECK:          <key>file</key><integer>0</integer>
 // CHECK:         </dict>
 // CHECK:         <dict>
-// CHECK:          <key>line</key><integer>217</integer>
-// CHECK:          <key>col</key><integer>16</integer>
+// CHECK:          <key>line</key><integer>221</integer>
+// CHECK:          <key>col</key><integer>45</integer>
 // CHECK:          <key>file</key><integer>0</integer>
 // CHECK:         </dict>
 // CHECK:        </array>
 // CHECK:      </array>
 // CHECK:      <key>depth</key><integer>0</integer>
 // CHECK:      <key>extended_message</key>
-// CHECK:      <string>Type &apos;NSArray&lt;NSNumber *&gt; *&apos; is inferred from implicit cast (from &apos;NSArray&lt;NSNumber *&gt; *&apos; to &apos;NSArray *&apos;)</string>
+// CHECK:      <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;__kindof NSArray&lt;NSString *&gt; *&apos; to &apos;BuggyMutableArray&lt;NSMutableString *&gt; *&apos;)</string>
 // CHECK:      <key>message</key>
-// CHECK:      <string>Type &apos;NSArray&lt;NSNumber *&gt; *&apos; is inferred from implicit cast (from &apos;NSArray&lt;NSNumber *&gt; *&apos; to &apos;NSArray *&apos;)</string>
+// CHECK:      <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;__kindof NSArray&lt;NSString *&gt; *&apos; to &apos;BuggyMutableArray&lt;NSMutableString *&gt; *&apos;)</string>
 // CHECK:     </dict>
 // CHECK:     <dict>
 // CHECK:      <key>kind</key><string>control</string>
@@ -4149,13 +4229,13 @@
 // CHECK:         <key>start</key>
 // CHECK:          <array>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>217</integer>
+// CHECK:            <key>line</key><integer>221</integer>
 // CHECK:            <key>col</key><integer>3</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>217</integer>
-// CHECK:            <key>col</key><integer>9</integer>
+// CHECK:            <key>line</key><integer>221</integer>
+// CHECK:            <key>col</key><integer>19</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
 // CHECK:          </array>
@@ -4168,7 +4248,7 @@
 // CHECK:           </dict>
 // CHECK:           <dict>
 // CHECK:            <key>line</key><integer>222</integer>
-// CHECK:            <key>col</key><integer>5</integer>
+// CHECK:            <key>col</key><integer>18</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
 // CHECK:          </array>
@@ -4176,6 +4256,35 @@
 // CHECK:       </array>
 // CHECK:     </dict>
 // CHECK:     <dict>
+// CHECK:      <key>kind</key><string>event</string>
+// CHECK:      <key>location</key>
+// CHECK:      <dict>
+// CHECK:       <key>line</key><integer>222</integer>
+// CHECK:       <key>col</key><integer>20</integer>
+// CHECK:       <key>file</key><integer>0</integer>
+// CHECK:      </dict>
+// CHECK:      <key>ranges</key>
+// CHECK:      <array>
+// CHECK:        <array>
+// CHECK:         <dict>
+// CHECK:          <key>line</key><integer>222</integer>
+// CHECK:          <key>col</key><integer>20</integer>
+// CHECK:          <key>file</key><integer>0</integer>
+// CHECK:         </dict>
+// CHECK:         <dict>
+// CHECK:          <key>line</key><integer>222</integer>
+// CHECK:          <key>col</key><integer>20</integer>
+// CHECK:          <key>file</key><integer>0</integer>
+// CHECK:         </dict>
+// CHECK:        </array>
+// CHECK:      </array>
+// CHECK:      <key>depth</key><integer>0</integer>
+// CHECK:      <key>extended_message</key>
+// CHECK:      <string>Type &apos;MutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;BuggyMutableArray&lt;NSMutableString *&gt; *&apos; to &apos;MutableArray&lt;NSString *&gt; *&apos;)</string>
+// CHECK:      <key>message</key>
+// CHECK:      <string>Type &apos;MutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;BuggyMutableArray&lt;NSMutableString *&gt; *&apos; to &apos;MutableArray&lt;NSString *&gt; *&apos;)</string>
+// CHECK:     </dict>
+// CHECK:     <dict>
 // CHECK:      <key>kind</key><string>control</string>
 // CHECK:      <key>edges</key>
 // CHECK:       <array>
@@ -4189,20 +4298,20 @@
 // CHECK:           </dict>
 // CHECK:           <dict>
 // CHECK:            <key>line</key><integer>222</integer>
-// CHECK:            <key>col</key><integer>5</integer>
+// CHECK:            <key>col</key><integer>18</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
 // CHECK:          </array>
 // CHECK:         <key>end</key>
 // CHECK:          <array>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>222</integer>
-// CHECK:            <key>col</key><integer>11</integer>
+// CHECK:            <key>line</key><integer>223</integer>
+// CHECK:            <key>col</key><integer>3</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>222</integer>
-// CHECK:            <key>col</key><integer>21</integer>
+// CHECK:            <key>line</key><integer>223</integer>
+// CHECK:            <key>col</key><integer>25</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
 // CHECK:          </array>
@@ -4210,10 +4319,476 @@
 // CHECK:       </array>
 // CHECK:     </dict>
 // CHECK:     <dict>
-// CHECK:      <key>kind</key><string>event</string>
-// CHECK:      <key>location</key>
-// CHECK:      <dict>
-// CHECK:       <key>line</key><integer>222</integer>
+// CHECK:      <key>kind</key><string>control</string>
+// CHECK:      <key>edges</key>
+// CHECK:       <array>
+// CHECK:        <dict>
+// CHECK:         <key>start</key>
+// CHECK:          <array>
+// CHECK:           <dict>
+// CHECK:            <key>line</key><integer>223</integer>
+// CHECK:            <key>col</key><integer>3</integer>
+// CHECK:            <key>file</key><integer>0</integer>
+// CHECK:           </dict>
+// CHECK:           <dict>
+// CHECK:            <key>line</key><integer>223</integer>
+// CHECK:            <key>col</key><integer>25</integer>
+// CHECK:            <key>file</key><integer>0</integer>
+// CHECK:           </dict>
+// CHECK:          </array>
+// CHECK:         <key>end</key>
+// CHECK:          <array>
+// CHECK:           <dict>
+// CHECK:            <key>line</key><integer>223</integer>
+// CHECK:            <key>col</key><integer>27</integer>
+// CHECK:            <key>file</key><integer>0</integer>
+// CHECK:           </dict>
+// CHECK:           <dict>
+// CHECK:            <key>line</key><integer>223</integer>
+// CHECK:            <key>col</key><integer>27</integer>
+// CHECK:            <key>file</key><integer>0</integer>
+// CHECK:           </dict>
+// CHECK:          </array>
+// CHECK:        </dict>
+// CHECK:       </array>
+// CHECK:     </dict>
+// CHECK:     <dict>
+// CHECK:      <key>kind</key><string>event</string>
+// CHECK:      <key>location</key>
+// CHECK:      <dict>
+// CHECK:       <key>line</key><integer>223</integer>
+// CHECK:       <key>col</key><integer>27</integer>
+// CHECK:       <key>file</key><integer>0</integer>
+// CHECK:      </dict>
+// CHECK:      <key>ranges</key>
+// CHECK:      <array>
+// CHECK:        <array>
+// CHECK:         <dict>
+// CHECK:          <key>line</key><integer>223</integer>
+// CHECK:          <key>col</key><integer>27</integer>
+// CHECK:          <key>file</key><integer>0</integer>
+// CHECK:         </dict>
+// CHECK:         <dict>
+// CHECK:          <key>line</key><integer>223</integer>
+// CHECK:          <key>col</key><integer>27</integer>
+// CHECK:          <key>file</key><integer>0</integer>
+// CHECK:         </dict>
+// CHECK:        </array>
+// CHECK:      </array>
+// CHECK:      <key>depth</key><integer>0</integer>
+// CHECK:      <key>extended_message</key>
+// CHECK:      <string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
+// CHECK:      <key>message</key>
+// CHECK:      <string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
+// CHECK:     </dict>
+// CHECK:    </array>
+// CHECK:    <key>description</key><string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
+// CHECK:    <key>category</key><string>Core Foundation/Objective-C</string>
+// CHECK:    <key>type</key><string>Generics</string>
+// CHECK:    <key>check_name</key><string>core.DynamicTypePropagation</string>
+// CHECK:   <key>issue_context_kind</key><string>function</string>
+// CHECK:   <key>issue_context</key><string>InferenceFromAPIWithBuggyTypes4</string>
+// CHECK:   <key>issue_hash</key><string>3</string>
+// CHECK:   <key>location</key>
+// CHECK:   <dict>
+// CHECK:    <key>line</key><integer>223</integer>
+// CHECK:    <key>col</key><integer>27</integer>
+// CHECK:    <key>file</key><integer>0</integer>
+// CHECK:   </dict>
+// CHECK:   </dict>
+// CHECK:   <dict>
+// CHECK:    <key>path</key>
+// CHECK:    <array>
+// CHECK:     <dict>
+// CHECK:      <key>kind</key><string>event</string>
+// CHECK:      <key>location</key>
+// CHECK:      <dict>
+// CHECK:       <key>line</key><integer>235</integer>
+// CHECK:       <key>col</key><integer>16</integer>
+// CHECK:       <key>file</key><integer>0</integer>
+// CHECK:      </dict>
+// CHECK:      <key>ranges</key>
+// CHECK:      <array>
+// CHECK:        <array>
+// CHECK:         <dict>
+// CHECK:          <key>line</key><integer>235</integer>
+// CHECK:          <key>col</key><integer>16</integer>
+// CHECK:          <key>file</key><integer>0</integer>
+// CHECK:         </dict>
+// CHECK:         <dict>
+// CHECK:          <key>line</key><integer>235</integer>
+// CHECK:          <key>col</key><integer>16</integer>
+// CHECK:          <key>file</key><integer>0</integer>
+// CHECK:         </dict>
+// CHECK:        </array>
+// CHECK:      </array>
+// CHECK:      <key>depth</key><integer>0</integer>
+// CHECK:      <key>extended_message</key>
+// CHECK:      <string>Type &apos;NSArray&lt;NSNumber *&gt; *&apos; is inferred from implicit cast (from &apos;NSArray&lt;NSNumber *&gt; *&apos; to &apos;NSArray *&apos;)</string>
+// CHECK:      <key>message</key>
+// CHECK:      <string>Type &apos;NSArray&lt;NSNumber *&gt; *&apos; is inferred from implicit cast (from &apos;NSArray&lt;NSNumber *&gt; *&apos; to &apos;NSArray *&apos;)</string>
+// CHECK:     </dict>
+// CHECK:     <dict>
+// CHECK:      <key>kind</key><string>control</string>
+// CHECK:      <key>edges</key>
+// CHECK:       <array>
+// CHECK:        <dict>
+// CHECK:         <key>start</key>
+// CHECK:          <array>
+// CHECK:           <dict>
+// CHECK:            <key>line</key><integer>235</integer>
+// CHECK:            <key>col</key><integer>3</integer>
+// CHECK:            <key>file</key><integer>0</integer>
+// CHECK:           </dict>
+// CHECK:           <dict>
+// CHECK:            <key>line</key><integer>235</integer>
+// CHECK:            <key>col</key><integer>9</integer>
+// CHECK:            <key>file</key><integer>0</integer>
+// CHECK:           </dict>
+// CHECK:          </array>
+// CHECK:         <key>end</key>
+// CHECK:          <array>
+// CHECK:           <dict>
+// CHECK:            <key>line</key><integer>236</integer>
+// CHECK:            <key>col</key><integer>3</integer>
+// CHECK:            <key>file</key><integer>0</integer>
+// CHECK:           </dict>
+// CHECK:           <dict>
+// CHECK:            <key>line</key><integer>236</integer>
+// CHECK:            <key>col</key><integer>10</integer>
+// CHECK:            <key>file</key><integer>0</integer>
+// CHECK:           </dict>
+// CHECK:          </array>
+// CHECK:        </dict>
+// CHECK:       </array>
+// CHECK:     </dict>
+// CHECK:     <dict>
+// CHECK:      <key>kind</key><string>control</string>
+// CHECK:      <key>edges</key>
+// CHECK:       <array>
+// CHECK:        <dict>
+// CHECK:         <key>start</key>
+// CHECK:          <array>
+// CHECK:           <dict>
+// CHECK:            <key>line</key><integer>236</integer>
+// CHECK:            <key>col</key><integer>3</integer>
+// CHECK:            <key>file</key><integer>0</integer>
+// CHECK:           </dict>
+// CHECK:           <dict>
+// CHECK:            <key>line</key><integer>236</integer>
+// CHECK:            <key>col</key><integer>10</integer>
+// CHECK:            <key>file</key><integer>0</integer>
+// CHECK:           </dict>
+// CHECK:          </array>
+// CHECK:         <key>end</key>
+// CHECK:          <array>
+// CHECK:           <dict>
+// CHECK:            <key>line</key><integer>236</integer>
+// CHECK:            <key>col</key><integer>19</integer>
+// CHECK:            <key>file</key><integer>0</integer>
+// CHECK:           </dict>
+// CHECK:           <dict>
+// CHECK:            <key>line</key><integer>236</integer>
+// CHECK:            <key>col</key><integer>19</integer>
+// CHECK:            <key>file</key><integer>0</integer>
+// CHECK:           </dict>
+// CHECK:          </array>
+// CHECK:        </dict>
+// CHECK:       </array>
+// CHECK:     </dict>
+// CHECK:     <dict>
+// CHECK:      <key>kind</key><string>event</string>
+// CHECK:      <key>location</key>
+// CHECK:      <dict>
+// CHECK:       <key>line</key><integer>236</integer>
+// CHECK:       <key>col</key><integer>19</integer>
+// CHECK:       <key>file</key><integer>0</integer>
+// CHECK:      </dict>
+// CHECK:      <key>ranges</key>
+// CHECK:      <array>
+// CHECK:        <array>
+// CHECK:         <dict>
+// CHECK:          <key>line</key><integer>236</integer>
+// CHECK:          <key>col</key><integer>19</integer>
+// CHECK:          <key>file</key><integer>0</integer>
+// CHECK:         </dict>
+// CHECK:         <dict>
+// CHECK:          <key>line</key><integer>236</integer>
+// CHECK:          <key>col</key><integer>38</integer>
+// CHECK:          <key>file</key><integer>0</integer>
+// CHECK:         </dict>
+// CHECK:        </array>
+// CHECK:      </array>
+// CHECK:      <key>depth</key><integer>0</integer>
+// CHECK:      <key>extended_message</key>
+// CHECK:      <string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
+// CHECK:      <key>message</key>
+// CHECK:      <string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
+// CHECK:     </dict>
+// CHECK:    </array>
+// CHECK:    <key>description</key><string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
+// CHECK:    <key>category</key><string>Core Foundation/Objective-C</string>
+// CHECK:    <key>type</key><string>Generics</string>
+// CHECK:    <key>check_name</key><string>core.DynamicTypePropagation</string>
+// CHECK:   <key>issue_context_kind</key><string>function</string>
+// CHECK:   <key>issue_context</key><string>workWithProperties</string>
+// CHECK:   <key>issue_hash</key><string>2</string>
+// CHECK:   <key>location</key>
+// CHECK:   <dict>
+// CHECK:    <key>line</key><integer>236</integer>
+// CHECK:    <key>col</key><integer>19</integer>
+// CHECK:    <key>file</key><integer>0</integer>
+// CHECK:   </dict>
+// CHECK:   </dict>
+// CHECK:   <dict>
+// CHECK:    <key>path</key>
+// CHECK:    <array>
+// CHECK:     <dict>
+// CHECK:      <key>kind</key><string>event</string>
+// CHECK:      <key>location</key>
+// CHECK:      <dict>
+// CHECK:       <key>line</key><integer>235</integer>
+// CHECK:       <key>col</key><integer>16</integer>
+// CHECK:       <key>file</key><integer>0</integer>
+// CHECK:      </dict>
+// CHECK:      <key>ranges</key>
+// CHECK:      <array>
+// CHECK:        <array>
+// CHECK:         <dict>
+// CHECK:          <key>line</key><integer>235</integer>
+// CHECK:          <key>col</key><integer>16</integer>
+// CHECK:          <key>file</key><integer>0</integer>
+// CHECK:         </dict>
+// CHECK:         <dict>
+// CHECK:          <key>line</key><integer>235</integer>
+// CHECK:          <key>col</key><integer>16</integer>
+// CHECK:          <key>file</key><integer>0</integer>
+// CHECK:         </dict>
+// CHECK:        </array>
+// CHECK:      </array>
+// CHECK:      <key>depth</key><integer>0</integer>
+// CHECK:      <key>extended_message</key>
+// CHECK:      <string>Type &apos;NSArray&lt;NSNumber *&gt; *&apos; is inferred from implicit cast (from &apos;NSArray&lt;NSNumber *&gt; *&apos; to &apos;NSArray *&apos;)</string>
+// CHECK:      <key>message</key>
+// CHECK:      <string>Type &apos;NSArray&lt;NSNumber *&gt; *&apos; is inferred from implicit cast (from &apos;NSArray&lt;NSNumber *&gt; *&apos; to &apos;NSArray *&apos;)</string>
+// CHECK:     </dict>
+// CHECK:     <dict>
+// CHECK:      <key>kind</key><string>control</string>
+// CHECK:      <key>edges</key>
+// CHECK:       <array>
+// CHECK:        <dict>
+// CHECK:         <key>start</key>
+// CHECK:          <array>
+// CHECK:           <dict>
+// CHECK:            <key>line</key><integer>235</integer>
+// CHECK:            <key>col</key><integer>3</integer>
+// CHECK:            <key>file</key><integer>0</integer>
+// CHECK:           </dict>
+// CHECK:           <dict>
+// CHECK:            <key>line</key><integer>235</integer>
+// CHECK:            <key>col</key><integer>9</integer>
+// CHECK:            <key>file</key><integer>0</integer>
+// CHECK:           </dict>
+// CHECK:          </array>
+// CHECK:         <key>end</key>
+// CHECK:          <array>
+// CHECK:           <dict>
+// CHECK:            <key>line</key><integer>238</integer>
+// CHECK:            <key>col</key><integer>3</integer>
+// CHECK:            <key>file</key><integer>0</integer>
+// CHECK:           </dict>
+// CHECK:           <dict>
+// CHECK:            <key>line</key><integer>238</integer>
+// CHECK:            <key>col</key><integer>5</integer>
+// CHECK:            <key>file</key><integer>0</integer>
+// CHECK:           </dict>
+// CHECK:          </array>
+// CHECK:        </dict>
+// CHECK:       </array>
+// CHECK:     </dict>
+// CHECK:     <dict>
+// CHECK:      <key>kind</key><string>control</string>
+// CHECK:      <key>edges</key>
+// CHECK:       <array>
+// CHECK:        <dict>
+// CHECK:         <key>start</key>
+// CHECK:          <array>
+// CHECK:           <dict>
+// CHECK:            <key>line</key><integer>238</integer>
+// CHECK:            <key>col</key><integer>3</integer>
+// CHECK:            <key>file</key><integer>0</integer>
+// CHECK:           </dict>
+// CHECK:           <dict>
+// CHECK:            <key>line</key><integer>238</integer>
+// CHECK:            <key>col</key><integer>5</integer>
+// CHECK:            <key>file</key><integer>0</integer>
+// CHECK:           </dict>
+// CHECK:          </array>
+// CHECK:         <key>end</key>
+// CHECK:          <array>
+// CHECK:           <dict>
+// CHECK:            <key>line</key><integer>238</integer>
+// CHECK:            <key>col</key><integer>9</integer>
+// CHECK:            <key>file</key><integer>0</integer>
+// CHECK:           </dict>
+// CHECK:           <dict>
+// CHECK:            <key>line</key><integer>238</integer>
+// CHECK:            <key>col</key><integer>9</integer>
+// CHECK:            <key>file</key><integer>0</integer>
+// CHECK:           </dict>
+// CHECK:          </array>
+// CHECK:        </dict>
+// CHECK:       </array>
+// CHECK:     </dict>
+// CHECK:     <dict>
+// CHECK:      <key>kind</key><string>event</string>
+// CHECK:      <key>location</key>
+// CHECK:      <dict>
+// CHECK:       <key>line</key><integer>238</integer>
+// CHECK:       <key>col</key><integer>9</integer>
+// CHECK:       <key>file</key><integer>0</integer>
+// CHECK:      </dict>
+// CHECK:      <key>ranges</key>
+// CHECK:      <array>
+// CHECK:        <array>
+// CHECK:         <dict>
+// CHECK:          <key>line</key><integer>238</integer>
+// CHECK:          <key>col</key><integer>9</integer>
+// CHECK:          <key>file</key><integer>0</integer>
+// CHECK:         </dict>
+// CHECK:         <dict>
+// CHECK:          <key>line</key><integer>238</integer>
+// CHECK:          <key>col</key><integer>23</integer>
+// CHECK:          <key>file</key><integer>0</integer>
+// CHECK:         </dict>
+// CHECK:        </array>
+// CHECK:      </array>
+// CHECK:      <key>depth</key><integer>0</integer>
+// CHECK:      <key>extended_message</key>
+// CHECK:      <string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
+// CHECK:      <key>message</key>
+// CHECK:      <string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
+// CHECK:     </dict>
+// CHECK:    </array>
+// CHECK:    <key>description</key><string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
+// CHECK:    <key>category</key><string>Core Foundation/Objective-C</string>
+// CHECK:    <key>type</key><string>Generics</string>
+// CHECK:    <key>check_name</key><string>core.DynamicTypePropagation</string>
+// CHECK:   <key>issue_context_kind</key><string>function</string>
+// CHECK:   <key>issue_context</key><string>workWithProperties</string>
+// CHECK:   <key>issue_hash</key><string>4</string>
+// CHECK:   <key>location</key>
+// CHECK:   <dict>
+// CHECK:    <key>line</key><integer>238</integer>
+// CHECK:    <key>col</key><integer>9</integer>
+// CHECK:    <key>file</key><integer>0</integer>
+// CHECK:   </dict>
+// CHECK:   </dict>
+// CHECK:   <dict>
+// CHECK:    <key>path</key>
+// CHECK:    <array>
+// CHECK:     <dict>
+// CHECK:      <key>kind</key><string>event</string>
+// CHECK:      <key>location</key>
+// CHECK:      <dict>
+// CHECK:       <key>line</key><integer>235</integer>
+// CHECK:       <key>col</key><integer>16</integer>
+// CHECK:       <key>file</key><integer>0</integer>
+// CHECK:      </dict>
+// CHECK:      <key>ranges</key>
+// CHECK:      <array>
+// CHECK:        <array>
+// CHECK:         <dict>
+// CHECK:          <key>line</key><integer>235</integer>
+// CHECK:          <key>col</key><integer>16</integer>
+// CHECK:          <key>file</key><integer>0</integer>
+// CHECK:         </dict>
+// CHECK:         <dict>
+// CHECK:          <key>line</key><integer>235</integer>
+// CHECK:          <key>col</key><integer>16</integer>
+// CHECK:          <key>file</key><integer>0</integer>
+// CHECK:         </dict>
+// CHECK:        </array>
+// CHECK:      </array>
+// CHECK:      <key>depth</key><integer>0</integer>
+// CHECK:      <key>extended_message</key>
+// CHECK:      <string>Type &apos;NSArray&lt;NSNumber *&gt; *&apos; is inferred from implicit cast (from &apos;NSArray&lt;NSNumber *&gt; *&apos; to &apos;NSArray *&apos;)</string>
+// CHECK:      <key>message</key>
+// CHECK:      <string>Type &apos;NSArray&lt;NSNumber *&gt; *&apos; is inferred from implicit cast (from &apos;NSArray&lt;NSNumber *&gt; *&apos; to &apos;NSArray *&apos;)</string>
+// CHECK:     </dict>
+// CHECK:     <dict>
+// CHECK:      <key>kind</key><string>control</string>
+// CHECK:      <key>edges</key>
+// CHECK:       <array>
+// CHECK:        <dict>
+// CHECK:         <key>start</key>
+// CHECK:          <array>
+// CHECK:           <dict>
+// CHECK:            <key>line</key><integer>235</integer>
+// CHECK:            <key>col</key><integer>3</integer>
+// CHECK:            <key>file</key><integer>0</integer>
+// CHECK:           </dict>
+// CHECK:           <dict>
+// CHECK:            <key>line</key><integer>235</integer>
+// CHECK:            <key>col</key><integer>9</integer>
+// CHECK:            <key>file</key><integer>0</integer>
+// CHECK:           </dict>
+// CHECK:          </array>
+// CHECK:         <key>end</key>
+// CHECK:          <array>
+// CHECK:           <dict>
+// CHECK:            <key>line</key><integer>240</integer>
+// CHECK:            <key>col</key><integer>3</integer>
+// CHECK:            <key>file</key><integer>0</integer>
+// CHECK:           </dict>
+// CHECK:           <dict>
+// CHECK:            <key>line</key><integer>240</integer>
+// CHECK:            <key>col</key><integer>5</integer>
+// CHECK:            <key>file</key><integer>0</integer>
+// CHECK:           </dict>
+// CHECK:          </array>
+// CHECK:        </dict>
+// CHECK:       </array>
+// CHECK:     </dict>
+// CHECK:     <dict>
+// CHECK:      <key>kind</key><string>control</string>
+// CHECK:      <key>edges</key>
+// CHECK:       <array>
+// CHECK:        <dict>
+// CHECK:         <key>start</key>
+// CHECK:          <array>
+// CHECK:           <dict>
+// CHECK:            <key>line</key><integer>240</integer>
+// CHECK:            <key>col</key><integer>3</integer>
+// CHECK:            <key>file</key><integer>0</integer>
+// CHECK:           </dict>
+// CHECK:           <dict>
+// CHECK:            <key>line</key><integer>240</integer>
+// CHECK:            <key>col</key><integer>5</integer>
+// CHECK:            <key>file</key><integer>0</integer>
+// CHECK:           </dict>
+// CHECK:          </array>
+// CHECK:         <key>end</key>
+// CHECK:          <array>
+// CHECK:           <dict>
+// CHECK:            <key>line</key><integer>240</integer>
+// CHECK:            <key>col</key><integer>11</integer>
+// CHECK:            <key>file</key><integer>0</integer>
+// CHECK:           </dict>
+// CHECK:           <dict>
+// CHECK:            <key>line</key><integer>240</integer>
+// CHECK:            <key>col</key><integer>21</integer>
+// CHECK:            <key>file</key><integer>0</integer>
+// CHECK:           </dict>
+// CHECK:          </array>
+// CHECK:        </dict>
+// CHECK:       </array>
+// CHECK:     </dict>
+// CHECK:     <dict>
+// CHECK:      <key>kind</key><string>event</string>
+// CHECK:      <key>location</key>
+// CHECK:      <dict>
+// CHECK:       <key>line</key><integer>240</integer>
 // CHECK:       <key>col</key><integer>11</integer>
 // CHECK:       <key>file</key><integer>0</integer>
 // CHECK:      </dict>
@@ -4221,12 +4796,12 @@
 // CHECK:      <array>
 // CHECK:        <array>
 // CHECK:         <dict>
-// CHECK:          <key>line</key><integer>222</integer>
+// CHECK:          <key>line</key><integer>240</integer>
 // CHECK:          <key>col</key><integer>11</integer>
 // CHECK:          <key>file</key><integer>0</integer>
 // CHECK:         </dict>
 // CHECK:         <dict>
-// CHECK:          <key>line</key><integer>222</integer>
+// CHECK:          <key>line</key><integer>240</integer>
 // CHECK:          <key>col</key><integer>21</integer>
 // CHECK:          <key>file</key><integer>0</integer>
 // CHECK:         </dict>
@@ -4234,21 +4809,21 @@
 // CHECK:      </array>
 // CHECK:      <key>depth</key><integer>0</integer>
 // CHECK:      <key>extended_message</key>
-// CHECK:      <string>Incompatible pointer types assigning to &apos;NSString *&apos; from &apos;NSNumber *&apos;</string>
+// CHECK:      <string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
 // CHECK:      <key>message</key>
-// CHECK:      <string>Incompatible pointer types assigning to &apos;NSString *&apos; from &apos;NSNumber *&apos;</string>
+// CHECK:      <string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
 // CHECK:     </dict>
 // CHECK:    </array>
-// CHECK:    <key>description</key><string>Incompatible pointer types assigning to &apos;NSString *&apos; from &apos;NSNumber *&apos;</string>
+// CHECK:    <key>description</key><string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
 // CHECK:    <key>category</key><string>Core Foundation/Objective-C</string>
 // CHECK:    <key>type</key><string>Generics</string>
-// CHECK:    <key>check_name</key><string>alpha.osx.cocoa.ObjCGenerics</string>
+// CHECK:    <key>check_name</key><string>core.DynamicTypePropagation</string>
 // CHECK:   <key>issue_context_kind</key><string>function</string>
 // CHECK:   <key>issue_context</key><string>workWithProperties</string>
 // CHECK:   <key>issue_hash</key><string>6</string>
 // CHECK:   <key>location</key>
 // CHECK:   <dict>
-// CHECK:    <key>line</key><integer>222</integer>
+// CHECK:    <key>line</key><integer>240</integer>
 // CHECK:    <key>col</key><integer>11</integer>
 // CHECK:    <key>file</key><integer>0</integer>
 // CHECK:   </dict>
@@ -4260,7 +4835,7 @@
 // CHECK:      <key>kind</key><string>event</string>
 // CHECK:      <key>location</key>
 // CHECK:      <dict>
-// CHECK:       <key>line</key><integer>217</integer>
+// CHECK:       <key>line</key><integer>235</integer>
 // CHECK:       <key>col</key><integer>16</integer>
 // CHECK:       <key>file</key><integer>0</integer>
 // CHECK:      </dict>
@@ -4268,12 +4843,12 @@
 // CHECK:      <array>
 // CHECK:        <array>
 // CHECK:         <dict>
-// CHECK:          <key>line</key><integer>217</integer>
+// CHECK:          <key>line</key><integer>235</integer>
 // CHECK:          <key>col</key><integer>16</integer>
 // CHECK:          <key>file</key><integer>0</integer>
 // CHECK:         </dict>
 // CHECK:         <dict>
-// CHECK:          <key>line</key><integer>217</integer>
+// CHECK:          <key>line</key><integer>235</integer>
 // CHECK:          <key>col</key><integer>16</integer>
 // CHECK:          <key>file</key><integer>0</integer>
 // CHECK:         </dict>
@@ -4293,12 +4868,12 @@
 // CHECK:         <key>start</key>
 // CHECK:          <array>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>217</integer>
+// CHECK:            <key>line</key><integer>235</integer>
 // CHECK:            <key>col</key><integer>3</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>217</integer>
+// CHECK:            <key>line</key><integer>235</integer>
 // CHECK:            <key>col</key><integer>9</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
@@ -4306,12 +4881,12 @@
 // CHECK:         <key>end</key>
 // CHECK:          <array>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>224</integer>
+// CHECK:            <key>line</key><integer>242</integer>
 // CHECK:            <key>col</key><integer>3</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>224</integer>
+// CHECK:            <key>line</key><integer>242</integer>
 // CHECK:            <key>col</key><integer>5</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
@@ -4327,12 +4902,12 @@
 // CHECK:         <key>start</key>
 // CHECK:          <array>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>224</integer>
+// CHECK:            <key>line</key><integer>242</integer>
 // CHECK:            <key>col</key><integer>3</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>224</integer>
+// CHECK:            <key>line</key><integer>242</integer>
 // CHECK:            <key>col</key><integer>5</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
@@ -4340,12 +4915,12 @@
 // CHECK:         <key>end</key>
 // CHECK:          <array>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>224</integer>
+// CHECK:            <key>line</key><integer>242</integer>
 // CHECK:            <key>col</key><integer>9</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>224</integer>
+// CHECK:            <key>line</key><integer>242</integer>
 // CHECK:            <key>col</key><integer>9</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
@@ -4357,7 +4932,7 @@
 // CHECK:      <key>kind</key><string>event</string>
 // CHECK:      <key>location</key>
 // CHECK:      <dict>
-// CHECK:       <key>line</key><integer>224</integer>
+// CHECK:       <key>line</key><integer>242</integer>
 // CHECK:       <key>col</key><integer>9</integer>
 // CHECK:       <key>file</key><integer>0</integer>
 // CHECK:      </dict>
@@ -4365,12 +4940,12 @@
 // CHECK:      <array>
 // CHECK:        <array>
 // CHECK:         <dict>
-// CHECK:          <key>line</key><integer>224</integer>
+// CHECK:          <key>line</key><integer>242</integer>
 // CHECK:          <key>col</key><integer>9</integer>
 // CHECK:          <key>file</key><integer>0</integer>
 // CHECK:         </dict>
 // CHECK:         <dict>
-// CHECK:          <key>line</key><integer>224</integer>
+// CHECK:          <key>line</key><integer>242</integer>
 // CHECK:          <key>col</key><integer>9</integer>
 // CHECK:          <key>file</key><integer>0</integer>
 // CHECK:         </dict>
@@ -4378,21 +4953,21 @@
 // CHECK:      </array>
 // CHECK:      <key>depth</key><integer>0</integer>
 // CHECK:      <key>extended_message</key>
-// CHECK:      <string>Incompatible pointer types assigning to &apos;NSString *&apos; from &apos;NSNumber *&apos;</string>
+// CHECK:      <string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
 // CHECK:      <key>message</key>
-// CHECK:      <string>Incompatible pointer types assigning to &apos;NSString *&apos; from &apos;NSNumber *&apos;</string>
+// CHECK:      <string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
 // CHECK:     </dict>
 // CHECK:    </array>
-// CHECK:    <key>description</key><string>Incompatible pointer types assigning to &apos;NSString *&apos; from &apos;NSNumber *&apos;</string>
+// CHECK:    <key>description</key><string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
 // CHECK:    <key>category</key><string>Core Foundation/Objective-C</string>
 // CHECK:    <key>type</key><string>Generics</string>
-// CHECK:    <key>check_name</key><string>alpha.osx.cocoa.ObjCGenerics</string>
+// CHECK:    <key>check_name</key><string>core.DynamicTypePropagation</string>
 // CHECK:   <key>issue_context_kind</key><string>function</string>
 // CHECK:   <key>issue_context</key><string>workWithProperties</string>
 // CHECK:   <key>issue_hash</key><string>8</string>
 // CHECK:   <key>location</key>
 // CHECK:   <dict>
-// CHECK:    <key>line</key><integer>224</integer>
+// CHECK:    <key>line</key><integer>242</integer>
 // CHECK:    <key>col</key><integer>9</integer>
 // CHECK:    <key>file</key><integer>0</integer>
 // CHECK:   </dict>
@@ -4404,7 +4979,7 @@
 // CHECK:      <key>kind</key><string>event</string>
 // CHECK:      <key>location</key>
 // CHECK:      <dict>
-// CHECK:       <key>line</key><integer>230</integer>
+// CHECK:       <key>line</key><integer>248</integer>
 // CHECK:       <key>col</key><integer>7</integer>
 // CHECK:       <key>file</key><integer>0</integer>
 // CHECK:      </dict>
@@ -4412,12 +4987,12 @@
 // CHECK:      <array>
 // CHECK:        <array>
 // CHECK:         <dict>
-// CHECK:          <key>line</key><integer>230</integer>
+// CHECK:          <key>line</key><integer>248</integer>
 // CHECK:          <key>col</key><integer>7</integer>
 // CHECK:          <key>file</key><integer>0</integer>
 // CHECK:         </dict>
 // CHECK:         <dict>
-// CHECK:          <key>line</key><integer>230</integer>
+// CHECK:          <key>line</key><integer>248</integer>
 // CHECK:          <key>col</key><integer>7</integer>
 // CHECK:          <key>file</key><integer>0</integer>
 // CHECK:         </dict>
@@ -4437,12 +5012,12 @@
 // CHECK:         <key>start</key>
 // CHECK:          <array>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>230</integer>
+// CHECK:            <key>line</key><integer>248</integer>
 // CHECK:            <key>col</key><integer>3</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>230</integer>
+// CHECK:            <key>line</key><integer>248</integer>
 // CHECK:            <key>col</key><integer>3</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
@@ -4450,12 +5025,12 @@
 // CHECK:         <key>end</key>
 // CHECK:          <array>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>231</integer>
+// CHECK:            <key>line</key><integer>249</integer>
 // CHECK:            <key>col</key><integer>3</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>231</integer>
+// CHECK:            <key>line</key><integer>249</integer>
 // CHECK:            <key>col</key><integer>4</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
@@ -4471,12 +5046,12 @@
 // CHECK:         <key>start</key>
 // CHECK:          <array>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>231</integer>
+// CHECK:            <key>line</key><integer>249</integer>
 // CHECK:            <key>col</key><integer>3</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>231</integer>
+// CHECK:            <key>line</key><integer>249</integer>
 // CHECK:            <key>col</key><integer>4</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
@@ -4484,12 +5059,12 @@
 // CHECK:         <key>end</key>
 // CHECK:          <array>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>232</integer>
+// CHECK:            <key>line</key><integer>250</integer>
 // CHECK:            <key>col</key><integer>5</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>232</integer>
+// CHECK:            <key>line</key><integer>250</integer>
 // CHECK:            <key>col</key><integer>5</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
@@ -4505,12 +5080,12 @@
 // CHECK:         <key>start</key>
 // CHECK:          <array>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>232</integer>
+// CHECK:            <key>line</key><integer>250</integer>
 // CHECK:            <key>col</key><integer>5</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>232</integer>
+// CHECK:            <key>line</key><integer>250</integer>
 // CHECK:            <key>col</key><integer>5</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
@@ -4518,12 +5093,12 @@
 // CHECK:         <key>end</key>
 // CHECK:          <array>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>233</integer>
+// CHECK:            <key>line</key><integer>251</integer>
 // CHECK:            <key>col</key><integer>5</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>233</integer>
+// CHECK:            <key>line</key><integer>251</integer>
 // CHECK:            <key>col</key><integer>5</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
@@ -4535,7 +5110,7 @@
 // CHECK:      <key>kind</key><string>event</string>
 // CHECK:      <key>location</key>
 // CHECK:      <dict>
-// CHECK:       <key>line</key><integer>233</integer>
+// CHECK:       <key>line</key><integer>251</integer>
 // CHECK:       <key>col</key><integer>5</integer>
 // CHECK:       <key>file</key><integer>0</integer>
 // CHECK:      </dict>
@@ -4543,12 +5118,12 @@
 // CHECK:      <array>
 // CHECK:        <array>
 // CHECK:         <dict>
-// CHECK:          <key>line</key><integer>233</integer>
+// CHECK:          <key>line</key><integer>251</integer>
 // CHECK:          <key>col</key><integer>19</integer>
 // CHECK:          <key>file</key><integer>0</integer>
 // CHECK:         </dict>
 // CHECK:         <dict>
-// CHECK:          <key>line</key><integer>233</integer>
+// CHECK:          <key>line</key><integer>251</integer>
 // CHECK:          <key>col</key><integer>41</integer>
 // CHECK:          <key>file</key><integer>0</integer>
 // CHECK:         </dict>
@@ -4556,21 +5131,21 @@
 // CHECK:      </array>
 // CHECK:      <key>depth</key><integer>0</integer>
 // CHECK:      <key>extended_message</key>
-// CHECK:      <string>Incompatible pointer types assigning to &apos;NSMutableString *&apos; from &apos;NSString *&apos;</string>
+// CHECK:      <string>Conversion from value of type &apos;NSString *&apos; to incompatible type &apos;NSMutableString *&apos;</string>
 // CHECK:      <key>message</key>
-// CHECK:      <string>Incompatible pointer types assigning to &apos;NSMutableString *&apos; from &apos;NSString *&apos;</string>
+// CHECK:      <string>Conversion from value of type &apos;NSString *&apos; to incompatible type &apos;NSMutableString *&apos;</string>
 // CHECK:     </dict>
 // CHECK:    </array>
-// CHECK:    <key>description</key><string>Incompatible pointer types assigning to &apos;NSMutableString *&apos; from &apos;NSString *&apos;</string>
+// CHECK:    <key>description</key><string>Conversion from value of type &apos;NSString *&apos; to incompatible type &apos;NSMutableString *&apos;</string>
 // CHECK:    <key>category</key><string>Core Foundation/Objective-C</string>
 // CHECK:    <key>type</key><string>Generics</string>
-// CHECK:    <key>check_name</key><string>alpha.osx.cocoa.ObjCGenerics</string>
+// CHECK:    <key>check_name</key><string>core.DynamicTypePropagation</string>
 // CHECK:   <key>issue_context_kind</key><string>function</string>
 // CHECK:   <key>issue_context</key><string>findMethodDeclInTrackedType</string>
 // CHECK:   <key>issue_hash</key><string>4</string>
 // CHECK:   <key>location</key>
 // CHECK:   <dict>
-// CHECK:    <key>line</key><integer>233</integer>
+// CHECK:    <key>line</key><integer>251</integer>
 // CHECK:    <key>col</key><integer>5</integer>
 // CHECK:    <key>file</key><integer>0</integer>
 // CHECK:   </dict>
@@ -4582,7 +5157,7 @@
 // CHECK:      <key>kind</key><string>event</string>
 // CHECK:      <key>location</key>
 // CHECK:      <dict>
-// CHECK:       <key>line</key><integer>242</integer>
+// CHECK:       <key>line</key><integer>260</integer>
 // CHECK:       <key>col</key><integer>7</integer>
 // CHECK:       <key>file</key><integer>0</integer>
 // CHECK:      </dict>
@@ -4590,12 +5165,12 @@
 // CHECK:      <array>
 // CHECK:        <array>
 // CHECK:         <dict>
-// CHECK:          <key>line</key><integer>242</integer>
+// CHECK:          <key>line</key><integer>260</integer>
 // CHECK:          <key>col</key><integer>7</integer>
 // CHECK:          <key>file</key><integer>0</integer>
 // CHECK:         </dict>
 // CHECK:         <dict>
-// CHECK:          <key>line</key><integer>242</integer>
+// CHECK:          <key>line</key><integer>260</integer>
 // CHECK:          <key>col</key><integer>7</integer>
 // CHECK:          <key>file</key><integer>0</integer>
 // CHECK:         </dict>
@@ -4615,12 +5190,12 @@
 // CHECK:         <key>start</key>
 // CHECK:          <array>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>242</integer>
+// CHECK:            <key>line</key><integer>260</integer>
 // CHECK:            <key>col</key><integer>3</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>242</integer>
+// CHECK:            <key>line</key><integer>260</integer>
 // CHECK:            <key>col</key><integer>3</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
@@ -4628,12 +5203,12 @@
 // CHECK:         <key>end</key>
 // CHECK:          <array>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>243</integer>
+// CHECK:            <key>line</key><integer>261</integer>
 // CHECK:            <key>col</key><integer>3</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>243</integer>
+// CHECK:            <key>line</key><integer>261</integer>
 // CHECK:            <key>col</key><integer>4</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
@@ -4649,12 +5224,12 @@
 // CHECK:         <key>start</key>
 // CHECK:          <array>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>243</integer>
+// CHECK:            <key>line</key><integer>261</integer>
 // CHECK:            <key>col</key><integer>3</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>243</integer>
+// CHECK:            <key>line</key><integer>261</integer>
 // CHECK:            <key>col</key><integer>4</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
@@ -4662,12 +5237,12 @@
 // CHECK:         <key>end</key>
 // CHECK:          <array>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>244</integer>
+// CHECK:            <key>line</key><integer>262</integer>
 // CHECK:            <key>col</key><integer>5</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>244</integer>
+// CHECK:            <key>line</key><integer>262</integer>
 // CHECK:            <key>col</key><integer>5</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
@@ -4679,7 +5254,7 @@
 // CHECK:      <key>kind</key><string>event</string>
 // CHECK:      <key>location</key>
 // CHECK:      <dict>
-// CHECK:       <key>line</key><integer>244</integer>
+// CHECK:       <key>line</key><integer>262</integer>
 // CHECK:       <key>col</key><integer>5</integer>
 // CHECK:       <key>file</key><integer>0</integer>
 // CHECK:      </dict>
@@ -4687,12 +5262,12 @@
 // CHECK:      <array>
 // CHECK:        <array>
 // CHECK:         <dict>
-// CHECK:          <key>line</key><integer>244</integer>
+// CHECK:          <key>line</key><integer>262</integer>
 // CHECK:          <key>col</key><integer>19</integer>
 // CHECK:          <key>file</key><integer>0</integer>
 // CHECK:         </dict>
 // CHECK:         <dict>
-// CHECK:          <key>line</key><integer>244</integer>
+// CHECK:          <key>line</key><integer>262</integer>
 // CHECK:          <key>col</key><integer>41</integer>
 // CHECK:          <key>file</key><integer>0</integer>
 // CHECK:         </dict>
@@ -4700,21 +5275,21 @@
 // CHECK:      </array>
 // CHECK:      <key>depth</key><integer>0</integer>
 // CHECK:      <key>extended_message</key>
-// CHECK:      <string>Incompatible pointer types assigning to &apos;NSMutableString *&apos; from &apos;NSString *&apos;</string>
+// CHECK:      <string>Conversion from value of type &apos;NSString *&apos; to incompatible type &apos;NSMutableString *&apos;</string>
 // CHECK:      <key>message</key>
-// CHECK:      <string>Incompatible pointer types assigning to &apos;NSMutableString *&apos; from &apos;NSString *&apos;</string>
+// CHECK:      <string>Conversion from value of type &apos;NSString *&apos; to incompatible type &apos;NSMutableString *&apos;</string>
 // CHECK:     </dict>
 // CHECK:    </array>
-// CHECK:    <key>description</key><string>Incompatible pointer types assigning to &apos;NSMutableString *&apos; from &apos;NSString *&apos;</string>
+// CHECK:    <key>description</key><string>Conversion from value of type &apos;NSString *&apos; to incompatible type &apos;NSMutableString *&apos;</string>
 // CHECK:    <key>category</key><string>Core Foundation/Objective-C</string>
 // CHECK:    <key>type</key><string>Generics</string>
-// CHECK:    <key>check_name</key><string>alpha.osx.cocoa.ObjCGenerics</string>
+// CHECK:    <key>check_name</key><string>core.DynamicTypePropagation</string>
 // CHECK:   <key>issue_context_kind</key><string>function</string>
 // CHECK:   <key>issue_context</key><string>findMethodDeclInTrackedType2</string>
 // CHECK:   <key>issue_hash</key><string>3</string>
 // CHECK:   <key>location</key>
 // CHECK:   <dict>
-// CHECK:    <key>line</key><integer>244</integer>
+// CHECK:    <key>line</key><integer>262</integer>
 // CHECK:    <key>col</key><integer>5</integer>
 // CHECK:    <key>file</key><integer>0</integer>
 // CHECK:   </dict>
@@ -4726,7 +5301,7 @@
 // CHECK:      <key>kind</key><string>event</string>
 // CHECK:      <key>location</key>
 // CHECK:      <dict>
-// CHECK:       <key>line</key><integer>257</integer>
+// CHECK:       <key>line</key><integer>275</integer>
 // CHECK:       <key>col</key><integer>30</integer>
 // CHECK:       <key>file</key><integer>0</integer>
 // CHECK:      </dict>
@@ -4734,12 +5309,12 @@
 // CHECK:      <array>
 // CHECK:        <array>
 // CHECK:         <dict>
-// CHECK:          <key>line</key><integer>257</integer>
+// CHECK:          <key>line</key><integer>275</integer>
 // CHECK:          <key>col</key><integer>30</integer>
 // CHECK:          <key>file</key><integer>0</integer>
 // CHECK:         </dict>
 // CHECK:         <dict>
-// CHECK:          <key>line</key><integer>257</integer>
+// CHECK:          <key>line</key><integer>275</integer>
 // CHECK:          <key>col</key><integer>42</integer>
 // CHECK:          <key>file</key><integer>0</integer>
 // CHECK:         </dict>
@@ -4759,12 +5334,12 @@
 // CHECK:         <key>start</key>
 // CHECK:          <array>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>257</integer>
+// CHECK:            <key>line</key><integer>275</integer>
 // CHECK:            <key>col</key><integer>3</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>257</integer>
+// CHECK:            <key>line</key><integer>275</integer>
 // CHECK:            <key>col</key><integer>9</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
@@ -4772,12 +5347,12 @@
 // CHECK:         <key>end</key>
 // CHECK:          <array>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>259</integer>
+// CHECK:            <key>line</key><integer>277</integer>
 // CHECK:            <key>col</key><integer>3</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>259</integer>
+// CHECK:            <key>line</key><integer>277</integer>
 // CHECK:            <key>col</key><integer>3</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
@@ -4789,7 +5364,7 @@
 // CHECK:      <key>kind</key><string>event</string>
 // CHECK:      <key>location</key>
 // CHECK:      <dict>
-// CHECK:       <key>line</key><integer>259</integer>
+// CHECK:       <key>line</key><integer>277</integer>
 // CHECK:       <key>col</key><integer>3</integer>
 // CHECK:       <key>file</key><integer>0</integer>
 // CHECK:      </dict>
@@ -4797,12 +5372,12 @@
 // CHECK:      <array>
 // CHECK:        <array>
 // CHECK:         <dict>
-// CHECK:          <key>line</key><integer>259</integer>
+// CHECK:          <key>line</key><integer>277</integer>
 // CHECK:          <key>col</key><integer>19</integer>
 // CHECK:          <key>file</key><integer>0</integer>
 // CHECK:         </dict>
 // CHECK:         <dict>
-// CHECK:          <key>line</key><integer>259</integer>
+// CHECK:          <key>line</key><integer>277</integer>
 // CHECK:          <key>col</key><integer>41</integer>
 // CHECK:          <key>file</key><integer>0</integer>
 // CHECK:         </dict>
@@ -4810,21 +5385,21 @@
 // CHECK:      </array>
 // CHECK:      <key>depth</key><integer>0</integer>
 // CHECK:      <key>extended_message</key>
-// CHECK:      <string>Incompatible pointer types assigning to &apos;NSString *&apos; from &apos;NSNumber *&apos;</string>
+// CHECK:      <string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
 // CHECK:      <key>message</key>
-// CHECK:      <string>Incompatible pointer types assigning to &apos;NSString *&apos; from &apos;NSNumber *&apos;</string>
+// CHECK:      <string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
 // CHECK:     </dict>
 // CHECK:    </array>
-// CHECK:    <key>description</key><string>Incompatible pointer types assigning to &apos;NSString *&apos; from &apos;NSNumber *&apos;</string>
+// CHECK:    <key>description</key><string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
 // CHECK:    <key>category</key><string>Core Foundation/Objective-C</string>
 // CHECK:    <key>type</key><string>Generics</string>
-// CHECK:    <key>check_name</key><string>alpha.osx.cocoa.ObjCGenerics</string>
+// CHECK:    <key>check_name</key><string>core.DynamicTypePropagation</string>
 // CHECK:   <key>issue_context_kind</key><string>function</string>
 // CHECK:   <key>issue_context</key><string>testAnnotatedLiterals</string>
 // CHECK:   <key>issue_hash</key><string>3</string>
 // CHECK:   <key>location</key>
 // CHECK:   <dict>
-// CHECK:    <key>line</key><integer>259</integer>
+// CHECK:    <key>line</key><integer>277</integer>
 // CHECK:    <key>col</key><integer>3</integer>
 // CHECK:    <key>file</key><integer>0</integer>
 // CHECK:   </dict>
@@ -4836,7 +5411,7 @@
 // CHECK:      <key>kind</key><string>event</string>
 // CHECK:      <key>location</key>
 // CHECK:      <dict>
-// CHECK:       <key>line</key><integer>268</integer>
+// CHECK:       <key>line</key><integer>286</integer>
 // CHECK:       <key>col</key><integer>13</integer>
 // CHECK:       <key>file</key><integer>0</integer>
 // CHECK:      </dict>
@@ -4844,12 +5419,12 @@
 // CHECK:      <array>
 // CHECK:        <array>
 // CHECK:         <dict>
-// CHECK:          <key>line</key><integer>268</integer>
+// CHECK:          <key>line</key><integer>286</integer>
 // CHECK:          <key>col</key><integer>13</integer>
 // CHECK:          <key>file</key><integer>0</integer>
 // CHECK:         </dict>
 // CHECK:         <dict>
-// CHECK:          <key>line</key><integer>268</integer>
+// CHECK:          <key>line</key><integer>286</integer>
 // CHECK:          <key>col</key><integer>39</integer>
 // CHECK:          <key>file</key><integer>0</integer>
 // CHECK:         </dict>
@@ -4869,12 +5444,12 @@
 // CHECK:         <key>start</key>
 // CHECK:          <array>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>268</integer>
+// CHECK:            <key>line</key><integer>286</integer>
 // CHECK:            <key>col</key><integer>3</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>268</integer>
+// CHECK:            <key>line</key><integer>286</integer>
 // CHECK:            <key>col</key><integer>7</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
@@ -4882,12 +5457,12 @@
 // CHECK:         <key>end</key>
 // CHECK:          <array>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>269</integer>
+// CHECK:            <key>line</key><integer>287</integer>
 // CHECK:            <key>col</key><integer>3</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>269</integer>
+// CHECK:            <key>line</key><integer>287</integer>
 // CHECK:            <key>col</key><integer>9</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
@@ -4903,12 +5478,12 @@
 // CHECK:         <key>start</key>
 // CHECK:          <array>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>269</integer>
+// CHECK:            <key>line</key><integer>287</integer>
 // CHECK:            <key>col</key><integer>3</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>269</integer>
+// CHECK:            <key>line</key><integer>287</integer>
 // CHECK:            <key>col</key><integer>9</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
@@ -4916,12 +5491,12 @@
 // CHECK:         <key>end</key>
 // CHECK:          <array>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>269</integer>
+// CHECK:            <key>line</key><integer>287</integer>
 // CHECK:            <key>col</key><integer>28</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>269</integer>
+// CHECK:            <key>line</key><integer>287</integer>
 // CHECK:            <key>col</key><integer>28</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
@@ -4933,7 +5508,7 @@
 // CHECK:      <key>kind</key><string>event</string>
 // CHECK:      <key>location</key>
 // CHECK:      <dict>
-// CHECK:       <key>line</key><integer>269</integer>
+// CHECK:       <key>line</key><integer>287</integer>
 // CHECK:       <key>col</key><integer>28</integer>
 // CHECK:       <key>file</key><integer>0</integer>
 // CHECK:      </dict>
@@ -4941,12 +5516,12 @@
 // CHECK:      <array>
 // CHECK:        <array>
 // CHECK:         <dict>
-// CHECK:          <key>line</key><integer>269</integer>
+// CHECK:          <key>line</key><integer>287</integer>
 // CHECK:          <key>col</key><integer>28</integer>
 // CHECK:          <key>file</key><integer>0</integer>
 // CHECK:         </dict>
 // CHECK:         <dict>
-// CHECK:          <key>line</key><integer>269</integer>
+// CHECK:          <key>line</key><integer>287</integer>
 // CHECK:          <key>col</key><integer>39</integer>
 // CHECK:          <key>file</key><integer>0</integer>
 // CHECK:         </dict>
@@ -4954,21 +5529,21 @@
 // CHECK:      </array>
 // CHECK:      <key>depth</key><integer>0</integer>
 // CHECK:      <key>extended_message</key>
-// CHECK:      <string>Incompatible pointer types assigning to &apos;NSArray&lt;NSNumber *&gt; *&apos; from &apos;NSArray&lt;NSString *&gt; *&apos;</string>
+// CHECK:      <string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
 // CHECK:      <key>message</key>
-// CHECK:      <string>Incompatible pointer types assigning to &apos;NSArray&lt;NSNumber *&gt; *&apos; from &apos;NSArray&lt;NSString *&gt; *&apos;</string>
+// CHECK:      <string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
 // CHECK:     </dict>
 // CHECK:    </array>
-// CHECK:    <key>description</key><string>Incompatible pointer types assigning to &apos;NSArray&lt;NSNumber *&gt; *&apos; from &apos;NSArray&lt;NSString *&gt; *&apos;</string>
+// CHECK:    <key>description</key><string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
 // CHECK:    <key>category</key><string>Core Foundation/Objective-C</string>
 // CHECK:    <key>type</key><string>Generics</string>
-// CHECK:    <key>check_name</key><string>alpha.osx.cocoa.ObjCGenerics</string>
+// CHECK:    <key>check_name</key><string>core.DynamicTypePropagation</string>
 // CHECK:   <key>issue_context_kind</key><string>function</string>
 // CHECK:   <key>issue_context</key><string>trackedClassVariables</string>
 // CHECK:   <key>issue_hash</key><string>2</string>
 // CHECK:   <key>location</key>
 // CHECK:   <dict>
-// CHECK:    <key>line</key><integer>269</integer>
+// CHECK:    <key>line</key><integer>287</integer>
 // CHECK:    <key>col</key><integer>28</integer>
 // CHECK:    <key>file</key><integer>0</integer>
 // CHECK:   </dict>
@@ -4980,7 +5555,7 @@
 // CHECK:      <key>kind</key><string>event</string>
 // CHECK:      <key>location</key>
 // CHECK:      <dict>
-// CHECK:       <key>line</key><integer>268</integer>
+// CHECK:       <key>line</key><integer>286</integer>
 // CHECK:       <key>col</key><integer>13</integer>
 // CHECK:       <key>file</key><integer>0</integer>
 // CHECK:      </dict>
@@ -4988,12 +5563,12 @@
 // CHECK:      <array>
 // CHECK:        <array>
 // CHECK:         <dict>
-// CHECK:          <key>line</key><integer>268</integer>
+// CHECK:          <key>line</key><integer>286</integer>
 // CHECK:          <key>col</key><integer>13</integer>
 // CHECK:          <key>file</key><integer>0</integer>
 // CHECK:         </dict>
 // CHECK:         <dict>
-// CHECK:          <key>line</key><integer>268</integer>
+// CHECK:          <key>line</key><integer>286</integer>
 // CHECK:          <key>col</key><integer>39</integer>
 // CHECK:          <key>file</key><integer>0</integer>
 // CHECK:         </dict>
@@ -5013,12 +5588,12 @@
 // CHECK:         <key>start</key>
 // CHECK:          <array>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>268</integer>
+// CHECK:            <key>line</key><integer>286</integer>
 // CHECK:            <key>col</key><integer>3</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>268</integer>
+// CHECK:            <key>line</key><integer>286</integer>
 // CHECK:            <key>col</key><integer>7</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
@@ -5026,12 +5601,12 @@
 // CHECK:         <key>end</key>
 // CHECK:          <array>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>270</integer>
+// CHECK:            <key>line</key><integer>288</integer>
 // CHECK:            <key>col</key><integer>3</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>270</integer>
+// CHECK:            <key>line</key><integer>288</integer>
 // CHECK:            <key>col</key><integer>3</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
@@ -5047,12 +5622,12 @@
 // CHECK:         <key>start</key>
 // CHECK:          <array>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>270</integer>
+// CHECK:            <key>line</key><integer>288</integer>
 // CHECK:            <key>col</key><integer>3</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>270</integer>
+// CHECK:            <key>line</key><integer>288</integer>
 // CHECK:            <key>col</key><integer>3</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
@@ -5060,12 +5635,12 @@
 // CHECK:         <key>end</key>
 // CHECK:          <array>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>270</integer>
+// CHECK:            <key>line</key><integer>288</integer>
 // CHECK:            <key>col</key><integer>7</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>270</integer>
+// CHECK:            <key>line</key><integer>288</integer>
 // CHECK:            <key>col</key><integer>7</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
@@ -5077,7 +5652,7 @@
 // CHECK:      <key>kind</key><string>event</string>
 // CHECK:      <key>location</key>
 // CHECK:      <dict>
-// CHECK:       <key>line</key><integer>270</integer>
+// CHECK:       <key>line</key><integer>288</integer>
 // CHECK:       <key>col</key><integer>7</integer>
 // CHECK:       <key>file</key><integer>0</integer>
 // CHECK:      </dict>
@@ -5085,12 +5660,12 @@
 // CHECK:      <array>
 // CHECK:        <array>
 // CHECK:         <dict>
-// CHECK:          <key>line</key><integer>270</integer>
+// CHECK:          <key>line</key><integer>288</integer>
 // CHECK:          <key>col</key><integer>7</integer>
 // CHECK:          <key>file</key><integer>0</integer>
 // CHECK:         </dict>
 // CHECK:         <dict>
-// CHECK:          <key>line</key><integer>270</integer>
+// CHECK:          <key>line</key><integer>288</integer>
 // CHECK:          <key>col</key><integer>19</integer>
 // CHECK:          <key>file</key><integer>0</integer>
 // CHECK:         </dict>
@@ -5098,21 +5673,21 @@
 // CHECK:      </array>
 // CHECK:      <key>depth</key><integer>0</integer>
 // CHECK:      <key>extended_message</key>
-// CHECK:      <string>Incompatible pointer types assigning to &apos;NSArray&lt;NSNumber *&gt; *&apos; from &apos;NSArray&lt;NSString *&gt; *&apos;</string>
+// CHECK:      <string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
 // CHECK:      <key>message</key>
-// CHECK:      <string>Incompatible pointer types assigning to &apos;NSArray&lt;NSNumber *&gt; *&apos; from &apos;NSArray&lt;NSString *&gt; *&apos;</string>
+// CHECK:      <string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
 // CHECK:     </dict>
 // CHECK:    </array>
-// CHECK:    <key>description</key><string>Incompatible pointer types assigning to &apos;NSArray&lt;NSNumber *&gt; *&apos; from &apos;NSArray&lt;NSString *&gt; *&apos;</string>
+// CHECK:    <key>description</key><string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
 // CHECK:    <key>category</key><string>Core Foundation/Objective-C</string>
 // CHECK:    <key>type</key><string>Generics</string>
-// CHECK:    <key>check_name</key><string>alpha.osx.cocoa.ObjCGenerics</string>
+// CHECK:    <key>check_name</key><string>core.DynamicTypePropagation</string>
 // CHECK:   <key>issue_context_kind</key><string>function</string>
 // CHECK:   <key>issue_context</key><string>trackedClassVariables</string>
 // CHECK:   <key>issue_hash</key><string>3</string>
 // CHECK:   <key>location</key>
 // CHECK:   <dict>
-// CHECK:    <key>line</key><integer>270</integer>
+// CHECK:    <key>line</key><integer>288</integer>
 // CHECK:    <key>col</key><integer>7</integer>
 // CHECK:    <key>file</key><integer>0</integer>
 // CHECK:   </dict>
@@ -5124,7 +5699,7 @@
 // CHECK:      <key>kind</key><string>event</string>
 // CHECK:      <key>location</key>
 // CHECK:      <dict>
-// CHECK:       <key>line</key><integer>274</integer>
+// CHECK:       <key>line</key><integer>292</integer>
 // CHECK:       <key>col</key><integer>13</integer>
 // CHECK:       <key>file</key><integer>0</integer>
 // CHECK:      </dict>
@@ -5132,12 +5707,12 @@
 // CHECK:      <array>
 // CHECK:        <array>
 // CHECK:         <dict>
-// CHECK:          <key>line</key><integer>274</integer>
+// CHECK:          <key>line</key><integer>292</integer>
 // CHECK:          <key>col</key><integer>13</integer>
 // CHECK:          <key>file</key><integer>0</integer>
 // CHECK:         </dict>
 // CHECK:         <dict>
-// CHECK:          <key>line</key><integer>274</integer>
+// CHECK:          <key>line</key><integer>292</integer>
 // CHECK:          <key>col</key><integer>15</integer>
 // CHECK:          <key>file</key><integer>0</integer>
 // CHECK:         </dict>
@@ -5157,12 +5732,12 @@
 // CHECK:         <key>start</key>
 // CHECK:          <array>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>274</integer>
+// CHECK:            <key>line</key><integer>292</integer>
 // CHECK:            <key>col</key><integer>3</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>274</integer>
+// CHECK:            <key>line</key><integer>292</integer>
 // CHECK:            <key>col</key><integer>4</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
@@ -5170,12 +5745,12 @@
 // CHECK:         <key>end</key>
 // CHECK:          <array>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>275</integer>
+// CHECK:            <key>line</key><integer>293</integer>
 // CHECK:            <key>col</key><integer>3</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>275</integer>
+// CHECK:            <key>line</key><integer>293</integer>
 // CHECK:            <key>col</key><integer>3</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
@@ -5191,12 +5766,12 @@
 // CHECK:         <key>start</key>
 // CHECK:          <array>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>275</integer>
+// CHECK:            <key>line</key><integer>293</integer>
 // CHECK:            <key>col</key><integer>3</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>275</integer>
+// CHECK:            <key>line</key><integer>293</integer>
 // CHECK:            <key>col</key><integer>3</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
@@ -5204,12 +5779,12 @@
 // CHECK:         <key>end</key>
 // CHECK:          <array>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>275</integer>
+// CHECK:            <key>line</key><integer>293</integer>
 // CHECK:            <key>col</key><integer>18</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>275</integer>
+// CHECK:            <key>line</key><integer>293</integer>
 // CHECK:            <key>col</key><integer>21</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
@@ -5221,7 +5796,7 @@
 // CHECK:      <key>kind</key><string>event</string>
 // CHECK:      <key>location</key>
 // CHECK:      <dict>
-// CHECK:       <key>line</key><integer>275</integer>
+// CHECK:       <key>line</key><integer>293</integer>
 // CHECK:       <key>col</key><integer>18</integer>
 // CHECK:       <key>file</key><integer>0</integer>
 // CHECK:      </dict>
@@ -5229,12 +5804,12 @@
 // CHECK:      <array>
 // CHECK:        <array>
 // CHECK:         <dict>
-// CHECK:          <key>line</key><integer>275</integer>
+// CHECK:          <key>line</key><integer>293</integer>
 // CHECK:          <key>col</key><integer>18</integer>
 // CHECK:          <key>file</key><integer>0</integer>
 // CHECK:         </dict>
 // CHECK:         <dict>
-// CHECK:          <key>line</key><integer>275</integer>
+// CHECK:          <key>line</key><integer>293</integer>
 // CHECK:          <key>col</key><integer>21</integer>
 // CHECK:          <key>file</key><integer>0</integer>
 // CHECK:         </dict>
@@ -5242,24 +5817,23 @@
 // CHECK:      </array>
 // CHECK:      <key>depth</key><integer>0</integer>
 // CHECK:      <key>extended_message</key>
-// CHECK:      <string>Incompatible pointer types assigning to &apos;NSArray&lt;NSNumber *&gt; *&apos; from &apos;NSArray&lt;NSString *&gt; *&apos;</string>
+// CHECK:      <string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
 // CHECK:      <key>message</key>
-// CHECK:      <string>Incompatible pointer types assigning to &apos;NSArray&lt;NSNumber *&gt; *&apos; from &apos;NSArray&lt;NSString *&gt; *&apos;</string>
+// CHECK:      <string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
 // CHECK:     </dict>
 // CHECK:    </array>
-// CHECK:    <key>description</key><string>Incompatible pointer types assigning to &apos;NSArray&lt;NSNumber *&gt; *&apos; from &apos;NSArray&lt;NSString *&gt; *&apos;</string>
+// CHECK:    <key>description</key><string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
 // CHECK:    <key>category</key><string>Core Foundation/Objective-C</string>
 // CHECK:    <key>type</key><string>Generics</string>
-// CHECK:    <key>check_name</key><string>alpha.osx.cocoa.ObjCGenerics</string>
+// CHECK:    <key>check_name</key><string>core.DynamicTypePropagation</string>
 // CHECK:   <key>issue_context_kind</key><string>function</string>
 // CHECK:   <key>issue_context</key><string>nestedCollections</string>
 // CHECK:   <key>issue_hash</key><string>2</string>
 // CHECK:   <key>location</key>
 // CHECK:   <dict>
-// CHECK:    <key>line</key><integer>275</integer>
+// CHECK:    <key>line</key><integer>293</integer>
 // CHECK:    <key>col</key><integer>18</integer>
 // CHECK:    <key>file</key><integer>0</integer>
 // CHECK:   </dict>
 // CHECK:   </dict>
 // CHECK:  </array>
-