Restrict noneable parameters to be of type Object

This fixes a number of crash bugs, as passing None to these "noneable" parameters had resulted in a crash.
Technically, this change *appears* to change the API. However, as these params were never truly successfully "noneable", this is not an incompatible change.

RELNOTES: None.
PiperOrigin-RevId: 277518828
diff --git a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/WorkspaceGlobalsApi.java b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/WorkspaceGlobalsApi.java
index 97d36cb..5a00bde 100644
--- a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/WorkspaceGlobalsApi.java
+++ b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/WorkspaceGlobalsApi.java
@@ -68,7 +68,6 @@
             name = "managed_directories",
             type = SkylarkDict.class,
             generic1 = String.class,
-            noneable = true,
             named = true,
             positional = false,
             defaultValue = "{}",
diff --git a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/cpp/BazelCcModuleApi.java b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/cpp/BazelCcModuleApi.java
index cba68bd..08447d5 100644
--- a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/cpp/BazelCcModuleApi.java
+++ b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/cpp/BazelCcModuleApi.java
@@ -117,7 +117,6 @@
                     + "Usually passed with -I. Propagated to dependents transitively.",
             positional = false,
             named = true,
-            noneable = true,
             defaultValue = "[]",
             type = SkylarkList.class),
         @Param(
@@ -129,7 +128,6 @@
                     + "transitively.",
             positional = false,
             named = true,
-            noneable = true,
             defaultValue = "[]",
             type = SkylarkList.class),
         @Param(
@@ -141,7 +139,6 @@
                     + "transitively.",
             positional = false,
             named = true,
-            noneable = true,
             defaultValue = "[]",
             type = SkylarkList.class),
         @Param(
@@ -152,7 +149,6 @@
                     + "dependents transitively.",
             positional = false,
             named = true,
-            noneable = true,
             defaultValue = "[]",
             type = SkylarkList.class),
         @Param(
@@ -178,7 +174,6 @@
             doc = "Additional list of compilation options.",
             positional = false,
             named = true,
-            noneable = true,
             defaultValue = "[]",
             type = SkylarkList.class),
         @Param(
@@ -282,7 +277,6 @@
             positional = false,
             named = true,
             defaultValue = "[]",
-            noneable = true,
             type = SkylarkList.class),
         @Param(
             name = "linking_contexts",
@@ -291,7 +285,6 @@
                     + "generated by this rule.",
             positional = false,
             named = true,
-            noneable = true,
             defaultValue = "[]",
             type = SkylarkList.class),
         @Param(
@@ -307,7 +300,6 @@
             doc = "Only C++ supported for now. Do not use this parameter.",
             positional = false,
             named = true,
-            noneable = true,
             defaultValue = "'c++'",
             type = String.class),
         @Param(
@@ -315,7 +307,6 @@
             doc = "Can be either 'executable' or 'dynamic_library'.",
             positional = false,
             named = true,
-            noneable = true,
             defaultValue = "'executable'",
             type = String.class),
         @Param(
@@ -323,7 +314,6 @@
             doc = " True to link dependencies statically, False dynamically.",
             positional = false,
             named = true,
-            noneable = true,
             defaultValue = "True",
             type = Boolean.class),
         @Param(
diff --git a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/cpp/CcModuleApi.java b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/cpp/CcModuleApi.java
index fcf8898..2240e74 100644
--- a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/cpp/CcModuleApi.java
+++ b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/cpp/CcModuleApi.java
@@ -958,7 +958,6 @@
             positional = false,
             named = true,
             defaultValue = "[]",
-            noneable = true,
             type = SkylarkList.class),
         @Param(
             name = "linking_contexts",
@@ -967,7 +966,6 @@
                     + "artifact of the link() call, be it a binary or a library.",
             positional = false,
             named = true,
-            noneable = true,
             defaultValue = "[]",
             type = SkylarkList.class),
         @Param(
@@ -983,7 +981,6 @@
             doc = "Only C++ supported for now. Do not use this parameter.",
             positional = false,
             named = true,
-            noneable = true,
             defaultValue = "'c++'",
             type = String.class),
         @Param(
@@ -991,7 +988,6 @@
             doc = "Whether this library should always be linked.",
             positional = false,
             named = true,
-            noneable = true,
             defaultValue = "False",
             type = Boolean.class),
         @Param(
diff --git a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/cpp/GoWrapCcHelperApi.java b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/cpp/GoWrapCcHelperApi.java
index 84442f2..b4f919b 100644
--- a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/cpp/GoWrapCcHelperApi.java
+++ b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/cpp/GoWrapCcHelperApi.java
@@ -194,8 +194,6 @@
             name = "gopkg",
             positional = false,
             named = true,
-            defaultValue = "None",
-            noneable = true,
             allowedTypes = {@ParamType(type = NoneType.class), @ParamType(type = FileApi.class)}),
         @Param(name = "export", positional = false, named = true, type = FileApi.class),
         @Param(name = "swig_out_go", positional = false, named = true, type = FileApi.class),
@@ -213,8 +211,6 @@
             name = "gopkg",
             positional = false,
             named = true,
-            defaultValue = "None",
-            noneable = true,
             allowedTypes = {@ParamType(type = NoneType.class), @ParamType(type = FileApi.class)}),
       })
   public NestedSet<FileT> getGopackageFiles(
diff --git a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/platform/ConstraintCollectionApi.java b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/platform/ConstraintCollectionApi.java
index ef00565..fe66df4 100644
--- a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/platform/ConstraintCollectionApi.java
+++ b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/platform/ConstraintCollectionApi.java
@@ -51,8 +51,6 @@
         @Param(
             name = "constraint",
             type = ConstraintSettingInfoApi.class,
-            defaultValue = "None",
-            noneable = true,
             named = true,
             doc = "The constraint setting to fetch the value for.")
       },
@@ -67,8 +65,6 @@
         @Param(
             name = "constraint",
             type = ConstraintSettingInfoApi.class,
-            defaultValue = "None",
-            noneable = true,
             named = true,
             doc = "The constraint setting to check.")
       },
diff --git a/src/main/java/com/google/devtools/build/lib/skylarkinterface/processor/SkylarkCallableProcessor.java b/src/main/java/com/google/devtools/build/lib/skylarkinterface/processor/SkylarkCallableProcessor.java
index 2e6c37a..0a98d5c 100644
--- a/src/main/java/com/google/devtools/build/lib/skylarkinterface/processor/SkylarkCallableProcessor.java
+++ b/src/main/java/com/google/devtools/build/lib/skylarkinterface/processor/SkylarkCallableProcessor.java
@@ -59,6 +59,9 @@
  *       both.
  *   <li>Parameters may not specify their generic types (they must use the <code>?</code> wildcard
  *       exclusively.
+ *   <li>Noneable parameters must have java parameter type Object (as the actual value may be either
+ *       {@code None} or a value of a non-{@code None} type, which do not share a superclass other
+ *       than Object (or SkylarkValue, which is typically no more descriptive than Object).
  *   <li>Each parameter must be positional or named (or both).
  *   <li>Positional-only parameters must be specified before any named parameters.
  *   <li>Positional parameters must be specified before any non-positional parameters.
@@ -224,21 +227,38 @@
     boolean allowPositionalOnlyNext = true;
     boolean allowNonDefaultPositionalNext = true;
 
+    int paramIndex = 0;
     for (Param parameter : annotation.parameters()) {
+      if (parameter.noneable()) {
+        VariableElement methodParam = methodElement.getParameters().get(paramIndex);
+        if (!"java.lang.Object".equals(methodParam.asType().toString())) {
+          throw new SkylarkCallableProcessorException(
+              methodElement,
+              String.format(
+                  "Expected type 'Object' but got type '%s' for noneable parameter '%s'. The "
+                      + "argument for a noneable parameter may be None, so the java parameter "
+                      + "must be compatible with the type of None as well as possible non-None "
+                      + "values.",
+                  methodParam.asType(), methodParam.getSimpleName()));
+        }
+      } else { // !parameter.noneable()
+        if ("None".equals(parameter.defaultValue())) {
+          throw new SkylarkCallableProcessorException(
+              methodElement,
+              String.format(
+                  "Parameter '%s' has 'None' default value but is not noneable. "
+                      + "(If this is intended as a mandatory parameter, leave the defaultValue "
+                      + "field empty)",
+                  parameter.name()));
+        }
+      }
+
       if (!parameter.positional() && !parameter.named()) {
         throw new SkylarkCallableProcessorException(
             methodElement,
             String.format("Parameter '%s' must be either positional or named",
                 parameter.name()));
       }
-      if ("None".equals(parameter.defaultValue()) && !parameter.noneable()) {
-        throw new SkylarkCallableProcessorException(
-            methodElement,
-            String.format("Parameter '%s' has 'None' default value but is not noneable. "
-                    + "(If this is intended as a mandatory parameter, leave the defaultValue field "
-                    + "empty)",
-                parameter.name()));
-      }
       if ((parameter.allowedTypes().length > 0)
           && (!"java.lang.Object".equals(paramTypeFieldCanonicalName(parameter)))) {
         throw new SkylarkCallableProcessorException(
@@ -286,6 +306,7 @@
         // No positional-only parameters can come after this parameter.
         allowPositionalOnlyNext = false;
       }
+      paramIndex++;
     }
   }
 
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/MethodLibrary.java b/src/main/java/com/google/devtools/build/lib/syntax/MethodLibrary.java
index 04f6144..526d9b1 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/MethodLibrary.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/MethodLibrary.java
@@ -189,8 +189,7 @@
             doc = "Return results in descending order.",
             named = true,
             defaultValue = "False",
-            positional = false,
-            noneable = true)
+            positional = false)
       },
       useLocation = true,
       useStarlarkThread = true)
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/SkylarkDict.java b/src/main/java/com/google/devtools/build/lib/syntax/SkylarkDict.java
index 3a7660a..90682ec 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/SkylarkDict.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/SkylarkDict.java
@@ -187,13 +187,14 @@
       },
       useLocation = true,
       useStarlarkThread = true)
-  public Object setdefault(K key, V defaultValue, Location loc, StarlarkThread thread)
+  @SuppressWarnings("unchecked") // Cast of value to V
+  public Object setdefault(K key, Object defaultValue, Location loc, StarlarkThread thread)
       throws EvalException {
     Object value = get(key);
     if (value != null) {
       return value;
     }
-    put(key, defaultValue, loc, thread);
+    put(key, (V) defaultValue, loc, thread);
     return defaultValue;
   }
 
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/SkylarkList.java b/src/main/java/com/google/devtools/build/lib/syntax/SkylarkList.java
index 5dc7c41..479b08eb 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/SkylarkList.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/SkylarkList.java
@@ -476,9 +476,10 @@
         },
         useLocation = true,
         useStarlarkThread = true)
-    public Runtime.NoneType append(E item, Location loc, StarlarkThread thread)
+    @SuppressWarnings("unchecked") // Cast of Object item to E
+    public Runtime.NoneType append(Object item, Location loc, StarlarkThread thread)
         throws EvalException {
-      add(item, loc, thread.mutability());
+      add((E) item, loc, thread.mutability());
       return Runtime.NONE;
     }
 
@@ -502,9 +503,10 @@
         },
         useLocation = true,
         useStarlarkThread = true)
-    public Runtime.NoneType insert(Integer index, E item, Location loc, StarlarkThread thread)
+    @SuppressWarnings("unchecked") // Cast of Object item to E
+    public Runtime.NoneType insert(Integer index, Object item, Location loc, StarlarkThread thread)
         throws EvalException {
-      add(EvalUtils.clampRangeEndpoint(index, size()), item, loc, thread.mutability());
+      add(EvalUtils.clampRangeEndpoint(index, size()), (E) item, loc, thread.mutability());
       return Runtime.NONE;
     }
 
diff --git a/src/test/java/com/google/devtools/build/lib/skylarkinterface/processor/SkylarkCallableProcessorTest.java b/src/test/java/com/google/devtools/build/lib/skylarkinterface/processor/SkylarkCallableProcessorTest.java
index c9d3895..1aad801 100644
--- a/src/test/java/com/google/devtools/build/lib/skylarkinterface/processor/SkylarkCallableProcessorTest.java
+++ b/src/test/java/com/google/devtools/build/lib/skylarkinterface/processor/SkylarkCallableProcessorTest.java
@@ -376,4 +376,15 @@
             "Parameter one has generic type "
                 + "com.google.devtools.build.lib.syntax.SkylarkDict<?,java.lang.String>");
   }
+
+  @Test
+  public void testInvalidNoneableParameter() throws Exception {
+    assertAbout(javaSource())
+        .that(getFile("InvalidNoneableParameter.java"))
+        .processedWith(new SkylarkCallableProcessor())
+        .failsToCompile()
+        .withErrorContaining(
+            "Expected type 'Object' but got type 'java.lang.String' "
+                + "for noneable parameter 'aParameter'.");
+  }
 }
diff --git a/src/test/java/com/google/devtools/build/lib/skylarkinterface/processor/testsources/GoldenCase.java b/src/test/java/com/google/devtools/build/lib/skylarkinterface/processor/testsources/GoldenCase.java
index 2403fcd..de7f3f1 100644
--- a/src/test/java/com/google/devtools/build/lib/skylarkinterface/processor/testsources/GoldenCase.java
+++ b/src/test/java/com/google/devtools/build/lib/skylarkinterface/processor/testsources/GoldenCase.java
@@ -76,16 +76,21 @@
     return 0;
   }
 
-  @SkylarkCallable(name = "three_arg_method_with_ast",
+  @SkylarkCallable(
+      name = "three_arg_method_with_ast",
       documented = false,
       parameters = {
-          @Param(name = "one", type = String.class, named = true),
-          @Param(name = "two", type = Integer.class, named = true),
-          @Param(name = "three", type = String.class, named = true,
-              defaultValue = "None", noneable = true),
+        @Param(name = "one", type = String.class, named = true),
+        @Param(name = "two", type = Integer.class, named = true),
+        @Param(
+            name = "three",
+            type = String.class,
+            named = true,
+            defaultValue = "None",
+            noneable = true),
       },
       useAst = true)
-  public String threeArgMethod(String one, Integer two, String three, FuncallExpression ast) {
+  public String threeArgMethod(String one, Integer two, Object three, FuncallExpression ast) {
     return "bar";
   }
 
diff --git a/src/test/java/com/google/devtools/build/lib/skylarkinterface/processor/testsources/InvalidNoneableParameter.java b/src/test/java/com/google/devtools/build/lib/skylarkinterface/processor/testsources/InvalidNoneableParameter.java
new file mode 100644
index 0000000..69fbb36
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/skylarkinterface/processor/testsources/InvalidNoneableParameter.java
@@ -0,0 +1,35 @@
+// Copyright 2019 The Bazel Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//    http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.devtools.build.lib.skylarkinterface.processor.testsources;
+
+import com.google.devtools.build.lib.skylarkinterface.Param;
+import com.google.devtools.build.lib.skylarkinterface.SkylarkCallable;
+
+/**
+ * Test case for a SkylarkCallable method which has a parameter with both type and allowedTypes
+ * specified.
+ */
+public class InvalidNoneableParameter {
+
+  @SkylarkCallable(
+      name = "invalid_noneable_parameter",
+      documented = false,
+      parameters = {
+        @Param(name = "a_parameter", type = String.class, noneable = true, named = true)
+      })
+  public Integer invalidNoneableParameter(String aParameter) {
+    return 42;
+  }
+}