[gn] Use DCHECK in Target::info()

Follow-up to https://gn-review.googlesource.com/c/gn/+/26480.

As pointed out by Matt Stark (msta@), having a lazy
'info_.emplace(this)' fallback inside Target::info() could theoretically
allow concurrent mutation if info() were ever called on an unresolved
target in a multi-threaded context.

In production, Target::OnResolvedWithoutChecks() is always called before
any multi-threaded queries occur. Across the entire unit test suite (845
tests), only a single test (NinjaCBinaryTargetWriterTest.
DupeObjFileError) invoked NinjaCBinaryTargetWriter without calling
OnResolved() first.

By adding 'ASSERT_TRUE(target.OnResolved(&err))' to DupeObjFileError, we
can replace the lazy initialization in Target::info() with
'DCHECK(info_.has_value())', making info() strictly read-only and
branchless in release builds.

Note: 'info_' itself remains 'mutable' because ResolvedTargetData
queries receive 'const Target*' and lazily compute/populate the cache
fields inside TargetInfo (e.g., lib_dirs, inherited_libs). Keeping
'mutable' on 'info_' as a whole avoids scattering 'mutable' across ~20
individual fields inside TargetInfo and modifying all helper signatures.

TAG=agy
CONV=4cb5d931-60a8-4f44-8632-3e8d9fb10a8d
Change-Id: I6a697e0172473d38b80ca04ea0985c6dab8e3d44
Reviewed-on: https://gn-review.googlesource.com/c/gn/+/26500
Commit-Queue: Takuto Ikuta <tikuta@google.com>
Reviewed-by: Matt Stark <msta@google.com>
diff --git a/src/gn/ninja_c_binary_target_writer_unittest.cc b/src/gn/ninja_c_binary_target_writer_unittest.cc
index 34a473f..2f4977d 100644
--- a/src/gn/ninja_c_binary_target_writer_unittest.cc
+++ b/src/gn/ninja_c_binary_target_writer_unittest.cc
@@ -1608,10 +1608,12 @@
 // This is dependent on the toolchain's object file mapping.
 TEST_F(NinjaCBinaryTargetWriterTest, DupeObjFileError) {
   TestWithScope setup;
+  Err err;
   TestTarget target(setup, "//foo:bar", Target::EXECUTABLE);
   target.sources().push_back(SourceFile("//a.cc"));
   target.sources().push_back(SourceFile("//a.cc"));
   target.source_types_used().Set(SourceFile::SOURCE_CPP);
+  ASSERT_TRUE(target.OnResolved(&err));
 
   EXPECT_FALSE(scheduler().is_failed());
 
diff --git a/src/gn/target.h b/src/gn/target.h
index 17995f7..17e96d4 100644
--- a/src/gn/target.h
+++ b/src/gn/target.h
@@ -706,9 +706,7 @@
   };
 
   TargetInfo& info() const {
-    if (!info_.has_value()) {
-      info_.emplace(this);
-    }
+    DCHECK(info_.has_value());
     return *info_;
   }