Revert "Revert "Internal change" since GitHub hasn't picked up this change yet."

This reverts commit dbd8bae7f7d3e1b7bc61794536d045b8bd5953e3.
diff --git a/nullability/pointer_nullability_analysis.cc b/nullability/pointer_nullability_analysis.cc
index e0dbb6c..6895221 100644
--- a/nullability/pointer_nullability_analysis.cc
+++ b/nullability/pointer_nullability_analysis.cc
@@ -198,29 +198,37 @@
       T,
       [&](const SubstTemplateTypeParmType *ST)
           -> std::optional<TypeNullability> {
+        auto *DRE = dyn_cast<DeclRefExpr>(CE->getCallee()->IgnoreImpCasts());
+        if (DRE == nullptr) return std::nullopt;
+
         // TODO: Handle calls that use template argument deduction.
-        // TODO: Handle nested templates (...->getDepth() > 0).
-        if (auto *DRE =
-                dyn_cast<DeclRefExpr>(CE->getCallee()->IgnoreImpCasts());
-            DRE != nullptr && ST->getReplacedParameter()->getDepth() == 0 &&
-            // Some or all of the template arguments may be deduced, and we
-            // won't see those on the `DeclRefExpr`. If the template argument
-            // was deduced, we don't have any sugar for it.
-            // TODO(b/268348533): Can we somehow obtain it from the function
-            // param it was deduced from?
-            // TODO(b/268345783): This check, as well as the index into
-            // `template_arguments` below, may be incorrect in the presence of
-            // parameters packs.  In function templates, parameter packs may
-            // appear anywhere in the parameter list. The index may therefore
-            // refer to one of the pack arguments, but we might incorrectly
-            // interpret it as referring to an argument that follows the pack.
-            ST->getIndex() < DRE->template_arguments().size()) {
-          TypeSourceInfo *TSI =
-              DRE->template_arguments()[ST->getIndex()].getTypeSourceInfo();
-          if (TSI == nullptr) return std::nullopt;
-          return getNullabilityAnnotationsFromType(TSI->getType());
-        }
-        return std::nullopt;
+
+        // Does this refer to a parameter of the function template?
+        // If not (e.g. nested templates, template specialization types in the
+        // return value), we handle the desugaring elsewhere.
+        auto *ReferencedFunction = dyn_cast<FunctionDecl>(DRE->getDecl());
+        if (!ReferencedFunction) return std::nullopt;
+        if (ReferencedFunction->getPrimaryTemplate() != ST->getAssociatedDecl())
+          return std::nullopt;
+
+        // Some or all of the template arguments may be deduced, and we won't
+        // see those on the `DeclRefExpr`. If the template argument was deduced,
+        // we don't have any sugar for it.
+        // TODO(b/268348533): Can we somehow obtain it from the function param
+        // it was deduced from?
+        // TODO(b/268345783): This check, as well as the index into
+        // `template_arguments` below, may be incorrect in the presence of
+        // parameters packs.  In function templates, parameter packs may appear
+        // anywhere in the parameter list. The index may therefore refer to one
+        // of the pack arguments, but we might incorrectly interpret it as
+        // referring to an argument that follows the pack.
+        if (ST->getIndex() >= DRE->template_arguments().size())
+          return std::nullopt;
+
+        TypeSourceInfo *TSI =
+            DRE->template_arguments()[ST->getIndex()].getTypeSourceInfo();
+        if (TSI == nullptr) return std::nullopt;
+        return getNullabilityAnnotationsFromType(TSI->getType());
       });
 }
 
diff --git a/nullability/test/templates.cc b/nullability/test/templates.cc
index 53bc052..f994eb3 100644
--- a/nullability/test/templates.cc
+++ b/nullability/test/templates.cc
@@ -1223,5 +1223,17 @@
   )cc"));
 }
 
+TEST(PointerNullabilityTest, CallFunctionReturningTemplateSpecializationType) {
+  EXPECT_TRUE(checkDiagnostics(R"cc(
+    template <class T>
+    struct AliasWrapper {
+      using Type = T;
+    };
+    template <typename>
+    AliasWrapper<int* _Nonnull>::Type f();
+    void target() { __assert_nullability<NK_nonnull>(f<int>()); }
+  )cc"));
+}
+
 }  // namespace
 }  // namespace clang::tidy::nullability