Migrate struct() to skylarkbuildapi

RELNOTES: None.
PiperOrigin-RevId: 197915097
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredRuleClassProvider.java b/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredRuleClassProvider.java
index 04c3c1a..2fd2617 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredRuleClassProvider.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredRuleClassProvider.java
@@ -46,7 +46,6 @@
 import com.google.devtools.build.lib.graph.Node;
 import com.google.devtools.build.lib.packages.Attribute;
 import com.google.devtools.build.lib.packages.NativeAspectClass;
-import com.google.devtools.build.lib.packages.NativeProvider;
 import com.google.devtools.build.lib.packages.NonconfigurableAttributeMapper;
 import com.google.devtools.build.lib.packages.OutputFile;
 import com.google.devtools.build.lib.packages.Rule;
@@ -243,7 +242,6 @@
         ImmutableMap.builder();
      private ImmutableList.Builder<Class<?>> skylarkModules =
         ImmutableList.<Class<?>>builder();
-    private ImmutableList.Builder<NativeProvider> nativeProviders = ImmutableList.builder();
     private Set<String> reservedActionMnemonics = new TreeSet<>();
     private BuildConfiguration.ActionEnvironmentProvider actionEnvironmentProvider =
         (BuildOptions options) -> ActionEnvironment.EMPTY;
@@ -371,11 +369,6 @@
       return this;
     }
 
-    public Builder addNativeProvider(NativeProvider provider) {
-      this.nativeProviders.add(provider);
-      return this;
-    }
-
     public Builder addReservedActionMnemonic(String mnemonic) {
       this.reservedActionMnemonics.add(mnemonic);
       return this;
@@ -514,8 +507,7 @@
           skylarkAccessibleTopLevels.build(),
           skylarkModules.build(),
           ImmutableSet.copyOf(reservedActionMnemonics),
-          actionEnvironmentProvider,
-          nativeProviders.build());
+          actionEnvironmentProvider);
     }
 
     @Override
@@ -628,8 +620,6 @@
 
   private final BuildConfiguration.ActionEnvironmentProvider actionEnvironmentProvider;
 
-  private final ImmutableList<NativeProvider> nativeProviders;
-
   private final ImmutableMap<String, Class<?>> configurationFragmentMap;
 
   private ConfiguredRuleClassProvider(
@@ -651,8 +641,7 @@
       ImmutableMap<String, Object> skylarkAccessibleJavaClasses,
       ImmutableList<Class<?>> skylarkModules,
       ImmutableSet<String> reservedActionMnemonics,
-      BuildConfiguration.ActionEnvironmentProvider actionEnvironmentProvider,
-      ImmutableList<NativeProvider> nativeProviders) {
+      BuildConfiguration.ActionEnvironmentProvider actionEnvironmentProvider) {
     this.preludeLabel = preludeLabel;
     this.runfilesPrefix = runfilesPrefix;
     this.toolsRepository = toolsRepository;
@@ -671,7 +660,6 @@
     this.globals = createGlobals(skylarkAccessibleJavaClasses, skylarkModules);
     this.reservedActionMnemonics = reservedActionMnemonics;
     this.actionEnvironmentProvider = actionEnvironmentProvider;
-    this.nativeProviders = nativeProviders;
     this.configurationFragmentMap = createFragmentMap(configurationFragmentFactories);
   }
 
@@ -896,12 +884,4 @@
   public BuildConfiguration.ActionEnvironmentProvider getActionEnvironmentProvider() {
     return actionEnvironmentProvider;
   }
-
-  /**
-   * Returns all registered {@link NativeProvider} instances, i.e. all built-in provider types that
-   * are based on {@link Provider} rather than {@link TransitiveInfoProvider}.
-   */
-  public ImmutableList<NativeProvider> getNativeProviders() {
-    return nativeProviders;
-  }
 }
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkAttributesCollection.java b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkAttributesCollection.java
index ae13ebf..6ee03b7 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkAttributesCollection.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkAttributesCollection.java
@@ -23,7 +23,7 @@
 import com.google.devtools.build.lib.packages.Attribute;
 import com.google.devtools.build.lib.packages.BuildType;
 import com.google.devtools.build.lib.packages.Info;
-import com.google.devtools.build.lib.packages.NativeProvider;
+import com.google.devtools.build.lib.packages.StructProvider;
 import com.google.devtools.build.lib.skylarkbuildapi.SkylarkAttributesCollectionApi;
 import com.google.devtools.build.lib.skylarkinterface.SkylarkPrinter;
 import com.google.devtools.build.lib.syntax.Environment;
@@ -59,21 +59,21 @@
     this.skylarkRuleContext = skylarkRuleContext;
     this.ruleClassName = ruleClassName;
     attrObject =
-        NativeProvider.STRUCT.create(
+        StructProvider.STRUCT.create(
             attrs,
             "No attribute '%s' in attr. Make sure you declared a rule attribute with this name.");
     executableObject =
-        NativeProvider.STRUCT.create(
+        StructProvider.STRUCT.create(
             executables,
             "No attribute '%s' in executable. Make sure there is a label type attribute marked "
                 + "as 'executable' with this name");
     fileObject =
-        NativeProvider.STRUCT.create(
+        StructProvider.STRUCT.create(
             singleFiles,
             "No attribute '%s' in file. Make sure there is a label type attribute marked "
                 + "as 'single_file' with this name");
     filesObject =
-        NativeProvider.STRUCT.create(
+        StructProvider.STRUCT.create(
             files,
             "No attribute '%s' in files. Make sure there is a label or label_list type attribute "
                 + "with this name");
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkModules.java b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkModules.java
index 9271102..3450283 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkModules.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkModules.java
@@ -17,6 +17,7 @@
 import com.google.common.collect.ImmutableMap;
 import com.google.devtools.build.lib.packages.BazelLibrary;
 import com.google.devtools.build.lib.packages.SkylarkNativeModule;
+import com.google.devtools.build.lib.packages.StructProvider;
 import com.google.devtools.build.lib.skylarkbuildapi.TopLevelBootstrap;
 
 /**
@@ -26,15 +27,15 @@
 
   private SkylarkModules() { }
 
-  /**
-   * A bootstrap for non-rules-specific globals of the build API.
-   */
-  private static TopLevelBootstrap topLevelBootstrap = new TopLevelBootstrap(
-      BazelBuildApiGlobals.class,
-      SkylarkAttr.class,
-      SkylarkCommandLine.class,
-      SkylarkNativeModule.class,
-      SkylarkRuleClassFunctions.class);
+  /** A bootstrap for non-rules-specific globals of the build API. */
+  private static TopLevelBootstrap topLevelBootstrap =
+      new TopLevelBootstrap(
+          BazelBuildApiGlobals.class,
+          SkylarkAttr.class,
+          SkylarkCommandLine.class,
+          SkylarkNativeModule.class,
+          SkylarkRuleClassFunctions.class,
+          StructProvider.STRUCT);
 
   /**
    * Adds bindings for skylark built-ins and non-rules-specific globals of the build API to
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 561055f..b995abf 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
@@ -51,7 +51,6 @@
 import com.google.devtools.build.lib.packages.AttributeValueSource;
 import com.google.devtools.build.lib.packages.ImplicitOutputsFunction.SkylarkImplicitOutputsFunctionWithCallback;
 import com.google.devtools.build.lib.packages.ImplicitOutputsFunction.SkylarkImplicitOutputsFunctionWithMap;
-import com.google.devtools.build.lib.packages.Info;
 import com.google.devtools.build.lib.packages.NativeProvider;
 import com.google.devtools.build.lib.packages.Package.NameConflictException;
 import com.google.devtools.build.lib.packages.PackageFactory;
@@ -73,7 +72,6 @@
 import com.google.devtools.build.lib.packages.TestSize;
 import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
 import com.google.devtools.build.lib.skylarkbuildapi.SkylarkRuleFunctionsApi;
-import com.google.devtools.build.lib.skylarkinterface.Param;
 import com.google.devtools.build.lib.skylarkinterface.SkylarkPrinter;
 import com.google.devtools.build.lib.skylarkinterface.SkylarkSignature;
 import com.google.devtools.build.lib.syntax.BaseFunction;
@@ -209,19 +207,6 @@
       };
 
   @SkylarkSignature(
-    name = "struct",
-    returnType = Info.class,
-    doc =
-        "Creates an immutable struct using the keyword arguments as attributes. It is used to "
-            + "group multiple values together. Example:<br>"
-            + "<pre class=\"language-python\">s = struct(x = 2, y = 3)\n"
-            + "return s.x + getattr(s, \"y\")  # returns 5</pre>",
-    extraKeywords = @Param(name = "kwargs", doc = "the struct attributes."),
-    useLocation = true
-  )
-  private static final NativeProvider<?> struct = NativeProvider.STRUCT;
-
-  @SkylarkSignature(
     name = "DefaultInfo",
     returnType = Provider.class,
     doc =
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleConfiguredTargetUtil.java b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleConfiguredTargetUtil.java
index 5dd1479..2c9b62f 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleConfiguredTargetUtil.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleConfiguredTargetUtil.java
@@ -39,6 +39,7 @@
 import com.google.devtools.build.lib.packages.Rule;
 import com.google.devtools.build.lib.packages.RuleClass.ConfiguredTargetFactory.RuleErrorException;
 import com.google.devtools.build.lib.packages.SkylarkProviderIdentifier;
+import com.google.devtools.build.lib.packages.StructProvider;
 import com.google.devtools.build.lib.packages.TargetUtils;
 import com.google.devtools.build.lib.skylarkinterface.SkylarkValue;
 import com.google.devtools.build.lib.syntax.BaseFunction;
@@ -295,7 +296,7 @@
       SkylarkRuleContext context, RuleConfiguredTargetBuilder builder, Object target, Location loc)
       throws EvalException {
 
-    Info oldStyleProviders = NativeProvider.STRUCT.createEmpty(loc);
+    Info oldStyleProviders = StructProvider.STRUCT.createEmpty(loc);
     ArrayList<Info> declaredProviders = new ArrayList<>();
 
     if (target instanceof Info) {
@@ -303,7 +304,7 @@
       Info struct = (Info) target;
       // Use the creation location of this struct as a better reference in error messages
       loc = struct.getCreationLoc();
-      if (struct.getProvider().getKey().equals(NativeProvider.STRUCT.getKey())) {
+      if (struct.getProvider().getKey().equals(StructProvider.STRUCT.getKey())) {
         // Old-style struct, but it may contain declared providers
         oldStyleProviders = struct;
 
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleContext.java b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleContext.java
index 75e4f63..df2b386 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleContext.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleContext.java
@@ -56,11 +56,11 @@
 import com.google.devtools.build.lib.packages.ImplicitOutputsFunction;
 import com.google.devtools.build.lib.packages.ImplicitOutputsFunction.SkylarkImplicitOutputsFunction;
 import com.google.devtools.build.lib.packages.Info;
-import com.google.devtools.build.lib.packages.NativeProvider;
 import com.google.devtools.build.lib.packages.OutputFile;
 import com.google.devtools.build.lib.packages.Package;
 import com.google.devtools.build.lib.packages.Provider;
 import com.google.devtools.build.lib.packages.RawAttributeMapper;
+import com.google.devtools.build.lib.packages.StructProvider;
 import com.google.devtools.build.lib.shell.ShellUtils;
 import com.google.devtools.build.lib.shell.ShellUtils.TokenizationException;
 import com.google.devtools.build.lib.skylarkbuildapi.FileApi;
@@ -452,7 +452,7 @@
       }
     }
 
-    return NativeProvider.STRUCT.create(
+    return StructProvider.STRUCT.create(
         splitAttrInfos.build(),
         "No attribute '%s' in split_attr. Make sure that this attribute is defined with a "
             + "split configuration.");
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkRepositoryContext.java b/src/main/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkRepositoryContext.java
index a3f70b3..b796384 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkRepositoryContext.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkRepositoryContext.java
@@ -27,8 +27,8 @@
 import com.google.devtools.build.lib.events.Location;
 import com.google.devtools.build.lib.packages.Attribute;
 import com.google.devtools.build.lib.packages.Info;
-import com.google.devtools.build.lib.packages.NativeProvider;
 import com.google.devtools.build.lib.packages.Rule;
+import com.google.devtools.build.lib.packages.StructProvider;
 import com.google.devtools.build.lib.rules.repository.RepositoryFunction;
 import com.google.devtools.build.lib.rules.repository.RepositoryFunction.RepositoryFunctionException;
 import com.google.devtools.build.lib.rules.repository.WorkspaceAttributeMapper;
@@ -111,7 +111,7 @@
                     (com.google.devtools.build.lib.syntax.Environment) null));
       }
     }
-    attrObject = NativeProvider.STRUCT.create(attrBuilder.build(), "No such attribute '%s'");
+    attrObject = StructProvider.STRUCT.create(attrBuilder.build(), "No such attribute '%s'");
   }
 
   @SkylarkCallable(
diff --git a/src/main/java/com/google/devtools/build/lib/packages/Attribute.java b/src/main/java/com/google/devtools/build/lib/packages/Attribute.java
index 933790f..0bc32e42 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/Attribute.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/Attribute.java
@@ -1513,7 +1513,7 @@
     private Object invokeCallback(EventHandler eventHandler, Map<String, Object> attrValues)
         throws EvalException, InterruptedException {
       ClassObject attrs =
-          NativeProvider.STRUCT.create(
+          StructProvider.STRUCT.create(
               attrValues, "No such regular (non computed) attribute '%s'.");
       Object result = callback.call(eventHandler, attrs);
       try {
diff --git a/src/main/java/com/google/devtools/build/lib/packages/ImplicitOutputsFunction.java b/src/main/java/com/google/devtools/build/lib/packages/ImplicitOutputsFunction.java
index 33bc2cf..96388f2 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/ImplicitOutputsFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/ImplicitOutputsFunction.java
@@ -105,7 +105,7 @@
         }
       }
       ClassObject attrs =
-          NativeProvider.STRUCT.create(
+          StructProvider.STRUCT.create(
               attrValues,
               "Attribute '%s' either doesn't exist "
                   + "or uses a select() (i.e. could have multiple values)");
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 20e649b..c59d81e 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
@@ -13,7 +13,6 @@
 // limitations under the License.
 package com.google.devtools.build.lib.packages;
 
-import com.google.common.collect.ImmutableMap;
 import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
 import com.google.devtools.build.lib.events.Location;
 import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
@@ -23,7 +22,6 @@
 import com.google.devtools.build.lib.syntax.FunctionSignature;
 import com.google.devtools.build.lib.syntax.SkylarkType;
 import com.google.devtools.build.lib.util.Pair;
-import java.util.Map;
 import javax.annotation.Nullable;
 
 /**
@@ -40,8 +38,7 @@
  * </pre>
  *
  * To allow construction from Skylark and custom construction logic, override {@link
- * Provider#createInstanceFromSkylark(Object[], Environment, Location)} (see {@link #STRUCT} for an
- * example.
+ * ProviderFromFunction#createInstanceFromSkylark(Object[], Environment, Location)}.
  *
  * @deprecated use {@link BuiltinProvider} instead.
  */
@@ -51,9 +48,6 @@
   private final NativeKey key;
   private final String errorMessageFormatForUnknownField;
 
-  /** "struct" function. */
-  public static final StructProvider STRUCT = new StructProvider();
-
   private final Class<V> valueClass;
 
   public Class<V> getValueClass() {
@@ -72,42 +66,6 @@
     String getSkylarkName();
   }
 
-  /**
-   * The provider for the built-in type {@code struct}.
-   *
-   * <p>Its singleton instance is {@link #STRUCT}.
-   */
-  public static final class StructProvider extends NativeProvider<Info> {
-    private StructProvider() {
-      super(Info.class, "struct");
-    }
-
-    @Override
-    protected Info createInstanceFromSkylark(Object[] args, Environment env, Location loc) {
-      @SuppressWarnings("unchecked")
-      Map<String, Object> kwargs = (Map<String, Object>) args[0];
-      return SkylarkInfo.createSchemaless(this, kwargs, loc);
-    }
-
-    /**
-     * Creates a struct with the he given field values and message format for unknown fields.
-     *
-     * <p>The custom message is useful for objects that have fields but aren't exactly used as
-     * providers, such as the {@code native} object, and the struct fields of {@code ctx} like
-     * {@code ctx.attr}.
-     * */
-    public SkylarkInfo create(
-        Map<String, Object> values, String errorMessageFormatForUnknownField) {
-      return SkylarkInfo.createSchemalessWithCustomMessage(
-          this, values, errorMessageFormatForUnknownField);
-    }
-
-    /** Creates an empty struct with the given location. */
-    public SkylarkInfo createEmpty(Location loc) {
-      return SkylarkInfo.createSchemaless(this, ImmutableMap.of(), loc);
-    }
-  }
-
   private static final FunctionSignature.WithValues<Object, SkylarkType> SIGNATURE =
       FunctionSignature.WithValues.create(FunctionSignature.KWARGS);
 
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 ad682b6..71bf904 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
@@ -1514,7 +1514,7 @@
         builder.put(function.getName(), function);
       }
     }
-    return NativeProvider.STRUCT.create(builder.build(), "no native function or rule '%s'");
+    return StructProvider.STRUCT.create(builder.build(), "no native function or rule '%s'");
   }
 
   private void buildPkgEnv(
diff --git a/src/main/java/com/google/devtools/build/lib/packages/StructProvider.java b/src/main/java/com/google/devtools/build/lib/packages/StructProvider.java
new file mode 100644
index 0000000..21f8475
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/packages/StructProvider.java
@@ -0,0 +1,62 @@
+// 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.common.collect.ImmutableMap;
+import com.google.devtools.build.lib.events.Location;
+import com.google.devtools.build.lib.skylarkbuildapi.StructApi;
+import com.google.devtools.build.lib.syntax.EvalException;
+import com.google.devtools.build.lib.syntax.SkylarkDict;
+import java.util.Map;
+
+/**
+ * The provider for the built-in type {@code struct}.
+ *
+ * <p>Its singleton instance is {@link StructProvider#STRUCT}.
+ */
+public final class StructProvider extends BuiltinProvider<Info>
+    implements StructApi.StructProviderApi {
+
+  /** "struct" function. */
+  public static final StructProvider STRUCT = new StructProvider();
+
+  StructProvider() {
+    super("struct", Info.class);
+  }
+
+  @Override
+  public Info createStruct(SkylarkDict<?, ?> kwargs, Location loc) throws EvalException {
+    return SkylarkInfo.createSchemaless(
+        this, kwargs.getContents(String.class, Object.class, "kwargs"), loc);
+  }
+
+  /**
+   * Creates a struct with the he given field values and message format for unknown fields.
+   *
+   * <p>The custom message is useful for objects that have fields but aren't exactly used as
+   * providers, such as the {@code native} object, and the struct fields of {@code ctx} like
+   * {@code ctx.attr}.
+   * */
+  public SkylarkInfo create(
+      Map<String, Object> values, String errorMessageFormatForUnknownField) {
+    return SkylarkInfo.createSchemalessWithCustomMessage(
+        this, values, errorMessageFormatForUnknownField);
+  }
+
+  /** Creates an empty struct with the given location. */
+  public SkylarkInfo createEmpty(Location loc) {
+    return SkylarkInfo.createSchemaless(this, ImmutableMap.of(), loc);
+  }
+}
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 5d55d31..b9d86ad 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
@@ -569,7 +569,7 @@
     }
 
     builder.put("bazel_version", version);
-    return NativeProvider.STRUCT.create(builder.build(), "no native function or rule '%s'");
+    return StructProvider.STRUCT.create(builder.build(), "no native function or rule '%s'");
   }
 
   static ClassObject newNativeModule(RuleClassProvider ruleClassProvider, String version) {
diff --git a/src/main/java/com/google/devtools/build/lib/rules/core/CoreRules.java b/src/main/java/com/google/devtools/build/lib/rules/core/CoreRules.java
index 75fa2d6..90d44a5b 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/core/CoreRules.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/core/CoreRules.java
@@ -18,7 +18,6 @@
 import com.google.devtools.build.lib.analysis.ConfiguredRuleClassProvider;
 import com.google.devtools.build.lib.analysis.ConfiguredRuleClassProvider.RuleSet;
 import com.google.devtools.build.lib.analysis.test.TestConfiguration;
-import com.google.devtools.build.lib.packages.NativeProvider;
 
 /** A set of basic rules - Bazel won't work correctly without these. */
 public final class CoreRules implements RuleSet {
@@ -38,7 +37,6 @@
     builder.addRuleDefinition(new BaseRuleClasses.BinaryBaseRule());
     builder.addRuleDefinition(new BaseRuleClasses.TestBaseRule());
     builder.addRuleDefinition(new BaseRuleClasses.ErrorRule());
-    builder.addNativeProvider(NativeProvider.STRUCT);
   }
 
   @Override
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcProviderSkylarkConverters.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcProviderSkylarkConverters.java
index c2fe4d6..f7dc98a 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcProviderSkylarkConverters.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcProviderSkylarkConverters.java
@@ -25,7 +25,7 @@
 import com.google.devtools.build.lib.collect.nestedset.NestedSet;
 import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
 import com.google.devtools.build.lib.packages.Info;
-import com.google.devtools.build.lib.packages.NativeProvider;
+import com.google.devtools.build.lib.packages.StructProvider;
 import com.google.devtools.build.lib.rules.objc.ObjcProvider.Key;
 import com.google.devtools.build.lib.syntax.EvalException;
 import com.google.devtools.build.lib.syntax.EvalUtils;
@@ -171,7 +171,7 @@
       NestedSetBuilder<Info> result = NestedSetBuilder.stableOrder();
       for (BundleableFile bundleableFile : (Iterable<BundleableFile>) javaValue) {
         result.add(
-            NativeProvider.STRUCT.create(
+            StructProvider.STRUCT.create(
                 ImmutableMap.<String, Object>of(
                     BUNDLED_FIELD, bundleableFile.getBundled(),
                     BUNDLE_PATH_FIELD, bundleableFile.getBundlePath()),
diff --git a/src/main/java/com/google/devtools/build/lib/rules/python/PyCommon.java b/src/main/java/com/google/devtools/build/lib/rules/python/PyCommon.java
index 3a8c068..ede9e0f 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/python/PyCommon.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/python/PyCommon.java
@@ -43,8 +43,8 @@
 import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
 import com.google.devtools.build.lib.packages.BuildType;
 import com.google.devtools.build.lib.packages.Info;
-import com.google.devtools.build.lib.packages.NativeProvider;
 import com.google.devtools.build.lib.packages.Rule;
+import com.google.devtools.build.lib.packages.StructProvider;
 import com.google.devtools.build.lib.rules.cpp.CppFileTypes;
 import com.google.devtools.build.lib.syntax.EvalException;
 import com.google.devtools.build.lib.syntax.EvalUtils;
@@ -180,7 +180,7 @@
    */
   public static Info createSourceProvider(
       NestedSet<Artifact> transitivePythonSources, boolean isUsingSharedLibrary) {
-    return NativeProvider.STRUCT.create(
+    return StructProvider.STRUCT.create(
         ImmutableMap.<String, Object>of(
             TRANSITIVE_PYTHON_SRCS,
             SkylarkNestedSet.of(Artifact.class, transitivePythonSources),
diff --git a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/StructApi.java b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/StructApi.java
index 5e7b682..debb5bd 100644
--- a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/StructApi.java
+++ b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/StructApi.java
@@ -15,11 +15,14 @@
 package com.google.devtools.build.lib.skylarkbuildapi;
 
 import com.google.devtools.build.lib.events.Location;
+import com.google.devtools.build.lib.skylarkinterface.Param;
 import com.google.devtools.build.lib.skylarkinterface.SkylarkCallable;
+import com.google.devtools.build.lib.skylarkinterface.SkylarkConstructor;
 import com.google.devtools.build.lib.skylarkinterface.SkylarkModule;
 import com.google.devtools.build.lib.skylarkinterface.SkylarkModuleCategory;
 import com.google.devtools.build.lib.skylarkinterface.SkylarkValue;
 import com.google.devtools.build.lib.syntax.EvalException;
+import com.google.devtools.build.lib.syntax.SkylarkDict;
 
 /** Interface for the "struct" object in the build API. */
 @SkylarkModule(
@@ -72,4 +75,29 @@
               + "# {\"key\":{\"inner_key\":{\"inner_inner_key\":\"text\"}}}\n</pre>",
       useLocation = true)
   public String toJson(Location loc) throws EvalException;
+
+  /**
+   * Callable Provider for new struct objects.
+   */
+  @SkylarkModule(name = "Provider", documented = false, doc = "")
+  public interface StructProviderApi {
+
+    @SkylarkCallable(
+        name = "struct",
+        doc =
+            "Creates an immutable struct using the keyword arguments as attributes. It is used to "
+                + "group multiple values together. Example:<br>"
+                + "<pre class=\"language-python\">s = struct(x = 2, y = 3)\n"
+                + "return s.x + getattr(s, \"y\")  # returns 5</pre>",
+        extraKeywords =
+            @Param(
+                name = "kwargs",
+                type = SkylarkDict.class,
+                defaultValue = "{}",
+                doc = "Dictionary of arguments."),
+        useLocation = true,
+        selfCall = true)
+    @SkylarkConstructor(objectType = StructApi.class, receiverNameForDoc = "struct")
+    public StructApi createStruct(SkylarkDict<?, ?> kwargs, Location loc) throws EvalException;
+  }
 }
diff --git a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/TopLevelBootstrap.java b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/TopLevelBootstrap.java
index 910a67a..881b5fc 100644
--- a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/TopLevelBootstrap.java
+++ b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/TopLevelBootstrap.java
@@ -26,18 +26,21 @@
   private final Class<? extends SkylarkCommandLineApi> skylarkCommandLineApi;
   private final Class<? extends SkylarkNativeModuleApi> skylarkNativeModuleApi;
   private final Class<? extends SkylarkRuleFunctionsApi<?>> skylarkRuleFunctionsApi;
+  private final StructApi.StructProviderApi structProvider;
 
   public TopLevelBootstrap(
       Class<? extends SkylarkBuildApiGlobals> skylarkBuildApiGlobals,
       Class<? extends SkylarkAttrApi> skylarkAttrApi,
       Class<? extends SkylarkCommandLineApi> skylarkCommandLineApi,
       Class<? extends SkylarkNativeModuleApi> skylarkNativeModuleApi,
-      Class<? extends SkylarkRuleFunctionsApi<?>> skylarkRuleFunctionsApi) {
+      Class<? extends SkylarkRuleFunctionsApi<?>> skylarkRuleFunctionsApi,
+      StructApi.StructProviderApi structProvider) {
     this.skylarkAttrApi = skylarkAttrApi;
     this.skylarkBuildApiGlobals = skylarkBuildApiGlobals;
     this.skylarkCommandLineApi = skylarkCommandLineApi;
     this.skylarkNativeModuleApi = skylarkNativeModuleApi;
     this.skylarkRuleFunctionsApi = skylarkRuleFunctionsApi;
+    this.structProvider = structProvider;
   }
 
   @Override
@@ -47,5 +50,6 @@
     Runtime.setupModuleGlobals(builder, skylarkCommandLineApi);
     Runtime.setupModuleGlobals(builder, skylarkNativeModuleApi);
     Runtime.setupModuleGlobals(builder, skylarkRuleFunctionsApi);
+    builder.put("struct", structProvider);
   }
 }