native.existing_rule() should not see finalizer-instantiated targets
Working towards https://github.com/bazelbuild/bazel/issues/23160
PiperOrigin-RevId: 678773063
Change-Id: Iea8f319e8c6dae9a735420707f0d0a799df6fabd
diff --git a/src/main/java/com/google/devtools/build/lib/packages/Package.java b/src/main/java/com/google/devtools/build/lib/packages/Package.java
index b8d7e8f..1b8efc1 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/Package.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/Package.java
@@ -1728,6 +1728,24 @@
}
/**
+ * Returns a non-finalizer-instantiated rule target with the provided name belonging to this
+ * package at the time of this call. If such a rule target cannot be returned, returns null.
+ */
+ // TODO(https://github.com/bazelbuild/bazel/issues/23765): when we restrict
+ // native.existing_rule() to be usable only in finalizer context, we can replace this method
+ // with {@code getRulesSnapshotView().get(name)}; we don't do so at present because we do not
+ // want to make unnecessary snapshots.
+ @Nullable
+ Rule getNonFinalizerInstantiatedRule(String name) {
+ if (rulesSnapshotViewForFinalizers != null) {
+ return rulesSnapshotViewForFinalizers.get(name);
+ } else {
+ Target target = regEnv.getTargetMap().get(name);
+ return target instanceof Rule ? (Rule) target : null;
+ }
+ }
+
+ /**
* Creates an input file target in this package with the specified name, if it does not yet
* exist.
*
diff --git a/src/main/java/com/google/devtools/build/lib/packages/StarlarkNativeModule.java b/src/main/java/com/google/devtools/build/lib/packages/StarlarkNativeModule.java
index d0f253e..4cc70c6 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/StarlarkNativeModule.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/StarlarkNativeModule.java
@@ -434,8 +434,8 @@
}
Package.Builder pkgBuilder =
Package.Builder.fromOrFailDisallowNonFinalizerMacros(thread, "existing_rule()");
- Target target = pkgBuilder.getTarget(name);
- if (target instanceof Rule rule) {
+ @Nullable Rule rule = pkgBuilder.getNonFinalizerInstantiatedRule(name);
+ if (rule != null) {
return new ExistingRuleView(rule);
} else {
return Starlark.NONE;
diff --git a/src/test/java/com/google/devtools/build/lib/packages/RuleFinalizerTest.java b/src/test/java/com/google/devtools/build/lib/packages/RuleFinalizerTest.java
index 6fa16d3..855771f 100644
--- a/src/test/java/com/google/devtools/build/lib/packages/RuleFinalizerTest.java
+++ b/src/test/java/com/google/devtools/build/lib/packages/RuleFinalizerTest.java
@@ -200,11 +200,38 @@
}
@Test
- public void finalizer_nativeExistingRules_seesOnlyNonFinalizerTargets_inAllLexicalPositions()
+ public void finalizer_nativeExistingRule_seesOnlyNonFinalizerTargets_inAllLexicalPositions()
throws Exception {
scratch.file(
"pkg/foo.bzl",
"""
+ EXPECTED = [
+ "top_level_lexically_before_finalizer",
+ "macro_lexically_before_finalizer_inner_lib",
+ "top_level_lexically_after_finalizer",
+ "macro_lexically_after_finalizer_inner_lib",
+ ]
+
+ UNEXPECTED = [
+ "finalizer_inner_lib",
+ "finalizer_inner_macro_inner_lib",
+ "finalizer_inner_finalizer_inner_lib",
+ "other_finalizer_inner_lib",
+ "other_finalizer_inner_macro_inner_lib",
+ "other_finalizer_inner_finalizer_inner_lib",
+ ]
+
+ def check_existing_rules():
+ if (sorted(native.existing_rules().keys()) != sorted(EXPECTED)):
+ fail("native.existing_rules().keys(): " + native.existing_rules().keys())
+ for t in EXPECTED:
+ if native.existing_rule(t) == None:
+ fail("native.existing_rule(" + t + ") == None")
+ for t in UNEXPECTED:
+ if native.existing_rule(t) != None:
+ fail("native.existing_rule(" + t + ") != None")
+ print("native.existing_rules and native.existing_rule are as expected")
+
def _impl_macro(name):
native.cc_library(name = name + "_inner_lib")
@@ -212,8 +239,7 @@
def _impl_inner_finalizer(name):
native.cc_library(name = name + "_inner_lib")
- for r in native.existing_rules().values():
- print("saw " + r["name"])
+ check_existing_rules()
inner_finalizer = macro(implementation = _impl_inner_finalizer, finalizer = True)
@@ -221,8 +247,7 @@
native.cc_library(name = name + "_inner_lib")
my_macro(name = name + "_inner_macro")
inner_finalizer(name = name + "_inner_finalizer")
- for r in native.existing_rules().values():
- print("saw " + r["name"])
+ check_existing_rules()
my_finalizer = macro(implementation = _impl_finalizer, finalizer = True)
""");
@@ -240,15 +265,7 @@
Package pkg = getPackage("pkg");
assertPackageNotInError(pkg);
- assertContainsEventWithFrequency("saw top_level_lexically_before_finalizer", 4);
- assertContainsEventWithFrequency("saw macro_lexically_before_finalizer_inner_lib", 4);
- assertContainsEventWithFrequency("saw top_level_lexically_after_finalizer", 4);
- assertContainsEventWithFrequency("saw macro_lexically_after_finalizer_inner_lib", 4);
- assertDoesNotContainEvent("saw finalizer_inner_lib");
- assertDoesNotContainEvent("saw finalizer_inner_macro_inner_lib");
- assertDoesNotContainEvent("saw finalizer_inner_finalizer_inner_lib");
- assertDoesNotContainEvent("saw other_finalizer_inner_lib");
- assertDoesNotContainEvent("saw other_finalizer_inner_macro_inner_lib");
- assertDoesNotContainEvent("saw other_finalizer_inner_finalizer_inner_lib");
+ assertContainsEventWithFrequency(
+ "native.existing_rules and native.existing_rule are as expected", 4);
}
}