Clean up substituteNullabilityAnnotationsInClassTemplate

We can no longer hit the two edge-cases:
 - we now reliably detect whether we're indexing into the associated template
 - the nullability vector for the base expression is now guaranteed to
   match its type (at least as far as length goes)

Since we can now detect upfront whether substitution is going to fail, switch
to early-return.

PiperOrigin-RevId: 503957027
diff --git a/nullability_verification/pointer_nullability_analysis.cc b/nullability_verification/pointer_nullability_analysis.cc
index ee5b3dc..59ff710 100644
--- a/nullability_verification/pointer_nullability_analysis.cc
+++ b/nullability_verification/pointer_nullability_analysis.cc
@@ -138,39 +138,25 @@
       T,
       [&](const SubstTemplateTypeParmType* ST)
           -> std::optional<std::vector<NullabilityKind>> {
-        unsigned PointerCount = 0;
+        // The class specialization that is BaseType and owns ST.
+        const ClassTemplateSpecializationDecl* Specialization = nullptr;
+        if (auto RT = BaseType->getAs<RecordType>())
+          Specialization =
+              dyn_cast<ClassTemplateSpecializationDecl>(RT->getDecl());
+        // TODO: handle nested templates, where associated decl != base type
+        // (e.g. PointerNullabilityTest.MemberFunctionTemplateOfTemplateStruct)
+        if (!Specialization || Specialization != ST->getAssociatedDecl())
+          return std::nullopt;
+
         unsigned ArgIndex = ST->getIndex();
-        if (auto RT = BaseType->getAs<RecordType>()) {
-          if (auto CTSD =
-                  dyn_cast<ClassTemplateSpecializationDecl>(RT->getDecl());
-              CTSD == ST->getAssociatedDecl()) {
-            auto TemplateArgs = CTSD->getTemplateArgs().asArray();
+        auto TemplateArgs = Specialization->getTemplateArgs().asArray();
 
-            // TODO: Correctly handle the indexing of nested templates (e.g.
-            // PointerNullabilityTest.MemberFunctionTemplateOfTemplateStruct),
-            // then remove this fallback.
-            if (TemplateArgs.size() <= ArgIndex &&
-                ST->getReplacedParameter()->getDepth() == 0) {
-              return std::nullopt;
-            }
-
-            for (auto TA : TemplateArgs.take_front(ArgIndex)) {
-              PointerCount += countPointersInType(TA);
-            }
-            unsigned SliceSize = countPointersInType(TemplateArgs[ArgIndex]);
-            if (BaseNullabilityAnnotations.size() < PointerCount + SliceSize) {
-              // TODO: Currently, BaseNullabilityAnnotations can be erroneously
-              // empty due to lack of expression coverage. Use the dataflow
-              // lattice to retrieve correct base type annotations. Then, remove
-              // this fallback.
-              return std::nullopt;
-            } else {
-              return BaseNullabilityAnnotations.slice(PointerCount, SliceSize)
-                  .vec();
-            }
-          }
+        unsigned PointerCount = 0;
+        for (auto TA : TemplateArgs.take_front(ArgIndex)) {
+          PointerCount += countPointersInType(TA);
         }
-        return std::nullopt;
+        unsigned SliceSize = countPointersInType(TemplateArgs[ArgIndex]);
+        return BaseNullabilityAnnotations.slice(PointerCount, SliceSize).vec();
       });
 }