Avoid breaking toolchain resolution if platform has defaulted constraint.

### Summary
See https://github.com/bazelbuild/bazel/issues/8778 and https://github.com/bazelbuild/bazel/issues/8274 for context / motivation. In summary, the presence of a `constraint_setting` with `default_constraint_value` in a Platform's constraints will cause toolchain resolution to break for all toolchains that do not explicitly set that constraint value. This makes `default_constraint_value` dangerous because setting it can break other rulesets composed into the same top-level workspace.

cc @jayconrod @m3rcuriel @katre

### Test Plan
I updated the unit test `SingleToolchainResolutionFunction`, verified it failed, then altered the implementation to pass. I also built `//src:bazel` and ran it with a test workspace to verify the end result worked as expected.

Test workspace:
```
$ cat WORKSPACE
register_toolchains("//:my_toolchain")
$ cat BUILD
load(":rules.bzl", "my_toolchain_info", "my_rule")

my_rule(name = "hello")
toolchain_type(name = "my_toolchain_type")
my_toolchain_info(name = "my_toolchain_info")
toolchain(
    name = "my_toolchain",
    toolchain = "//:my_toolchain_info",
    toolchain_type = "//:my_toolchain_type",
)

constraint_setting(
    name = "setting",
    default_constraint_value = ":value_a",
)
constraint_value(
    name = "value_a",
    constraint_setting = ":setting",
)
constraint_value(
    name = "value_b",
    constraint_setting = ":setting",
)
platform(
    name = "platform_a",
    constraint_values = ["//:value_a"],
)
platform(
    name = "platform_b",
    constraint_values = ["//:value_b"],
)

$ cat rules.bzl
def _my_toolchain_info(ctx):
    return platform_common.ToolchainInfo()

my_toolchain_info = rule(_my_toolchain_info)

def _my_rule(ctx):
    pass

my_rule = rule(_my_rule, toolchains = ["//:my_toolchain_type"])
```

Before:
```
$ bazel build --toolchain_resolution_debug --host_platform=//:platform_b //:hello
[...]
INFO: ToolchainResolution: Looking for toolchain of type //:my_toolchain_type...
INFO: ToolchainResolution:   Considering toolchain //:my_toolchain_info...
INFO: ToolchainResolution:     Toolchain constraint //:setting has value //:value_a, which does not match value //:value_b from the target platform //:platform_b
INFO: ToolchainResolution:   Rejected toolchain //:my_toolchain_info, because of target platform mismatch
INFO: ToolchainResolution:   No toolchains found
ERROR: While resolving toolchains for target //:hello: no matching toolchains found for types //:my_toolchain_type
```

After:
```
$ bazel build --toolchain_resolution_debug --host_platform=//:platform_b //:hello
[...]
INFO: ToolchainResolution: Looking for toolchain of type //:my_toolchain_type...
INFO: ToolchainResolution:   Considering toolchain //:my_toolchain_info...
INFO: ToolchainResolution:   For toolchain type //:my_toolchain_type, possible execution platforms and toolchains: {//:platform_b -> //:my_toolchain_info}
INFO: ToolchainResolution: Selected execution platform //:platform_b, type //:my_toolchain_type -> toolchain //:my_toolchain_info
INFO: ToolchainResolution: Selected execution platform //:platform_b,
INFO: Analyzed target //:hello (9 packages loaded, 27 targets configured).
[...]
```

Closes #10102.

PiperOrigin-RevId: 278645171
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/platform/ConstraintCollection.java b/src/main/java/com/google/devtools/build/lib/analysis/platform/ConstraintCollection.java
index ab791a4..f4dfdb2 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/platform/ConstraintCollection.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/platform/ConstraintCollection.java
@@ -185,7 +185,7 @@
       return true;
     }
 
-    // Then, check the parent, directly to ignore defaults.
+    // Then, check the parent.
     if (parent() != null) {
       return parent().has(constraint);
     }
@@ -193,6 +193,20 @@
     return constraint.hasDefaultConstraintValue();
   }
 
+  public boolean hasWithoutDefault(ConstraintSettingInfo constraint) {
+    // First, check locally.
+    if (constraints().containsKey(constraint)) {
+      return true;
+    }
+
+    // Then, check the parent, directly to ignore defaults.
+    if (parent() != null) {
+      return parent().hasWithoutDefault(constraint);
+    }
+
+    return false;
+  }
+
   /**
    * Returns the {@link ConstraintValueInfo} for the given {@link ConstraintSettingInfo}, or {@code
    * null} if none exists.
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/SingleToolchainResolutionFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/SingleToolchainResolutionFunction.java
index 1e37fe4..42b4fc9 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/SingleToolchainResolutionFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/SingleToolchainResolutionFunction.java
@@ -214,7 +214,21 @@
     // Check every constraint_setting in either the toolchain or the platform.
     ImmutableSet<ConstraintSettingInfo> mismatchSettings =
         toolchainConstraints.diff(platform.constraints());
+    boolean matches = true;
     for (ConstraintSettingInfo mismatchSetting : mismatchSettings) {
+      // If a constraint_setting has a default_constraint_value, and the platform
+      // sets a non-default constraint value for the same constraint_setting, then
+      // even toolchains with no reference to that constraint_setting will detect
+      // a mismatch here. This manifests as a toolchain resolution failure (#8778).
+      //
+      // To allow combining rulesets with their own toolchains in a single top-level
+      // workspace, toolchains that do not reference a constraint_setting should not
+      // be forced to match with it.
+      if (!toolchainConstraints.hasWithoutDefault(mismatchSetting)) {
+        continue;
+      }
+      matches = false;
+
       debugMessage(
           eventHandler,
           "    Toolchain constraint %s has value %s, "
@@ -229,7 +243,7 @@
           platformType,
           platform.label());
     }
-    return mismatchSettings.isEmpty();
+    return matches;
   }
 
   @Nullable
diff --git a/src/test/java/com/google/devtools/build/lib/rules/platform/ToolchainTestCase.java b/src/test/java/com/google/devtools/build/lib/rules/platform/ToolchainTestCase.java
index 1fb12ce..dc12122 100644
--- a/src/test/java/com/google/devtools/build/lib/rules/platform/ToolchainTestCase.java
+++ b/src/test/java/com/google/devtools/build/lib/rules/platform/ToolchainTestCase.java
@@ -44,8 +44,10 @@
   public PlatformInfo macPlatform;
 
   public ConstraintSettingInfo setting;
+  public ConstraintSettingInfo defaultedSetting;
   public ConstraintValueInfo linuxConstraint;
   public ConstraintValueInfo macConstraint;
+  public ConstraintValueInfo defaultedConstraint;
 
   public Label testToolchainTypeLabel;
   public ToolchainTypeInfo testToolchainType;
@@ -101,28 +103,40 @@
         "constraint_value(name = 'linux',",
         "    constraint_setting = ':os')",
         "constraint_value(name = 'mac',",
-        "    constraint_setting = ':os')");
+        "    constraint_setting = ':os')",
+        "constraint_setting(name = 'setting_with_default',",
+        "    default_constraint_value = ':default_value')",
+        "constraint_value(name = 'default_value',",
+        "    constraint_setting = ':setting_with_default')",
+        "constraint_value(name = 'non_default_value',",
+        "    constraint_setting = ':setting_with_default')");
 
     scratch.file(
         "platforms/BUILD",
         "platform(name = 'linux',",
-        "    constraint_values = ['//constraints:linux'])",
+        "    constraint_values = ['//constraints:linux', '//constraints:non_default_value'])",
         "platform(name = 'mac',",
-        "    constraint_values = ['//constraints:mac'])");
+        "    constraint_values = ['//constraints:mac', '//constraints:non_default_value'])");
 
     setting = ConstraintSettingInfo.create(makeLabel("//constraints:os"));
     linuxConstraint = ConstraintValueInfo.create(setting, makeLabel("//constraints:linux"));
     macConstraint = ConstraintValueInfo.create(setting, makeLabel("//constraints:mac"));
+    defaultedSetting =
+        ConstraintSettingInfo.create(makeLabel("//constraints:setting_with_default"));
+    defaultedConstraint =
+        ConstraintValueInfo.create(defaultedSetting, makeLabel("//constraints:non_default_value"));
 
     linuxPlatform =
         PlatformInfo.builder()
             .setLabel(makeLabel("//platforms:linux"))
             .addConstraint(linuxConstraint)
+            .addConstraint(defaultedConstraint)
             .build();
     macPlatform =
         PlatformInfo.builder()
             .setLabel(makeLabel("//platforms:mac"))
             .addConstraint(macConstraint)
+            .addConstraint(defaultedConstraint)
             .build();
   }
 
diff --git a/src/test/shell/bazel/toolchain_test.sh b/src/test/shell/bazel/toolchain_test.sh
index 51c0996..e29a454 100755
--- a/src/test/shell/bazel/toolchain_test.sh
+++ b/src/test/shell/bazel/toolchain_test.sh
@@ -1105,12 +1105,21 @@
 constraint_value(name = 'value_foo', constraint_setting = ':setting1')
 constraint_value(name = 'value_bar', constraint_setting = ':setting1')
 
+# Default constraint values don't block toolchain resolution.
+constraint_setting(name = 'setting2', default_constraint_value = ':value_unused')
+constraint_value(name = 'value_unused', constraint_setting = ':setting2')
+
 platform(
     name = 'platform_default',
-    constraint_values = [])
+    constraint_values = [
+      ':value_unused',
+    ])
 platform(
     name = 'platform_no_default',
-    constraint_values = [':value_bar'])
+    constraint_values = [
+      ':value_bar',
+      ':value_unused',
+    ])
 EOF
 
   # Add test toolchains using the constraints.
@@ -1135,7 +1144,7 @@
     toolchain_type = '//toolchain:test_toolchain',
     exec_compatible_with = [],
     target_compatible_with = [
-      # No constraint set, takes the default.
+      '//platforms:value_foo',
     ],
     toolchain = ':test_toolchain_impl_foo',
     visibility = ['//visibility:public'])
@@ -1144,7 +1153,6 @@
     toolchain_type = '//toolchain:test_toolchain',
     exec_compatible_with = [],
     target_compatible_with = [
-      # Explicitly sets a non-default value.
       '//platforms:value_bar',
     ],
     toolchain = ':test_toolchain_impl_bar',