Enable rules to inherit the ExecutionPlatformConstraintsAllowed value.

PiperOrigin-RevId: 200247872
diff --git a/src/main/java/com/google/devtools/build/lib/packages/RuleClass.java b/src/main/java/com/google/devtools/build/lib/packages/RuleClass.java
index 330278f..78abb6f 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/RuleClass.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/RuleClass.java
@@ -209,13 +209,34 @@
      * Allows additional execution platform constraints to be added in the rule definition, which
      * apply to all targets of that rule.
      */
-    PER_RULE,
+    PER_RULE(1),
     /**
      * Users are allowed to specify additional execution platform constraints for each target, using
      * the 'exec_compatible_with' attribute. This also allows setting constraints in the rule
      * definition, like PER_RULE.
      */
-    PER_TARGET;
+    PER_TARGET(2);
+
+    private final int priority;
+
+    ExecutionPlatformConstraintsAllowed(int priority) {
+      this.priority = priority;
+    }
+
+    public int priority() {
+      return priority;
+    }
+
+    public static ExecutionPlatformConstraintsAllowed highestPriority(
+        ExecutionPlatformConstraintsAllowed first, ExecutionPlatformConstraintsAllowed... rest) {
+      ExecutionPlatformConstraintsAllowed result = first;
+      for (ExecutionPlatformConstraintsAllowed value : rest) {
+        if (result == null || result.priority() < value.priority()) {
+          result = value;
+        }
+      }
+      return result;
+    }
   }
 
   /**
@@ -668,7 +689,11 @@
 
         addRequiredToolchains(parent.getRequiredToolchains());
         supportsPlatforms = parent.supportsPlatforms;
-        // executionPlatformConstraintsAllowed is not inherited and takes the default.
+
+        // Make sure we use the highest priority value from all parents.
+        executionPlatformConstraintsAllowed(
+            ExecutionPlatformConstraintsAllowed.highestPriority(
+                executionPlatformConstraintsAllowed, parent.executionPlatformConstraintsAllowed()));
         addExecutionPlatformConstraints(parent.getExecutionPlatformConstraints());
 
         for (Attribute attribute : parent.getAttributes()) {
diff --git a/src/test/java/com/google/devtools/build/lib/packages/RuleClassTest.java b/src/test/java/com/google/devtools/build/lib/packages/RuleClassTest.java
index 088e7db..bc9d068 100644
--- a/src/test/java/com/google/devtools/build/lib/packages/RuleClassTest.java
+++ b/src/test/java/com/google/devtools/build/lib/packages/RuleClassTest.java
@@ -1139,11 +1139,58 @@
 
     RuleClass.Builder childRuleClassBuilder =
         new RuleClass.Builder("childRuleClass", RuleClassType.NORMAL, false, parentRuleClass)
+            .factory(DUMMY_CONFIGURED_TARGET_FACTORY);
+
+    RuleClass childRuleClass = childRuleClassBuilder.build();
+
+    assertThat(childRuleClass.executionPlatformConstraintsAllowed())
+        .isEqualTo(ExecutionPlatformConstraintsAllowed.PER_TARGET);
+    assertThat(childRuleClass.hasAttr("exec_compatible_with", LABEL_LIST)).isTrue();
+  }
+
+  @Test
+  public void testExecutionPlatformConstraints_inherit_multipleParents() {
+    RuleClass parentRuleClass1 =
+        new RuleClass.Builder("parentRuleClass1", RuleClassType.NORMAL, false)
+            .factory(DUMMY_CONFIGURED_TARGET_FACTORY)
+            .add(attr("tags", STRING_LIST))
+            .executionPlatformConstraintsAllowed(ExecutionPlatformConstraintsAllowed.PER_TARGET)
+            .build();
+    RuleClass parentRuleClass2 =
+        new RuleClass.Builder("$parentRuleClass2", RuleClassType.ABSTRACT, false)
+            .executionPlatformConstraintsAllowed(ExecutionPlatformConstraintsAllowed.PER_RULE)
+            .build();
+
+    RuleClass.Builder childRuleClassBuilder =
+        new RuleClass.Builder(
+                "childRuleClass", RuleClassType.NORMAL, false, parentRuleClass1, parentRuleClass2)
+            .factory(DUMMY_CONFIGURED_TARGET_FACTORY);
+
+    RuleClass childRuleClass = childRuleClassBuilder.build();
+
+    assertThat(childRuleClass.executionPlatformConstraintsAllowed())
+        .isEqualTo(ExecutionPlatformConstraintsAllowed.PER_TARGET);
+    assertThat(childRuleClass.hasAttr("exec_compatible_with", LABEL_LIST)).isTrue();
+  }
+
+  @Test
+  public void testExecutionPlatformConstraints_inherit_parentAllowsPerTarget_override() {
+    RuleClass parentRuleClass =
+        new RuleClass.Builder("parentRuleClass", RuleClassType.NORMAL, false)
+            .factory(DUMMY_CONFIGURED_TARGET_FACTORY)
+            .add(attr("tags", STRING_LIST))
+            .executionPlatformConstraintsAllowed(ExecutionPlatformConstraintsAllowed.PER_TARGET)
+            .build();
+
+    RuleClass.Builder childRuleClassBuilder =
+        new RuleClass.Builder("childRuleClass", RuleClassType.NORMAL, false, parentRuleClass)
             .factory(DUMMY_CONFIGURED_TARGET_FACTORY)
             .executionPlatformConstraintsAllowed(ExecutionPlatformConstraintsAllowed.PER_RULE);
 
     RuleClass childRuleClass = childRuleClassBuilder.build();
 
+    assertThat(childRuleClass.executionPlatformConstraintsAllowed())
+        .isEqualTo(ExecutionPlatformConstraintsAllowed.PER_RULE);
     assertThat(childRuleClass.hasAttr("exec_compatible_with", LABEL_LIST)).isFalse();
   }
 
@@ -1162,6 +1209,8 @@
 
     RuleClass childRuleClass = childRuleClassBuilder.build();
 
+    assertThat(childRuleClass.executionPlatformConstraintsAllowed())
+        .isEqualTo(ExecutionPlatformConstraintsAllowed.PER_TARGET);
     assertThat(childRuleClass.hasAttr("exec_compatible_with", LABEL_LIST)).isTrue();
   }