Reinstate mutable maps, again.

--
MOS_MIGRATED_REVID=114860576
diff --git a/src/main/java/com/google/devtools/build/lib/rules/SkylarkAttr.java b/src/main/java/com/google/devtools/build/lib/rules/SkylarkAttr.java
index 01d4bc3..f99f598 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/SkylarkAttr.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/SkylarkAttr.java
@@ -15,7 +15,6 @@
 package com.google.devtools.build.lib.rules;
 
 import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Iterables;
 import com.google.devtools.build.lib.cmdline.Label;
 import com.google.devtools.build.lib.packages.Attribute;
@@ -34,6 +33,7 @@
 import com.google.devtools.build.lib.syntax.FuncallExpression;
 import com.google.devtools.build.lib.syntax.Runtime;
 import com.google.devtools.build.lib.syntax.SkylarkCallbackFunction;
+import com.google.devtools.build.lib.syntax.SkylarkDict;
 import com.google.devtools.build.lib.syntax.SkylarkList;
 import com.google.devtools.build.lib.syntax.SkylarkSignatureProcessor;
 import com.google.devtools.build.lib.syntax.Type;
@@ -42,7 +42,6 @@
 import com.google.devtools.build.lib.util.FileTypeSet;
 
 import java.util.List;
-import java.util.Map;
 
 /**
  * A helper class to provide Attr module in Skylark.
@@ -106,12 +105,12 @@
       "the list of allowed values for the attribute. An error is raised if any other "
           + "value is given.";
 
-  private static boolean containsNonNoneKey(Map<String, Object> arguments, String key) {
+  private static boolean containsNonNoneKey(SkylarkDict<String, Object> arguments, String key) {
     return arguments.containsKey(key) && arguments.get(key) != Runtime.NONE;
   }
 
   private static Attribute.Builder<?> createAttribute(
-      Type<?> type, Map<String, Object> arguments, FuncallExpression ast, Environment env)
+      Type<?> type, SkylarkDict<String, Object> arguments, FuncallExpression ast, Environment env)
       throws EvalException, ConversionException {
     // We use an empty name now so that we can set it later.
     // This trick makes sense only in the context of Skylark (builtin rules should not use it).
@@ -192,7 +191,7 @@
   }
 
   private static Descriptor createAttrDescriptor(
-      Map<String, Object> kwargs, Type<?> type, FuncallExpression ast, Environment env)
+      SkylarkDict<String, Object> kwargs, Type<?> type, FuncallExpression ast, Environment env)
       throws EvalException {
     try {
       return new Descriptor(createAttribute(type, kwargs, ast, env));
@@ -202,7 +201,10 @@
   }
 
   private static Descriptor createNonconfigurableAttrDescriptor(
-      Map<String, Object> kwargs, Type<?> type, String whyNotConfigurable, FuncallExpression ast,
+      SkylarkDict<String, Object> kwargs,
+      Type<?> type,
+      String whyNotConfigurable,
+      FuncallExpression ast,
       Environment env) throws EvalException {
     try {
       return new Descriptor(
@@ -242,15 +244,15 @@
         public Descriptor invoke(
             Integer defaultInt,
             Boolean mandatory,
-            SkylarkList values,
+            SkylarkList<?> values,
             FuncallExpression ast,
             Environment env)
             throws EvalException {
           // TODO(bazel-team): Replace literal strings with constants.
           env.checkLoadingPhase("attr.int", ast.getLocation());
           return createAttrDescriptor(
-              EvalUtils.optionMap(
-                  DEFAULT_ARG, defaultInt, MANDATORY_ARG, mandatory, VALUES_ARG, values),
+              EvalUtils.<String, Object>optionMap(
+                  env, DEFAULT_ARG, defaultInt, MANDATORY_ARG, mandatory, VALUES_ARG, values),
               Type.INTEGER,
               ast,
               env);
@@ -287,14 +289,14 @@
         public Descriptor invoke(
             String defaultString,
             Boolean mandatory,
-            SkylarkList values,
+            SkylarkList<?> values,
             FuncallExpression ast,
             Environment env)
             throws EvalException {
           env.checkLoadingPhase("attr.string", ast.getLocation());
           return createAttrDescriptor(
-              EvalUtils.optionMap(
-                  DEFAULT_ARG, defaultString, MANDATORY_ARG, mandatory, VALUES_ARG, values),
+              EvalUtils.<String, Object>optionMap(
+                  env, DEFAULT_ARG, defaultString, MANDATORY_ARG, mandatory, VALUES_ARG, values),
               Type.STRING,
               ast,
               env);
@@ -372,7 +374,7 @@
             Boolean executable,
             Object allowFiles,
             Boolean mandatory,
-            SkylarkList providers,
+            SkylarkList<?> providers,
             Object allowRules,
             Boolean singleFile,
             Object cfg,
@@ -381,7 +383,8 @@
             throws EvalException {
           env.checkLoadingPhase("attr.label", ast.getLocation());
           return createAttrDescriptor(
-              EvalUtils.optionMap(
+              EvalUtils.<String, Object>optionMap(
+                  env,
                   DEFAULT_ARG,
                   defaultO,
                   EXECUTABLE_ARG,
@@ -428,7 +431,7 @@
   private static BuiltinFunction stringList =
       new BuiltinFunction("string_list") {
         public Descriptor invoke(
-            SkylarkList defaultList,
+            SkylarkList<?> defaultList,
             Boolean mandatory,
             Boolean nonEmpty,
             FuncallExpression ast,
@@ -436,8 +439,14 @@
             throws EvalException {
           env.checkLoadingPhase("attr.string_list", ast.getLocation());
           return createAttrDescriptor(
-              EvalUtils.optionMap(
-                  DEFAULT_ARG, defaultList, MANDATORY_ARG, mandatory, NON_EMPTY_ARG, nonEmpty),
+              EvalUtils.<String, Object>optionMap(
+                  env,
+                  DEFAULT_ARG,
+                  defaultList,
+                  MANDATORY_ARG,
+                  mandatory,
+                  NON_EMPTY_ARG,
+                  nonEmpty),
               Type.STRING_LIST,
               ast,
               env);
@@ -468,7 +477,7 @@
   private static BuiltinFunction intList =
       new BuiltinFunction("int_list") {
         public Descriptor invoke(
-            SkylarkList defaultList,
+            SkylarkList<?> defaultList,
             Boolean mandatory,
             Boolean nonEmpty,
             FuncallExpression ast,
@@ -476,8 +485,14 @@
             throws EvalException {
           env.checkLoadingPhase("attr.int_list", ast.getLocation());
           return createAttrDescriptor(
-              EvalUtils.optionMap(
-                  DEFAULT_ARG, defaultList, MANDATORY_ARG, mandatory, NON_EMPTY_ARG, nonEmpty),
+              EvalUtils.<String, Object>optionMap(
+                  env,
+                  DEFAULT_ARG,
+                  defaultList,
+                  MANDATORY_ARG,
+                  mandatory,
+                  NON_EMPTY_ARG,
+                  nonEmpty),
               Type.INTEGER_LIST,
               ast,
               env);
@@ -558,18 +573,20 @@
             Object defaultList,
             Object allowFiles,
             Object allowRules,
-            SkylarkList providers,
-            SkylarkList flags,
+            SkylarkList<?> providers,
+            SkylarkList<?> flags,
             Boolean mandatory,
             Boolean nonEmpty,
             Object cfg,
-            SkylarkList aspects,
+            SkylarkList<?> aspects,
             FuncallExpression ast,
             Environment env)
             throws EvalException {
           env.checkLoadingPhase("attr.label_list", ast.getLocation());
-          ImmutableMap<String, Object> kwargs = EvalUtils.optionMap(
-              DEFAULT_ARG, defaultList,
+          SkylarkDict<String, Object> kwargs = EvalUtils.<String, Object>optionMap(
+              env,
+              DEFAULT_ARG,
+              defaultList,
               ALLOW_FILES_ARG,
               allowFiles,
               ALLOW_RULES_ARG,
@@ -587,25 +604,13 @@
           try {
             Attribute.Builder<?> attribute = createAttribute(
                 BuildType.LABEL_LIST, kwargs, ast, env);
-
-            ImmutableList<SkylarkAspect> skylarkAspects = getSkylarkAspects(aspects);
+            ImmutableList<SkylarkAspect> skylarkAspects =
+                ImmutableList.copyOf(aspects.getContents(SkylarkAspect.class, "aspects"));
             return new Descriptor(attribute, skylarkAspects);
-          } catch (ConversionException e) {
-            throw new EvalException(ast.getLocation(), e.getMessage());
+          } catch (EvalException e) {
+            throw new EvalException(ast.getLocation(), e.getMessage(), e);
           }
         }
-
-        protected ImmutableList<SkylarkAspect> getSkylarkAspects(SkylarkList aspects)
-            throws ConversionException {
-          ImmutableList.Builder<SkylarkAspect> aspectBuilder = ImmutableList.builder();
-          for (Object aspect : aspects) {
-            if (!(aspect instanceof SkylarkAspect)) {
-              throw new ConversionException("Expected a list of aspects for 'aspects'");
-            }
-            aspectBuilder.add((SkylarkAspect) aspect);
-          }
-          return aspectBuilder.build();
-        }
       };
 
   @SkylarkSignature(
@@ -628,7 +633,8 @@
             throws EvalException {
           env.checkLoadingPhase("attr.bool", ast.getLocation());
           return createAttrDescriptor(
-              EvalUtils.optionMap(DEFAULT_ARG, defaultO, MANDATORY_ARG, mandatory),
+              EvalUtils.<String, Object>optionMap(
+                  env, DEFAULT_ARG, defaultO, MANDATORY_ARG, mandatory),
               Type.BOOLEAN,
               ast,
               env);
@@ -664,7 +670,8 @@
             throws EvalException {
           env.checkLoadingPhase("attr.output", ast.getLocation());
           return createNonconfigurableAttrDescriptor(
-              EvalUtils.optionMap(DEFAULT_ARG, defaultO, MANDATORY_ARG, mandatory),
+              EvalUtils.<String, Object>optionMap(
+                  env, DEFAULT_ARG, defaultO, MANDATORY_ARG, mandatory),
               BuildType.OUTPUT,
               "output paths are part of the static graph structure",
               ast,
@@ -706,8 +713,14 @@
             throws EvalException {
           env.checkLoadingPhase("attr.output_list", ast.getLocation());
           return createAttrDescriptor(
-              EvalUtils.optionMap(
-                  DEFAULT_ARG, defaultList, MANDATORY_ARG, mandatory, NON_EMPTY_ARG, nonEmpty),
+              EvalUtils.<String, Object>optionMap(
+                  env,
+                  DEFAULT_ARG,
+                  defaultList,
+                  MANDATORY_ARG,
+                  mandatory,
+                  NON_EMPTY_ARG,
+                  nonEmpty),
               BuildType.OUTPUT_LIST,
               ast,
               env);
@@ -722,7 +735,7 @@
     objectType = SkylarkAttr.class,
     returnType = Descriptor.class,
     optionalNamedOnly = {
-      @Param(name = DEFAULT_ARG, type = Map.class, defaultValue = "{}", doc = DEFAULT_DOC),
+      @Param(name = DEFAULT_ARG, type = SkylarkDict.class, defaultValue = "{}", doc = DEFAULT_DOC),
       @Param(name = MANDATORY_ARG, type = Boolean.class, defaultValue = "False", doc = MANDATORY_DOC
       ),
       @Param(name = NON_EMPTY_ARG, type = Boolean.class, defaultValue = "False", doc = NON_EMPTY_DOC
@@ -734,7 +747,7 @@
   private static BuiltinFunction stringDict =
       new BuiltinFunction("string_dict") {
         public Descriptor invoke(
-            Map<?, ?> defaultO,
+            SkylarkDict<?, ?> defaultO,
             Boolean mandatory,
             Boolean nonEmpty,
             FuncallExpression ast,
@@ -742,8 +755,8 @@
             throws EvalException {
           env.checkLoadingPhase("attr.string_dict", ast.getLocation());
           return createAttrDescriptor(
-              EvalUtils.optionMap(
-                  DEFAULT_ARG, defaultO, MANDATORY_ARG, mandatory, NON_EMPTY_ARG, nonEmpty),
+              EvalUtils.<String, Object>optionMap(
+                  env, DEFAULT_ARG, defaultO, MANDATORY_ARG, mandatory, NON_EMPTY_ARG, nonEmpty),
               Type.STRING_DICT,
               ast,
               env);
@@ -758,7 +771,7 @@
     objectType = SkylarkAttr.class,
     returnType = Descriptor.class,
     optionalNamedOnly = {
-      @Param(name = DEFAULT_ARG, type = Map.class, defaultValue = "{}", doc = DEFAULT_DOC),
+      @Param(name = DEFAULT_ARG, type = SkylarkDict.class, defaultValue = "{}", doc = DEFAULT_DOC),
       @Param(name = MANDATORY_ARG, type = Boolean.class, defaultValue = "False", doc = MANDATORY_DOC
       ),
       @Param(name = NON_EMPTY_ARG, type = Boolean.class, defaultValue = "False", doc = NON_EMPTY_DOC
@@ -770,7 +783,7 @@
   private static BuiltinFunction stringListDict =
       new BuiltinFunction("string_list_dict") {
         public Descriptor invoke(
-            Map<?, ?> defaultO,
+            SkylarkDict<?, ?> defaultO,
             Boolean mandatory,
             Boolean nonEmpty,
             FuncallExpression ast,
@@ -778,8 +791,8 @@
             throws EvalException {
           env.checkLoadingPhase("attr.string_list_dict", ast.getLocation());
           return createAttrDescriptor(
-              EvalUtils.optionMap(
-                  DEFAULT_ARG, defaultO, MANDATORY_ARG, mandatory, NON_EMPTY_ARG, nonEmpty),
+              EvalUtils.<String, Object>optionMap(
+                  env, DEFAULT_ARG, defaultO, MANDATORY_ARG, mandatory, NON_EMPTY_ARG, nonEmpty),
               Type.STRING_LIST_DICT,
               ast,
               env);
@@ -808,7 +821,8 @@
             throws EvalException {
           env.checkLoadingPhase("attr.license", ast.getLocation());
           return createNonconfigurableAttrDescriptor(
-              EvalUtils.optionMap(DEFAULT_ARG, defaultO, MANDATORY_ARG, mandatory),
+              EvalUtils.<String, Object>optionMap(
+                  env, DEFAULT_ARG, defaultO, MANDATORY_ARG, mandatory),
               BuildType.LICENSE,
               "loading phase license checking logic assumes non-configurable values",
               ast,