bazel syntax: delete BaseFunction.name field

Leave getName method abstract.
Some subclasses want a field, others need a method.

BaseFunction is one step closer to becoming an interface.

Also:
- eliminate ProviderFromFunction, which was not an abstraction but merely
  code-reuse hack.
- inline FakeStarlarkCallable class into sole point of use.
PiperOrigin-RevId: 280185359
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleClassFunctions.java b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleClassFunctions.java
index b30f3c2..8a14c07 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleClassFunctions.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleClassFunctions.java
@@ -611,7 +611,7 @@
         RuleClassType type,
         ImmutableList<Pair<String, SkylarkAttr.Descriptor>> attributes,
         Location definitionLocation) {
-      super("rule", FunctionSignature.KWARGS);
+      super(FunctionSignature.KWARGS);
       this.builder = builder;
       this.type = type;
       this.attributes = attributes;
@@ -621,7 +621,7 @@
     /** This is for post-export reconstruction for serialization. */
     private SkylarkRuleFunction(
         RuleClass ruleClass, RuleClassType type, Location definitionLocation, Label skylarkLabel) {
-      super("rule", FunctionSignature.KWARGS);
+      super(FunctionSignature.KWARGS);
       Preconditions.checkNotNull(
           ruleClass,
           "RuleClass must be non-null as this SkylarkRuleFunction should have been exported.");
@@ -635,6 +635,11 @@
     }
 
     @Override
+    public String getName() {
+      return "rule";
+    }
+
+    @Override
     public Object call(Object[] args, FuncallExpression astForLocation, StarlarkThread thread)
         throws EvalException, InterruptedException, ConversionException {
       Location loc = astForLocation.getLocation();
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkRepositoryModule.java b/src/main/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkRepositoryModule.java
index 2b337e6..bf42816 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkRepositoryModule.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkRepositoryModule.java
@@ -105,12 +105,17 @@
     private final Location ruleClassDefinitionLocation;
 
     public RepositoryRuleFunction(RuleClass.Builder builder, Location ruleClassDefinitionLocation) {
-      super("repository_rule", FunctionSignature.KWARGS);
+      super(FunctionSignature.KWARGS);
       this.builder = builder;
       this.ruleClassDefinitionLocation = ruleClassDefinitionLocation;
     }
 
     @Override
+    public String getName() {
+      return "repository_rule";
+    }
+
+    @Override
     public void export(Label extensionLabel, String exportedName) {
       this.extensionLabel = extensionLabel;
       this.exportedName = exportedName;
diff --git a/src/main/java/com/google/devtools/build/lib/packages/NativeProvider.java b/src/main/java/com/google/devtools/build/lib/packages/NativeProvider.java
index bbf9711..877e5a5 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/NativeProvider.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/NativeProvider.java
@@ -17,7 +17,9 @@
 import com.google.devtools.build.lib.events.Location;
 import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
 import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec.VisibleForSerialization;
+import com.google.devtools.build.lib.syntax.BaseFunction;
 import com.google.devtools.build.lib.syntax.EvalException;
+import com.google.devtools.build.lib.syntax.FuncallExpression;
 import com.google.devtools.build.lib.syntax.FunctionSignature;
 import com.google.devtools.build.lib.syntax.StarlarkThread;
 import com.google.devtools.build.lib.util.Pair;
@@ -36,14 +38,16 @@
  *       new NativeProvider("link_params") { };
  * </pre>
  *
- * To allow construction from Skylark and custom construction logic, override {@link
- * ProviderFromFunction#createInstanceFromSkylark(Object[], StarlarkThread, Location)}.
+ * To allow construction from Skylark and custom construction logic, override the {@link #call}
+ * method.
  *
  * @deprecated use {@link BuiltinProvider} instead.
  */
 @Immutable
 @Deprecated
-public abstract class NativeProvider<V extends InfoInterface> extends ProviderFromFunction {
+public abstract class NativeProvider<V extends InfoInterface> extends BaseFunction
+    implements Provider {
+  private final String name;
   private final NativeKey key;
   private final String errorMessageFormatForUnknownField;
 
@@ -66,13 +70,18 @@
   }
 
   protected NativeProvider(Class<V> valueClass, String name) {
-    super(name, FunctionSignature.KWARGS);
+    super(FunctionSignature.KWARGS, /*defaultValues=*/ null);
+    this.name = name;
     this.key = new NativeKey(name, getClass());
     this.valueClass = valueClass;
     this.errorMessageFormatForUnknownField =
         String.format("'%s' object has no attribute '%%s'", name);
   }
 
+  public final SkylarkProviderIdentifier id() {
+    return SkylarkProviderIdentifier.forKey(getKey());
+  }
+
   /**
    * equals() implements singleton class semantics.
    *
@@ -97,7 +106,12 @@
 
   @Override
   public String getPrintableName() {
-    return getName();
+    return name; // for provider-related errors
+  }
+
+  @Override
+  public String getName() {
+    return name; // for stack traces
   }
 
   @Override
@@ -120,9 +134,19 @@
     return key;
   }
 
+  /**
+   * Override this method to provide logic that is used to instantiate a declared provider from
+   * Skylark.
+   *
+   * <p>This is a method that is called when a constructor {@code c} is invoked as<br>
+   * {@code c(arg1 = val1, arg2 = val2, ...)}.
+   *
+   * @param args an array of argument values sorted as per the signature ({@see BaseFunction#call})
+   */
   @Override
-  protected InfoInterface createInstanceFromSkylark(
-      Object[] args, StarlarkThread thread, Location loc) throws EvalException {
+  protected Object call(Object[] args, @Nullable FuncallExpression ast, StarlarkThread thread)
+      throws EvalException, InterruptedException {
+    Location loc = ast != null ? ast.getLocation() : Location.BUILTIN;
     throw new EvalException(
         loc, String.format("'%s' cannot be constructed from Starlark", getPrintableName()));
   }
diff --git a/src/main/java/com/google/devtools/build/lib/packages/PackageFactory.java b/src/main/java/com/google/devtools/build/lib/packages/PackageFactory.java
index 4b8a349..bf622a0 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/PackageFactory.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/PackageFactory.java
@@ -509,7 +509,12 @@
       argumentSpecifiers[i++] = entry.getValue();
     }
 
-    return new BaseFunction("package", FunctionSignature.namedOnly(0, argumentNames)) {
+    return new BaseFunction(FunctionSignature.namedOnly(0, argumentNames)) {
+      @Override
+      public String getName() {
+        return "package";
+      }
+
       @Override
       public Object call(Object[] arguments, FuncallExpression ast, StarlarkThread thread)
           throws EvalException {
@@ -566,7 +571,7 @@
       RuleClass cl = ruleFactory.getRuleClass(ruleClassName);
       if (cl.getRuleClassType() == RuleClassType.NORMAL
           || cl.getRuleClassType() == RuleClassType.TEST) {
-        result.put(ruleClassName, new BuiltinRuleFunction(ruleClassName, ruleFactory));
+        result.put(ruleClassName, new BuiltinRuleFunction(cl));
       }
     }
     return result.build();
@@ -577,23 +582,17 @@
    * com.google.devtools.build.lib.packages.RuleClass}es.
    */
   private static class BuiltinRuleFunction extends BuiltinFunction implements RuleFunction {
-    private final String ruleClassName;
     private final RuleClass ruleClass;
 
-    BuiltinRuleFunction(String ruleClassName, RuleFactory ruleFactory) {
-      super(ruleClassName, FunctionSignature.KWARGS);
-      this.ruleClassName = ruleClassName;
-      Preconditions.checkNotNull(ruleFactory, "ruleFactory was null");
-      this.ruleClass = Preconditions.checkNotNull(
-          ruleFactory.getRuleClass(ruleClassName),
-          "No such rule class: %s",
-          ruleClassName);
+    BuiltinRuleFunction(RuleClass ruleClass) {
+      super(FunctionSignature.KWARGS);
+      this.ruleClass = Preconditions.checkNotNull(ruleClass);
     }
 
     @SuppressWarnings("unused")
     public NoneType invoke(Map<String, Object> kwargs, Location loc, StarlarkThread thread)
         throws EvalException, InterruptedException {
-      SkylarkUtils.checkLoadingOrWorkspacePhase(thread, ruleClassName, loc);
+      SkylarkUtils.checkLoadingOrWorkspacePhase(thread, ruleClass.getName(), loc);
       try {
         addRule(getContext(thread, loc), kwargs, loc, thread);
       } catch (RuleFactory.InvalidRuleException | Package.NameConflictException e) {
@@ -618,6 +617,11 @@
     }
 
     @Override
+    public String getName() {
+      return ruleClass.getName();
+    }
+
+    @Override
     public void repr(SkylarkPrinter printer) {
       printer.append("<built-in rule " + getName() + ">");
     }
diff --git a/src/main/java/com/google/devtools/build/lib/packages/ProviderFromFunction.java b/src/main/java/com/google/devtools/build/lib/packages/ProviderFromFunction.java
deleted file mode 100644
index d279aa9..0000000
--- a/src/main/java/com/google/devtools/build/lib/packages/ProviderFromFunction.java
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright 2018 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.packages;
-
-import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
-import com.google.devtools.build.lib.events.Location;
-import com.google.devtools.build.lib.syntax.BaseFunction;
-import com.google.devtools.build.lib.syntax.EvalException;
-import com.google.devtools.build.lib.syntax.FuncallExpression;
-import com.google.devtools.build.lib.syntax.FunctionSignature;
-import com.google.devtools.build.lib.syntax.StarlarkThread;
-import javax.annotation.Nullable;
-
-/**
- * Implementation of {@link Provider} that is represented by a {@link BaseFunction}, and thus
- * callable from Skylark.
- */
-// TODO(adonovan): eliminate by inlining into its two subclasses.
-@Immutable
-abstract class ProviderFromFunction extends BaseFunction implements Provider {
-
-  /**
-   * Constructs a provider.
-   *
-   * @param name provider name; should be null iff the subclass overrides {@link #getName}
-   * @param signature the signature for calling this provider as a Skylark function (to construct an
-   *     instance of the provider)
-   * @param location the location of this provider's Skylark definition. Use {@link
-   *     Location#BUILTIN} if it is a native provider.
-   */
-  protected ProviderFromFunction(@Nullable String name, FunctionSignature signature) {
-    super(name, signature, /*defaultValues=*/ null);
-  }
-
-  public final SkylarkProviderIdentifier id() {
-    return SkylarkProviderIdentifier.forKey(getKey());
-  }
-
-  @Override
-  protected final Object call(Object[] args, @Nullable FuncallExpression ast, StarlarkThread thread)
-      throws EvalException, InterruptedException {
-    Location loc = ast != null ? ast.getLocation() : Location.BUILTIN;
-    return createInstanceFromSkylark(args, thread, loc);
-  }
-
-  /**
-   * Override this method to provide logic that is used to instantiate a declared provider from
-   * Skylark.
-   *
-   * <p>This is a method that is called when a constructor {@code c} is invoked as<br>
-   * {@code c(arg1 = val1, arg2 = val2, ...)}.
-   *
-   * @param args an array of argument values sorted as per the signature ({@see BaseFunction#call})
-   */
-  protected abstract InfoInterface createInstanceFromSkylark(
-      Object[] args, StarlarkThread thread, Location loc) throws EvalException;
-}
diff --git a/src/main/java/com/google/devtools/build/lib/packages/SkylarkProvider.java b/src/main/java/com/google/devtools/build/lib/packages/SkylarkProvider.java
index 9fbbe23..a0f1d56 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/SkylarkProvider.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/SkylarkProvider.java
@@ -22,6 +22,9 @@
 import com.google.devtools.build.lib.packages.SkylarkInfo.Layout;
 import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
 import com.google.devtools.build.lib.skylarkinterface.SkylarkPrinter;
+import com.google.devtools.build.lib.syntax.BaseFunction;
+import com.google.devtools.build.lib.syntax.EvalException;
+import com.google.devtools.build.lib.syntax.FuncallExpression;
 import com.google.devtools.build.lib.syntax.FunctionSignature;
 import com.google.devtools.build.lib.syntax.StarlarkThread;
 import java.util.Map;
@@ -44,7 +47,7 @@
  * pre-exported provider directly. Exported providers use only their key for {@link #equals} and
  * {@link #hashCode}.
  */
-public class SkylarkProvider extends ProviderFromFunction implements SkylarkExportable {
+public final class SkylarkProvider extends BaseFunction implements SkylarkExportable, Provider {
 
   /** Default value for {@link #errorMessageFormatForUnknownField}. */
   private static final String DEFAULT_ERROR_MESSAGE_FORMAT = "Object has no '%s' attribute.";
@@ -126,9 +129,7 @@
    */
   private SkylarkProvider(
       @Nullable SkylarkKey key, @Nullable ImmutableList<String> fields, Location location) {
-    // We override getName() in order to use the name that is assigned when export() is called.
-    // Hence BaseFunction's constructor gets a null name.
-    super(/*name=*/ null, buildSignature(fields));
+    super(buildSignature(fields), /*defaultValues=*/ null);
     this.location = location;
     this.layout = fields == null ? null : new Layout(fields);
     this.key = key;  // possibly null
@@ -144,8 +145,9 @@
   }
 
   @Override
-  protected SkylarkInfo createInstanceFromSkylark(
-      Object[] args, StarlarkThread thread, Location loc) {
+  protected Object call(Object[] args, @Nullable FuncallExpression ast, StarlarkThread thread)
+      throws EvalException, InterruptedException {
+    Location loc = ast != null ? ast.getLocation() : Location.BUILTIN;
     if (layout == null) {
       @SuppressWarnings("unchecked")
       Map<String, Object> kwargs = (Map<String, Object>) args[0];
diff --git a/src/main/java/com/google/devtools/build/lib/packages/WorkspaceFactory.java b/src/main/java/com/google/devtools/build/lib/packages/WorkspaceFactory.java
index 03dcfc3..5506192 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/WorkspaceFactory.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/WorkspaceFactory.java
@@ -261,7 +261,12 @@
    */
   private static BuiltinFunction newRuleFunction(
       final RuleFactory ruleFactory, final String ruleClassName, final boolean allowOverride) {
-    return new BuiltinFunction(ruleClassName, FunctionSignature.KWARGS) {
+    return new BuiltinFunction(FunctionSignature.KWARGS) {
+      @Override
+      public String getName() {
+        return ruleClassName;
+      }
+
       public Object invoke(Map<String, Object> kwargs, Location loc, StarlarkThread thread)
           throws EvalException, InterruptedException {
         try {
diff --git a/src/main/java/com/google/devtools/build/lib/rules/config/ConfigFeatureFlagProvider.java b/src/main/java/com/google/devtools/build/lib/rules/config/ConfigFeatureFlagProvider.java
index 566d1ca..cc2d260 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/config/ConfigFeatureFlagProvider.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/config/ConfigFeatureFlagProvider.java
@@ -26,8 +26,10 @@
 import com.google.devtools.build.lib.packages.SkylarkProviderIdentifier;
 import com.google.devtools.build.lib.skylarkbuildapi.config.ConfigFeatureFlagProviderApi;
 import com.google.devtools.build.lib.syntax.EvalException;
+import com.google.devtools.build.lib.syntax.FuncallExpression;
 import com.google.devtools.build.lib.syntax.StarlarkThread;
 import java.util.Map;
+import javax.annotation.Nullable;
 
 /** Provider for exporting value and valid value predicate of feature flags to consuming targets. */
 @Immutable
@@ -65,8 +67,10 @@
     }
 
     @Override
-    protected ConfigFeatureFlagProvider createInstanceFromSkylark(
-        Object[] args, StarlarkThread thread, Location loc) throws EvalException {
+    protected ConfigFeatureFlagProvider call(
+        Object[] args, @Nullable FuncallExpression ast, StarlarkThread thread)
+        throws EvalException {
+      Location loc = ast != null ? ast.getLocation() : Location.BUILTIN;
 
       @SuppressWarnings("unchecked")
       Map<String, Object> kwargs = (Map<String, Object>) args[0];
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/BaseFunction.java b/src/main/java/com/google/devtools/build/lib/syntax/BaseFunction.java
index 485d3ff..3c8141f 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/BaseFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/BaseFunction.java
@@ -53,14 +53,6 @@
   // TODO(adonovan): Turn fields into abstract methods. Make processArguments a static function
   // with multiple parameters, instead of a "mix-in" that accesses instance fields.
 
-  /**
-   * The name of the function.
-   *
-   * <p>For safe extensibility, this class only retrieves name via the accessor {@link #getName}.
-   * This field must be null iff {@link #getName} is overridden.
-   */
-  @Nullable private final String name;
-
   private final FunctionSignature signature;
 
   /**
@@ -71,17 +63,6 @@
   // element per optional parameter, without exception.
   @Nullable private final List<Object> defaultValues;
 
-  /**
-   * Returns the name of this function.
-   *
-   * <p>A subclass must override this function if a null name is given to this class's constructor.
-   */
-  @Override
-  public String getName() {
-    Preconditions.checkNotNull(name);
-    return name;
-  }
-
   /** Returns the signature of this function. */
   public FunctionSignature getSignature() {
     return signature;
@@ -96,14 +77,8 @@
     return defaultValues;
   }
 
-  /**
-   * Constructs a BaseFunction with a given name and signature.
-   *
-   * @param signature the signature with default values and types
-   */
-  protected BaseFunction(
-      @Nullable String name, FunctionSignature signature, @Nullable List<Object> defaultValues) {
-    this.name = name;
+  /** Constructs a BaseFunction with a given signature and default values. */
+  protected BaseFunction(FunctionSignature signature, @Nullable List<Object> defaultValues) {
     this.signature = Preconditions.checkNotNull(signature);
     this.defaultValues = defaultValues;
     if (defaultValues != null) {
@@ -111,14 +86,9 @@
     }
   }
 
-  /**
-   * Constructs a BaseFunction with a given name and signature without default values or types.
-   *
-   * @param name the function name; null iff this is a subclass overriding {@link #getName}
-   * @param signature the function signature
-   */
-  protected BaseFunction(@Nullable String name, FunctionSignature signature) {
-    this(name, signature, /*defaultValues=*/ null);
+  /** Constructs a BaseFunction with a given signature without default values. */
+  protected BaseFunction(FunctionSignature signature) {
+    this(signature, /*defaultValues=*/ null);
   }
 
   /**
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/BuiltinFunction.java b/src/main/java/com/google/devtools/build/lib/syntax/BuiltinFunction.java
index 4724086..537f8ae 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/BuiltinFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/BuiltinFunction.java
@@ -34,7 +34,7 @@
  * this class do not need to be serializable because they should effectively be treated as
  * constants.
  */
-public class BuiltinFunction extends BaseFunction {
+public abstract class BuiltinFunction extends BaseFunction {
 
   // Builtins cannot create or modify variable bindings. So it's sufficient to use a shared
   // instance.
@@ -52,9 +52,9 @@
   // The returnType of the method.
   private Class<?> returnType;
 
-  /** Creates a BuiltinFunction with the given name and signature. */
-  protected BuiltinFunction(String name, FunctionSignature signature) {
-    super(name, signature);
+  /** Creates a BuiltinFunction with the given signature. */
+  protected BuiltinFunction(FunctionSignature signature) {
+    super(signature);
     initialize();
   }
 
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/StarlarkFunction.java b/src/main/java/com/google/devtools/build/lib/syntax/StarlarkFunction.java
index e2d2f62..93f43a7 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/StarlarkFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/StarlarkFunction.java
@@ -24,6 +24,7 @@
 /** A StarlarkFunction is the function value created by a Starlark {@code def} statement. */
 public final class StarlarkFunction extends BaseFunction {
 
+  private final String name;
   private final Location location;
   private final ImmutableList<Statement> statements;
 
@@ -39,7 +40,8 @@
       ImmutableList<Object> defaultValues,
       ImmutableList<Statement> statements,
       Module definitionGlobals) {
-    super(name, signature, defaultValues);
+    super(signature, defaultValues);
+    this.name = name;
     this.location = location;
     this.statements = statements;
     this.definitionGlobals = definitionGlobals;
@@ -50,6 +52,11 @@
     return location;
   }
 
+  @Override
+  public String getName() {
+    return name;
+  }
+
   public ImmutableList<Statement> getStatements() {
     return statements;
   }
diff --git a/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeProviderApi.java b/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeProviderApi.java
index 71042d8..82341be 100644
--- a/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeProviderApi.java
+++ b/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeProviderApi.java
@@ -34,8 +34,10 @@
    */
   private static int idCounter = 0;
 
+  private final String name = "ProviderIdentifier" + idCounter++;
+
   public FakeProviderApi() {
-    super("ProviderIdentifier" + idCounter++, FunctionSignature.KWARGS);
+    super(FunctionSignature.KWARGS);
   }
 
   @Override
@@ -45,5 +47,10 @@
   }
 
   @Override
+  public String getName() {
+    return name;
+  }
+
+  @Override
   public void repr(SkylarkPrinter printer) {}
 }
diff --git a/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeSkylarkAspect.java b/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeSkylarkAspect.java
index b2540ee..d66cc0d 100644
--- a/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeSkylarkAspect.java
+++ b/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeSkylarkAspect.java
@@ -27,8 +27,15 @@
    */
   private static int idCounter = 0;
 
+  private final String name = "AspectIdentifier" + idCounter++;
+
   public FakeSkylarkAspect() {
-    super("AspectIdentifier" + idCounter++, FunctionSignature.KWARGS);
+    super(FunctionSignature.KWARGS);
+  }
+
+  @Override
+  public String getName() {
+    return name;
   }
 
   @Override
diff --git a/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeSkylarkNativeModuleApi.java b/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeSkylarkNativeModuleApi.java
index 32554bf..9159df2 100644
--- a/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeSkylarkNativeModuleApi.java
+++ b/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeSkylarkNativeModuleApi.java
@@ -18,13 +18,19 @@
 import com.google.common.collect.ImmutableList;
 import com.google.devtools.build.lib.events.Location;
 import com.google.devtools.build.lib.skylarkbuildapi.SkylarkNativeModuleApi;
+import com.google.devtools.build.lib.skylarkinterface.SkylarkPrinter;
 import com.google.devtools.build.lib.syntax.ClassObject;
 import com.google.devtools.build.lib.syntax.EvalException;
+import com.google.devtools.build.lib.syntax.FuncallExpression;
 import com.google.devtools.build.lib.syntax.NoneType;
 import com.google.devtools.build.lib.syntax.Sequence;
 import com.google.devtools.build.lib.syntax.SkylarkDict;
+import com.google.devtools.build.lib.syntax.Starlark;
+import com.google.devtools.build.lib.syntax.StarlarkCallable;
 import com.google.devtools.build.lib.syntax.StarlarkList;
 import com.google.devtools.build.lib.syntax.StarlarkThread;
+import java.util.List;
+import java.util.Map;
 import javax.annotation.Nullable;
 
 /** Fake implementation of {@link SkylarkNativeModuleApi}. */
@@ -85,7 +91,31 @@
     // as far as native rules are concerned. Returning None on all unsupported invocations of
     // native.[func_name]() is the safest "best effort" approach to implementing a fake for
     // "native".
-    return new FakeStarlarkCallable(name);
+    return new StarlarkCallable() {
+      @Override
+      public Object call(
+          List<Object> args,
+          @Nullable Map<String, Object> kwargs,
+          @Nullable FuncallExpression call,
+          StarlarkThread thread) {
+        return Starlark.NONE;
+      }
+
+      @Override
+      public String getName() {
+        return name;
+      }
+
+      @Override
+      public Location getLocation() {
+        return Location.BUILTIN;
+      }
+
+      @Override
+      public void repr(SkylarkPrinter printer) {
+        printer.append("<faked no-op function " + name + ">");
+      }
+    };
   }
 
   @Override
diff --git a/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeSkylarkRuleFunctionsApi.java b/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeSkylarkRuleFunctionsApi.java
index 6dc554e..edabfce 100644
--- a/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeSkylarkRuleFunctionsApi.java
+++ b/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeSkylarkRuleFunctionsApi.java
@@ -248,9 +248,15 @@
   private static class RuleDefinitionIdentifier extends BaseFunction {
 
     private static int idCounter = 0;
+    private final String name = "RuleDefinitionIdentifier" + idCounter++;
 
     public RuleDefinitionIdentifier() {
-      super("RuleDefinitionIdentifier" + idCounter++, FunctionSignature.KWARGS);
+      super(FunctionSignature.KWARGS);
+    }
+
+    @Override
+    public String getName() {
+      return name;
     }
   }
 
diff --git a/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeStarlarkCallable.java b/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeStarlarkCallable.java
deleted file mode 100644
index d42da43..0000000
--- a/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeStarlarkCallable.java
+++ /dev/null
@@ -1,62 +0,0 @@
-// 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.skydoc.fakebuildapi;
-
-import com.google.devtools.build.lib.events.Location;
-import com.google.devtools.build.lib.skylarkinterface.SkylarkPrinter;
-import com.google.devtools.build.lib.syntax.FuncallExpression;
-import com.google.devtools.build.lib.syntax.Starlark;
-import com.google.devtools.build.lib.syntax.StarlarkCallable;
-import com.google.devtools.build.lib.syntax.StarlarkThread;
-import java.util.List;
-import java.util.Map;
-import javax.annotation.Nullable;
-
-/**
- * "Fake" implementation of {@link StarlarkCallable} which accepts any parameters and always returns
- * None.
- */
-public final class FakeStarlarkCallable implements StarlarkCallable {
-
-  private final String functionName;
-
-  public FakeStarlarkCallable(String functionName) {
-    this.functionName = functionName;
-  }
-
-  @Override
-  public Object call(
-      List<Object> args,
-      @Nullable Map<String, Object> kwargs,
-      @Nullable FuncallExpression call,
-      StarlarkThread thread) {
-    return Starlark.NONE;
-  }
-
-  @Override
-  public String getName() {
-    return functionName;
-  }
-
-  @Override
-  public Location getLocation() {
-    return Location.BUILTIN;
-  }
-
-  @Override
-  public void repr(SkylarkPrinter printer) {
-    printer.append("<faked no-op function " + functionName + ">");
-  }
-}
diff --git a/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/repository/FakeRepositoryModule.java b/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/repository/FakeRepositoryModule.java
index 4c28900..db0a107 100644
--- a/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/repository/FakeRepositoryModule.java
+++ b/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/repository/FakeRepositoryModule.java
@@ -95,9 +95,15 @@
   private static class RepositoryRuleDefinitionIdentifier extends BaseFunction {
 
     private static int idCounter = 0;
+    private final String name = "RepositoryRuleDefinitionIdentifier" + idCounter++;
 
     public RepositoryRuleDefinitionIdentifier() {
-      super("RepositoryRuleDefinitionIdentifier" + idCounter++, FunctionSignature.KWARGS);
+      super(FunctionSignature.KWARGS);
+    }
+
+    @Override
+    public String getName() {
+      return name;
     }
   }
 
diff --git a/src/test/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkRepositoryContextTest.java b/src/test/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkRepositoryContextTest.java
index eb6e51f..b49b68c 100644
--- a/src/test/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkRepositoryContextTest.java
+++ b/src/test/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkRepositoryContextTest.java
@@ -89,7 +89,12 @@
     }
     ruleClassBuilder.setWorkspaceOnly();
     ruleClassBuilder.setConfiguredTargetFunction(
-        new BuiltinFunction("test", FunctionSignature.ANY) {
+        new BuiltinFunction(FunctionSignature.ANY) {
+          @Override
+          public String getName() {
+            return "test";
+          }
+
           public void invoke(
               List<Object> args, Map<String, Object> kwargs, StarlarkThread thread) {}
         });
diff --git a/src/test/java/com/google/devtools/build/lib/profiler/memory/AllocationTrackerTest.java b/src/test/java/com/google/devtools/build/lib/profiler/memory/AllocationTrackerTest.java
index c9904ca..c03a3a4 100644
--- a/src/test/java/com/google/devtools/build/lib/profiler/memory/AllocationTrackerTest.java
+++ b/src/test/java/com/google/devtools/build/lib/profiler/memory/AllocationTrackerTest.java
@@ -58,14 +58,21 @@
   }
 
   private static class TestFunction extends BaseFunction {
+    private final String name;
     private final Location location;
 
     TestFunction(String file, String name, int line) {
-      super(name, FunctionSignature.ANY, /*defaultValues=*/ null);
+      super(FunctionSignature.ANY, /*defaultValues=*/ null);
+      this.name = name;
       this.location = location(file, line);
     }
 
     @Override
+    public String getName() {
+      return name;
+    }
+
+    @Override
     public Location getLocation() {
       return location;
     }
diff --git a/src/test/java/com/google/devtools/build/lib/syntax/BaseFunctionTest.java b/src/test/java/com/google/devtools/build/lib/syntax/BaseFunctionTest.java
index 4b5edb5..c0b00d1 100644
--- a/src/test/java/com/google/devtools/build/lib/syntax/BaseFunctionTest.java
+++ b/src/test/java/com/google/devtools/build/lib/syntax/BaseFunctionTest.java
@@ -34,11 +34,16 @@
 
   /**
    * Handy implementation of {@link BaseFunction} that returns all its args as a list. (We'd use
-   * Sequence.tuple, but it can't handle null.)
+   * Tuple, but it can't handle null.)
    */
   private static class TestingBaseFunction extends BaseFunction {
     TestingBaseFunction(FunctionSignature signature) {
-      super("mixed", signature);
+      super(signature);
+    }
+
+    @Override
+    public String getName() {
+      return "mixed";
     }
 
     @Override
diff --git a/src/test/java/com/google/devtools/build/lib/syntax/EvaluationTest.java b/src/test/java/com/google/devtools/build/lib/syntax/EvaluationTest.java
index 910ed32..5dea7d8 100644
--- a/src/test/java/com/google/devtools/build/lib/syntax/EvaluationTest.java
+++ b/src/test/java/com/google/devtools/build/lib/syntax/EvaluationTest.java
@@ -136,7 +136,12 @@
   @Test
   public void testSumFunction() throws Exception {
     BaseFunction sum =
-        new BaseFunction("sum", FunctionSignature.ANY) {
+        new BaseFunction(FunctionSignature.ANY) {
+          @Override
+          public String getName() {
+            return "sum";
+          }
+
           @Override
           public Object call(
               List<Object> args,
@@ -178,7 +183,12 @@
 
     // This function returns the map of keyword arguments passed to it.
     BaseFunction kwargs =
-        new BaseFunction("kwargs", FunctionSignature.ANY) {
+        new BaseFunction(FunctionSignature.KWARGS) {
+          @Override
+          public String getName() {
+            return "kwargs";
+          }
+
           @Override
           public Object call(
               List<Object> args,
diff --git a/src/test/java/com/google/devtools/build/lib/syntax/FunctionTest.java b/src/test/java/com/google/devtools/build/lib/syntax/FunctionTest.java
index a0559bb..fc4e9a7 100644
--- a/src/test/java/com/google/devtools/build/lib/syntax/FunctionTest.java
+++ b/src/test/java/com/google/devtools/build/lib/syntax/FunctionTest.java
@@ -69,7 +69,12 @@
 
   private void createOuterFunction(final List<Object> params) throws Exception {
     BaseFunction outerFunc =
-        new BaseFunction("outer_func", FunctionSignature.ANY) {
+        new BaseFunction(FunctionSignature.ANY) {
+          @Override
+          public String getName() {
+            return "outer_func";
+          }
+
           @Override
           public Object call(
               List<Object> args,
diff --git a/src/test/java/com/google/devtools/build/lib/syntax/SkylarkEvaluationTest.java b/src/test/java/com/google/devtools/build/lib/syntax/SkylarkEvaluationTest.java
index ff07322..231b373 100644
--- a/src/test/java/com/google/devtools/build/lib/syntax/SkylarkEvaluationTest.java
+++ b/src/test/java/com/google/devtools/build/lib/syntax/SkylarkEvaluationTest.java
@@ -2088,7 +2088,12 @@
               "values_only_field",
               "fromValues",
               "values_only_method",
-              new BuiltinFunction("values_only_method", FunctionSignature.of()) {
+              new BuiltinFunction(FunctionSignature.of()) {
+                @Override
+                public String getName() {
+                  return "values_only_method";
+                }
+
                 public String invoke() {
                   return "fromValues";
                 }
@@ -2096,7 +2101,12 @@
               "collision_field",
               "fromValues",
               "collision_method",
-              new BuiltinFunction("collision_method", FunctionSignature.of()) {
+              new BuiltinFunction(FunctionSignature.of()) {
+                @Override
+                public String getName() {
+                  return "collision_method";
+                }
+
                 public String invoke() {
                   return "fromValues";
                 }
diff --git a/src/test/java/com/google/devtools/build/lib/syntax/StarlarkThreadDebuggingTest.java b/src/test/java/com/google/devtools/build/lib/syntax/StarlarkThreadDebuggingTest.java
index 2ec0157..358c897 100644
--- a/src/test/java/com/google/devtools/build/lib/syntax/StarlarkThreadDebuggingTest.java
+++ b/src/test/java/com/google/devtools/build/lib/syntax/StarlarkThreadDebuggingTest.java
@@ -44,7 +44,12 @@
     FuncallExpression ast = new FuncallExpression(Identifier.of("test"), ImmutableList.of());
     ast.setLocation(location);
     thread.enterScope(
-        new BaseFunction(functionName, FunctionSignature.ANY) {},
+        new BaseFunction(FunctionSignature.ANY) {
+          @Override
+          public String getName() {
+            return functionName;
+          }
+        },
         LexicalFrame.create(thread.mutability()),
         ast,
         thread.getGlobals());