Allow dict() and dict.update() to take arbitrary maps, not necessarily dicts.

In particular, this allows immutable view objects returned by
native.existing_rule/s() with --incompatible_existing_rules_immutable_view to
be used in dict() and dict.update().

Partially addresses https://github.com/bazelbuild/bazel/issues/13605

PiperOrigin-RevId: 478527510
Change-Id: Ic796df9d556027c5d797b03ca85aebf1c90165cd
diff --git a/src/main/java/net/starlark/java/eval/Dict.java b/src/main/java/net/starlark/java/eval/Dict.java
index 919eeab..ca3fcb7 100644
--- a/src/main/java/net/starlark/java/eval/Dict.java
+++ b/src/main/java/net/starlark/java/eval/Dict.java
@@ -339,10 +339,10 @@
 
   // Common implementation of dict(pairs, **kwargs) and dict.update(pairs, **kwargs).
   static void update(
-      String funcname, Dict<Object, Object> dict, Object pairs, Dict<String, Object> kwargs)
+      String funcname, Dict<Object, Object> dict, Object pairs, Map<String, Object> kwargs)
       throws EvalException {
-    if (pairs instanceof Dict) { // common case
-      dict.putEntries((Dict<?, ?>) pairs);
+    if (pairs instanceof Map) { // common case
+      dict.putEntries((Map<?, ?>) pairs);
     } else {
       Iterable<?> iterable;
       try {
diff --git a/src/test/java/com/google/devtools/build/lib/packages/NativeExistingRulesTest.java b/src/test/java/com/google/devtools/build/lib/packages/NativeExistingRulesTest.java
index 5252e06..dbef3a5 100644
--- a/src/test/java/com/google/devtools/build/lib/packages/NativeExistingRulesTest.java
+++ b/src/test/java/com/google/devtools/build/lib/packages/NativeExistingRulesTest.java
@@ -337,6 +337,52 @@
   }
 
   @Test
+  public void existingRule_asDictArgument() throws Exception {
+    scratch.file(
+        "test/test.bzl",
+        "def save_as_dict(r):",
+        "  test.save('type(dict(r))', type(dict(r)))",
+        "  test.save('dict(r)[\"name\"]', dict(r)[\"name\"])",
+        "  test.save('dict(r)[\"kind\"]', dict(r)[\"kind\"])");
+    scratch.file(
+        "test/BUILD",
+        "load('//test:test.bzl', 'save_as_dict')", //
+        "cc_library(",
+        "    name ='rulename',",
+        ")",
+        "save_as_dict(existing_rule('rulename'))");
+    getConfiguredTarget("//test:rulename");
+    assertThat(getSaved("type(dict(r))")).isEqualTo("dict");
+    assertThat(getSaved("dict(r)[\"name\"]")).isEqualTo("rulename");
+    assertThat(getSaved("dict(r)[\"kind\"]")).isEqualTo("cc_library");
+  }
+
+  @Test
+  public void existingRule_asDictUpdateArgument() throws Exception {
+    // We do not test `existing_rule(r).update({...})` because `existing_rule(r)` may be immutable
+    // (as verified by other test cases).
+    scratch.file(
+        "test/test.bzl",
+        "def save_as_updated_dict(r):",
+        "  updated_dict = {'name': 'dictname', 'dictkey': 1}",
+        "  updated_dict.update(r)",
+        "  test.save('updated_dict[\"name\"]', updated_dict[\"name\"])",
+        "  test.save('updated_dict[\"kind\"]', updated_dict[\"kind\"])",
+        "  test.save('updated_dict[\"dictkey\"]', updated_dict[\"dictkey\"])");
+    scratch.file(
+        "test/BUILD",
+        "load('//test:test.bzl', 'save_as_updated_dict')", //
+        "cc_library(",
+        "    name ='rulename',",
+        ")",
+        "save_as_updated_dict(existing_rule('rulename'))");
+    getConfiguredTarget("//test:rulename");
+    assertThat(getSaved("updated_dict[\"name\"]")).isEqualTo("rulename");
+    assertThat(getSaved("updated_dict[\"kind\"]")).isEqualTo("cc_library");
+    assertThat(getSaved("updated_dict[\"dictkey\"]")).isEqualTo(StarlarkInt.of(1));
+  }
+
+  @Test
   public void existingRule_asKwargs() throws Exception {
     scratch.file(
         "test/test.bzl",