bazel syntax: rename Environment -> StarlarkThread

The environment features are about to be removed.

This is inevitably a breaking API change (sorry copybara).

PiperOrigin-RevId: 271339546
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 0eb63f0..e064798 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
@@ -61,13 +61,13 @@
 import com.google.devtools.build.lib.skylarkbuildapi.Bootstrap;
 import com.google.devtools.build.lib.skylarkinterface.SkylarkInterfaceUtils;
 import com.google.devtools.build.lib.skylarkinterface.SkylarkModule;
-import com.google.devtools.build.lib.syntax.Environment;
-import com.google.devtools.build.lib.syntax.Environment.Extension;
-import com.google.devtools.build.lib.syntax.Environment.GlobalFrame;
 import com.google.devtools.build.lib.syntax.Mutability;
 import com.google.devtools.build.lib.syntax.SkylarkUtils;
 import com.google.devtools.build.lib.syntax.SkylarkUtils.Phase;
 import com.google.devtools.build.lib.syntax.StarlarkSemantics;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
+import com.google.devtools.build.lib.syntax.StarlarkThread.Extension;
+import com.google.devtools.build.lib.syntax.StarlarkThread.GlobalFrame;
 import com.google.devtools.common.options.Option;
 import com.google.devtools.common.options.OptionDefinition;
 import com.google.devtools.common.options.OptionsProvider;
@@ -652,7 +652,7 @@
 
   private final PrerequisiteValidator prerequisiteValidator;
 
-  private final Environment.GlobalFrame globals;
+  private final StarlarkThread.GlobalFrame globals;
 
   private final ImmutableSet<String> reservedActionMnemonics;
 
@@ -854,7 +854,7 @@
     return BuildOptions.of(configurationOptions, optionsProvider);
   }
 
-  private Environment.GlobalFrame createGlobals(
+  private StarlarkThread.GlobalFrame createGlobals(
       ImmutableMap<String, Object> skylarkAccessibleTopLevels,
       ImmutableList<Bootstrap> bootstraps) {
     ImmutableMap.Builder<String, Object> envBuilder = ImmutableMap.builder();
@@ -882,7 +882,7 @@
   }
 
   @Override
-  public Environment createSkylarkRuleClassEnvironment(
+  public StarlarkThread createRuleClassStarlarkThread(
       Label fileLabel,
       Mutability mutability,
       StarlarkSemantics starlarkSemantics,
@@ -890,8 +890,8 @@
       String astFileContentHashCode,
       Map<String, Extension> importMap,
       ImmutableMap<RepositoryName, RepositoryName> repoMapping) {
-    Environment env =
-        Environment.builder(mutability)
+    StarlarkThread thread =
+        StarlarkThread.builder(mutability)
             .setGlobals(globals.withLabel(fileLabel))
             .setSemantics(starlarkSemantics)
             .setEventHandler(eventHandler)
@@ -905,10 +905,10 @@
             repoMapping,
             new SymbolGenerator<>(fileLabel),
             /* analysisRuleLabel= */ null)
-        .storeInThread(env);
+        .storeInThread(thread);
 
-    SkylarkUtils.setPhase(env, Phase.LOADING);
-    return env;
+    SkylarkUtils.setPhase(thread, Phase.LOADING);
+    return thread;
   }
 
   @Override
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/TemplateVariableInfo.java b/src/main/java/com/google/devtools/build/lib/analysis/TemplateVariableInfo.java
index 14097b2..a4c5613 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/TemplateVariableInfo.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/TemplateVariableInfo.java
@@ -22,11 +22,11 @@
 import com.google.devtools.build.lib.packages.NativeProvider;
 import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
 import com.google.devtools.build.lib.skylarkbuildapi.TemplateVariableInfoApi;
-import com.google.devtools.build.lib.syntax.Environment;
 import com.google.devtools.build.lib.syntax.EvalException;
 import com.google.devtools.build.lib.syntax.FunctionSignature;
 import com.google.devtools.build.lib.syntax.SkylarkDict;
 import com.google.devtools.build.lib.syntax.SkylarkType;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
 import java.util.Map;
 
 /** Provides access to make variables from the current fragments. */
@@ -46,7 +46,7 @@
           TemplateVariableInfo.class, SKYLARK_NAME, SIGNATURE) {
         @Override
         protected TemplateVariableInfo createInstanceFromSkylark(
-            Object[] args, Environment env, Location loc) throws EvalException {
+            Object[] args, StarlarkThread thread, Location loc) throws EvalException {
           Map<String, String> vars =
               SkylarkDict.castSkylarkDictOrNoneToDict(args[0], String.class, String.class, "vars");
           return new TemplateVariableInfo(ImmutableMap.copyOf(vars), location);
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/config/StarlarkDefinedConfigTransition.java b/src/main/java/com/google/devtools/build/lib/analysis/config/StarlarkDefinedConfigTransition.java
index 078a2b6..dd9f39c 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/config/StarlarkDefinedConfigTransition.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/config/StarlarkDefinedConfigTransition.java
@@ -23,12 +23,12 @@
 import com.google.devtools.build.lib.skylarkbuildapi.config.ConfigurationTransitionApi;
 import com.google.devtools.build.lib.skylarkinterface.SkylarkPrinter;
 import com.google.devtools.build.lib.syntax.BaseFunction;
-import com.google.devtools.build.lib.syntax.Environment;
 import com.google.devtools.build.lib.syntax.EvalException;
 import com.google.devtools.build.lib.syntax.Mutability;
 import com.google.devtools.build.lib.syntax.SkylarkDict;
 import com.google.devtools.build.lib.syntax.SkylarkList;
 import com.google.devtools.build.lib.syntax.StarlarkSemantics;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
@@ -109,8 +109,9 @@
       List<String> inputs,
       List<String> outputs,
       StarlarkSemantics semantics,
-      Environment env) {
-    return new RegularTransition(impl, inputs, outputs, semantics, BazelStarlarkContext.from(env));
+      StarlarkThread thread) {
+    return new RegularTransition(
+        impl, inputs, outputs, semantics, BazelStarlarkContext.from(thread));
   }
 
   public static StarlarkDefinedConfigTransition newAnalysisTestTransition(
@@ -273,13 +274,13 @@
     private Object evalFunction(BaseFunction function, ImmutableList<Object> args)
         throws InterruptedException, EvalException {
       try (Mutability mutability = Mutability.create("eval_transition_function")) {
-        Environment env =
-            Environment.builder(mutability)
+        StarlarkThread thread =
+            StarlarkThread.builder(mutability)
                 .setSemantics(semantics)
                 .setEventHandler(getEventHandler())
                 .build();
-        starlarkContext.storeInThread(env);
-        return function.call(args, ImmutableMap.of(), null, env);
+        starlarkContext.storeInThread(thread);
+        return function.call(args, ImmutableMap.of(), null, thread);
       }
     }
 
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/platform/ToolchainInfo.java b/src/main/java/com/google/devtools/build/lib/analysis/platform/ToolchainInfo.java
index d68af64..0ea68cd 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/platform/ToolchainInfo.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/platform/ToolchainInfo.java
@@ -22,11 +22,11 @@
 import com.google.devtools.build.lib.packages.NativeProvider;
 import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
 import com.google.devtools.build.lib.skylarkbuildapi.platform.ToolchainInfoApi;
-import com.google.devtools.build.lib.syntax.Environment;
 import com.google.devtools.build.lib.syntax.EvalException;
 import com.google.devtools.build.lib.syntax.FunctionSignature;
 import com.google.devtools.build.lib.syntax.SkylarkDict;
 import com.google.devtools.build.lib.syntax.SkylarkType;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
 import java.util.Map;
 
 /**
@@ -57,7 +57,7 @@
       new NativeProvider<ToolchainInfo>(ToolchainInfo.class, SKYLARK_NAME, SIGNATURE) {
         @Override
         protected ToolchainInfo createInstanceFromSkylark(
-            Object[] args, Environment env, Location loc) throws EvalException {
+            Object[] args, StarlarkThread thread, Location loc) throws EvalException {
           Map<String, Object> data =
               SkylarkDict.castSkylarkDictOrNoneToDict(args[0], String.class, Object.class, "data");
           return ToolchainInfo.create(data, loc);
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/skylark/BazelBuildApiGlobals.java b/src/main/java/com/google/devtools/build/lib/analysis/skylark/BazelBuildApiGlobals.java
index c7431d6..aa5070e 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/skylark/BazelBuildApiGlobals.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/skylark/BazelBuildApiGlobals.java
@@ -17,8 +17,8 @@
 import com.google.devtools.build.lib.events.Location;
 import com.google.devtools.build.lib.packages.BazelStarlarkContext;
 import com.google.devtools.build.lib.skylarkbuildapi.SkylarkBuildApiGlobals;
-import com.google.devtools.build.lib.syntax.Environment;
 import com.google.devtools.build.lib.syntax.EvalException;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
 
 /**
  * Bazel implementation of {@link SkylarkBuildApiGlobals}: a collection of global skylark build
@@ -28,8 +28,8 @@
 
   @Override
   public SkylarkLateBoundDefault<?> configurationField(
-      String fragment, String name, Location loc, Environment env) throws EvalException {
-    BazelStarlarkContext bazelContext = BazelStarlarkContext.from(env);
+      String fragment, String name, Location loc, StarlarkThread thread) throws EvalException {
+    BazelStarlarkContext bazelContext = BazelStarlarkContext.from(thread);
     Class<?> fragmentClass = bazelContext.getFragmentNameToClass().get(fragment);
 
     if (fragmentClass == null) {
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkActionFactory.java b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkActionFactory.java
index 3a0ea5b..e7671b1 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkActionFactory.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkActionFactory.java
@@ -59,7 +59,6 @@
 import com.google.devtools.build.lib.skylarkbuildapi.SkylarkActionFactoryApi;
 import com.google.devtools.build.lib.skylarkinterface.SkylarkPrinter;
 import com.google.devtools.build.lib.syntax.BaseFunction;
-import com.google.devtools.build.lib.syntax.Environment;
 import com.google.devtools.build.lib.syntax.EvalException;
 import com.google.devtools.build.lib.syntax.EvalUtils;
 import com.google.devtools.build.lib.syntax.FunctionSignature.Shape;
@@ -70,6 +69,7 @@
 import com.google.devtools.build.lib.syntax.SkylarkNestedSet;
 import com.google.devtools.build.lib.syntax.StarlarkMutable;
 import com.google.devtools.build.lib.syntax.StarlarkSemantics;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
 import com.google.devtools.build.lib.vfs.PathFragment;
 import com.google.protobuf.GeneratedMessage;
 import java.nio.charset.StandardCharsets;
@@ -1086,8 +1086,8 @@
   }
 
   @Override
-  public Args args(Environment env) {
-    return new Args(env.mutability(), starlarkSemantics);
+  public Args args(StarlarkThread thread) {
+    return new Args(thread.mutability(), starlarkSemantics);
   }
 
   @Override
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkAttr.java b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkAttr.java
index bfef40d..ef2a8c2 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkAttr.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkAttr.java
@@ -44,7 +44,6 @@
 import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
 import com.google.devtools.build.lib.skylarkbuildapi.SkylarkAttrApi;
 import com.google.devtools.build.lib.skylarkinterface.SkylarkPrinter;
-import com.google.devtools.build.lib.syntax.Environment;
 import com.google.devtools.build.lib.syntax.EvalException;
 import com.google.devtools.build.lib.syntax.EvalUtils;
 import com.google.devtools.build.lib.syntax.FuncallExpression;
@@ -54,6 +53,7 @@
 import com.google.devtools.build.lib.syntax.SkylarkType;
 import com.google.devtools.build.lib.syntax.SkylarkUtils;
 import com.google.devtools.build.lib.syntax.StarlarkFunction;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
 import com.google.devtools.build.lib.util.FileType;
 import com.google.devtools.build.lib.util.FileTypeSet;
 import java.util.List;
@@ -98,11 +98,11 @@
       String doc,
       SkylarkDict<String, Object> arguments,
       FuncallExpression ast,
-      Environment env)
+      StarlarkThread thread)
       throws EvalException {
     // 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).
-    return createAttributeFactory(type, doc, arguments, ast, env, "");
+    return createAttributeFactory(type, doc, arguments, ast, thread, "");
   }
 
   private static ImmutableAttributeFactory createAttributeFactory(
@@ -110,10 +110,10 @@
       String doc,
       SkylarkDict<String, Object> arguments,
       FuncallExpression ast,
-      Environment env,
+      StarlarkThread thread,
       String name)
       throws EvalException {
-    return createAttribute(type, doc, arguments, ast, env, name).buildPartial();
+    return createAttribute(type, doc, arguments, ast, thread, name).buildPartial();
   }
 
   private static Attribute.Builder<?> createAttribute(
@@ -121,7 +121,7 @@
       String doc,
       SkylarkDict<String, Object> arguments,
       FuncallExpression ast,
-      Environment env,
+      StarlarkThread thread,
       String name)
       throws EvalException {
     Attribute.Builder<?> builder = Attribute.attr(name, type).setDoc(doc);
@@ -134,8 +134,8 @@
             new StarlarkCallbackHelper(
                 (StarlarkFunction) defaultValue,
                 ast,
-                env.getSemantics(),
-                BazelStarlarkContext.from(env));
+                thread.getSemantics(),
+                BazelStarlarkContext.from(thread));
         // SkylarkComputedDefaultTemplate needs to know the names of all attributes that it depends
         // on. However, this method does not know anything about other attributes.
         // We solve this problem by asking the StarlarkCallbackHelper for the parameter names used
@@ -149,8 +149,8 @@
         builder.defaultValue(
             defaultValue,
             new BuildType.LabelConversionContext(
-                (Label) env.getGlobals().getLabel(),
-                BazelStarlarkContext.from(env).getRepoMapping()),
+                (Label) thread.getGlobals().getLabel(),
+                BazelStarlarkContext.from(thread).getRepoMapping()),
             DEFAULT_ARG);
       }
     }
@@ -166,7 +166,7 @@
 
     if (containsNonNoneKey(arguments, NON_EMPTY_ARG)
         && (Boolean) arguments.get(NON_EMPTY_ARG)) {
-      if (env.getSemantics().incompatibleDisableDeprecatedAttrParams()) {
+      if (thread.getSemantics().incompatibleDisableDeprecatedAttrParams()) {
         throw new EvalException(
             ast.getLocation(),
             "'non_empty' is no longer supported. use allow_empty instead. You can use "
@@ -195,7 +195,7 @@
 
     if (containsNonNoneKey(arguments, SINGLE_FILE_ARG)
         && (Boolean) arguments.get(SINGLE_FILE_ARG)) {
-      if (env.getSemantics().incompatibleDisableDeprecatedAttrParams()) {
+      if (thread.getSemantics().incompatibleDisableDeprecatedAttrParams()) {
         throw new EvalException(
             ast.getLocation(),
             "'single_file' is no longer supported. use allow_single_file instead. You can use "
@@ -278,7 +278,7 @@
         if (starlarkDefinedTransition.isForAnalysisTesting()) {
           builder.hasAnalysisTestTransition();
         } else {
-          if (!env.getSemantics().experimentalStarlarkConfigTransitions()) {
+          if (!thread.getSemantics().experimentalStarlarkConfigTransitions()) {
             throw new EvalException(
                 ast.getLocation(),
                 "Starlark-defined transitions on rule attributes is experimental and disabled by "
@@ -395,10 +395,10 @@
       SkylarkDict<String, Object> kwargs,
       Type<?> type,
       FuncallExpression ast,
-      Environment env)
+      StarlarkThread thread)
       throws EvalException {
     try {
-      return new Descriptor(name, createAttributeFactory(type, null, kwargs, ast, env));
+      return new Descriptor(name, createAttributeFactory(type, null, kwargs, ast, thread));
     } catch (ConversionException e) {
       throw new EvalException(ast.getLocation(), e.getMessage());
     }
@@ -425,7 +425,7 @@
       SkylarkDict<String, Object> kwargs,
       Type<?> type,
       FuncallExpression ast,
-      Environment env)
+      StarlarkThread thread)
       throws EvalException {
     String whyNotConfigurableReason =
         Preconditions.checkNotNull(maybeGetNonConfigurableReason(type), type);
@@ -434,7 +434,7 @@
       // This trick makes sense only in the context of Skylark (builtin rules should not use it).
       return new Descriptor(
           name,
-          createAttribute(type, null, kwargs, ast, env, "")
+          createAttribute(type, null, kwargs, ast, thread, "")
               .nonconfigurable(whyNotConfigurableReason)
               .buildPartial());
     } catch (ConversionException e) {
@@ -454,17 +454,17 @@
       Boolean mandatory,
       SkylarkList<?> values,
       FuncallExpression ast,
-      Environment env)
+      StarlarkThread thread)
       throws EvalException {
     // TODO(bazel-team): Replace literal strings with constants.
-    SkylarkUtils.checkLoadingOrWorkspacePhase(env, "attr.int", ast.getLocation());
+    SkylarkUtils.checkLoadingOrWorkspacePhase(thread, "attr.int", ast.getLocation());
     return createAttrDescriptor(
         "int",
         EvalUtils.<String, Object>optionMap(
-            env, DEFAULT_ARG, defaultInt, MANDATORY_ARG, mandatory, VALUES_ARG, values),
+            thread, DEFAULT_ARG, defaultInt, MANDATORY_ARG, mandatory, VALUES_ARG, values),
         Type.INTEGER,
         ast,
-        env);
+        thread);
   }
 
   @Override
@@ -474,16 +474,16 @@
       Boolean mandatory,
       SkylarkList<?> values,
       FuncallExpression ast,
-      Environment env)
+      StarlarkThread thread)
       throws EvalException {
-    SkylarkUtils.checkLoadingOrWorkspacePhase(env, "attr.string", ast.getLocation());
+    SkylarkUtils.checkLoadingOrWorkspacePhase(thread, "attr.string", ast.getLocation());
     return createAttrDescriptor(
         "string",
         EvalUtils.<String, Object>optionMap(
-            env, DEFAULT_ARG, defaultString, MANDATORY_ARG, mandatory, VALUES_ARG, values),
+            thread, DEFAULT_ARG, defaultString, MANDATORY_ARG, mandatory, VALUES_ARG, values),
         Type.STRING,
         ast,
-        env);
+        thread);
   }
 
   @Override
@@ -500,16 +500,16 @@
       Object cfg,
       SkylarkList<?> aspects,
       FuncallExpression ast,
-      Environment env)
+      StarlarkThread thread)
       throws EvalException {
-    SkylarkUtils.checkLoadingOrWorkspacePhase(env, "attr.label", ast.getLocation());
+    SkylarkUtils.checkLoadingOrWorkspacePhase(thread, "attr.label", ast.getLocation());
     try {
       ImmutableAttributeFactory attribute =
           createAttributeFactory(
               BuildType.LABEL,
               doc,
               EvalUtils.<String, Object>optionMap(
-                  env,
+                  thread,
                   DEFAULT_ARG,
                   defaultO,
                   EXECUTABLE_ARG,
@@ -531,7 +531,7 @@
                   ASPECTS_ARG,
                   aspects),
               ast,
-              env,
+              thread,
               "label");
       return new Descriptor("label", attribute);
     } catch (EvalException e) {
@@ -547,13 +547,13 @@
       SkylarkList<?> defaultList,
       String doc,
       FuncallExpression ast,
-      Environment env)
+      StarlarkThread thread)
       throws EvalException {
-    SkylarkUtils.checkLoadingOrWorkspacePhase(env, "attr.string_list", ast.getLocation());
+    SkylarkUtils.checkLoadingOrWorkspacePhase(thread, "attr.string_list", ast.getLocation());
     return createAttrDescriptor(
         "string_list",
         EvalUtils.<String, Object>optionMap(
-            env,
+            thread,
             DEFAULT_ARG,
             defaultList,
             MANDATORY_ARG,
@@ -564,7 +564,7 @@
             allowEmpty),
         Type.STRING_LIST,
         ast,
-        env);
+        thread);
   }
 
   @Override
@@ -575,13 +575,13 @@
       SkylarkList<?> defaultList,
       String doc,
       FuncallExpression ast,
-      Environment env)
+      StarlarkThread thread)
       throws EvalException {
-    SkylarkUtils.checkLoadingOrWorkspacePhase(env, "attr.int_list", ast.getLocation());
+    SkylarkUtils.checkLoadingOrWorkspacePhase(thread, "attr.int_list", ast.getLocation());
     return createAttrDescriptor(
         "int_list",
         EvalUtils.<String, Object>optionMap(
-            env,
+            thread,
             DEFAULT_ARG,
             defaultList,
             MANDATORY_ARG,
@@ -592,7 +592,7 @@
             allowEmpty),
         Type.INTEGER_LIST,
         ast,
-        env);
+        thread);
   }
 
   @Override
@@ -609,12 +609,12 @@
       Object cfg,
       SkylarkList<?> aspects,
       FuncallExpression ast,
-      Environment env)
+      StarlarkThread thread)
       throws EvalException {
-    SkylarkUtils.checkLoadingOrWorkspacePhase(env, "attr.label_list", ast.getLocation());
+    SkylarkUtils.checkLoadingOrWorkspacePhase(thread, "attr.label_list", ast.getLocation());
     SkylarkDict<String, Object> kwargs =
         EvalUtils.<String, Object>optionMap(
-            env,
+            thread,
             DEFAULT_ARG,
             defaultList,
             ALLOW_FILES_ARG,
@@ -637,7 +637,7 @@
             aspects);
     try {
       ImmutableAttributeFactory attribute =
-          createAttributeFactory(BuildType.LABEL_LIST, doc, kwargs, ast, env, "label_list");
+          createAttributeFactory(BuildType.LABEL_LIST, doc, kwargs, ast, thread, "label_list");
       return new Descriptor("label_list", attribute);
     } catch (EvalException e) {
       throw new EvalException(ast.getLocation(), e.getMessage(), e);
@@ -658,13 +658,13 @@
       Object cfg,
       SkylarkList<?> aspects,
       FuncallExpression ast,
-      Environment env)
+      StarlarkThread thread)
       throws EvalException {
     SkylarkUtils.checkLoadingOrWorkspacePhase(
-        env, "attr.label_keyed_string_dict", ast.getLocation());
+        thread, "attr.label_keyed_string_dict", ast.getLocation());
     SkylarkDict<String, Object> kwargs =
         EvalUtils.<String, Object>optionMap(
-            env,
+            thread,
             DEFAULT_ARG,
             defaultList,
             ALLOW_FILES_ARG,
@@ -692,7 +692,7 @@
               doc,
               kwargs,
               ast,
-              env,
+              thread,
               "label_keyed_string_dict");
       return new Descriptor("label_keyed_string_dict", attribute);
     } catch (EvalException e) {
@@ -702,29 +702,31 @@
 
   @Override
   public Descriptor boolAttribute(
-      Boolean defaultO, String doc, Boolean mandatory, FuncallExpression ast, Environment env)
+      Boolean defaultO, String doc, Boolean mandatory, FuncallExpression ast, StarlarkThread thread)
       throws EvalException {
-    SkylarkUtils.checkLoadingOrWorkspacePhase(env, "attr.bool", ast.getLocation());
+    SkylarkUtils.checkLoadingOrWorkspacePhase(thread, "attr.bool", ast.getLocation());
     return createAttrDescriptor(
         "bool",
-        EvalUtils.<String, Object>optionMap(env, DEFAULT_ARG, defaultO, MANDATORY_ARG, mandatory),
+        EvalUtils.<String, Object>optionMap(
+            thread, DEFAULT_ARG, defaultO, MANDATORY_ARG, mandatory),
         Type.BOOLEAN,
         ast,
-        env);
+        thread);
   }
 
   @Override
   public Descriptor outputAttribute(
-      Object defaultO, String doc, Boolean mandatory, FuncallExpression ast, Environment env)
+      Object defaultO, String doc, Boolean mandatory, FuncallExpression ast, StarlarkThread thread)
       throws EvalException {
-    SkylarkUtils.checkLoadingOrWorkspacePhase(env, "attr.output", ast.getLocation());
+    SkylarkUtils.checkLoadingOrWorkspacePhase(thread, "attr.output", ast.getLocation());
 
     return createNonconfigurableAttrDescriptor(
         "output",
-        EvalUtils.<String, Object>optionMap(env, DEFAULT_ARG, defaultO, MANDATORY_ARG, mandatory),
+        EvalUtils.<String, Object>optionMap(
+            thread, DEFAULT_ARG, defaultO, MANDATORY_ARG, mandatory),
         BuildType.OUTPUT,
         ast,
-        env);
+        thread);
   }
 
   @Override
@@ -735,14 +737,14 @@
       Boolean mandatory,
       Boolean nonEmpty,
       FuncallExpression ast,
-      Environment env)
+      StarlarkThread thread)
       throws EvalException {
-    SkylarkUtils.checkLoadingOrWorkspacePhase(env, "attr.output_list", ast.getLocation());
+    SkylarkUtils.checkLoadingOrWorkspacePhase(thread, "attr.output_list", ast.getLocation());
 
     return createAttrDescriptor(
         "output_list",
         EvalUtils.<String, Object>optionMap(
-            env,
+            thread,
             DEFAULT_ARG,
             defaultList,
             MANDATORY_ARG,
@@ -753,7 +755,7 @@
             allowEmpty),
         BuildType.OUTPUT_LIST,
         ast,
-        env);
+        thread);
   }
 
   @Override
@@ -764,13 +766,13 @@
       Boolean mandatory,
       Boolean nonEmpty,
       FuncallExpression ast,
-      Environment env)
+      StarlarkThread thread)
       throws EvalException {
-    SkylarkUtils.checkLoadingOrWorkspacePhase(env, "attr.string_dict", ast.getLocation());
+    SkylarkUtils.checkLoadingOrWorkspacePhase(thread, "attr.string_dict", ast.getLocation());
     return createAttrDescriptor(
         "string_dict",
         EvalUtils.<String, Object>optionMap(
-            env,
+            thread,
             DEFAULT_ARG,
             defaultO,
             MANDATORY_ARG,
@@ -781,7 +783,7 @@
             allowEmpty),
         Type.STRING_DICT,
         ast,
-        env);
+        thread);
   }
 
   @Override
@@ -792,13 +794,13 @@
       Boolean mandatory,
       Boolean nonEmpty,
       FuncallExpression ast,
-      Environment env)
+      StarlarkThread thread)
       throws EvalException {
-    SkylarkUtils.checkLoadingOrWorkspacePhase(env, "attr.string_list_dict", ast.getLocation());
+    SkylarkUtils.checkLoadingOrWorkspacePhase(thread, "attr.string_list_dict", ast.getLocation());
     return createAttrDescriptor(
         "string_list_dict",
         EvalUtils.<String, Object>optionMap(
-            env,
+            thread,
             DEFAULT_ARG,
             defaultO,
             MANDATORY_ARG,
@@ -809,20 +811,21 @@
             allowEmpty),
         Type.STRING_LIST_DICT,
         ast,
-        env);
+        thread);
   }
 
   @Override
   public Descriptor licenseAttribute(
-      Object defaultO, String doc, Boolean mandatory, FuncallExpression ast, Environment env)
+      Object defaultO, String doc, Boolean mandatory, FuncallExpression ast, StarlarkThread thread)
       throws EvalException {
-    SkylarkUtils.checkLoadingOrWorkspacePhase(env, "attr.license", ast.getLocation());
+    SkylarkUtils.checkLoadingOrWorkspacePhase(thread, "attr.license", ast.getLocation());
     return createNonconfigurableAttrDescriptor(
         "license",
-        EvalUtils.<String, Object>optionMap(env, DEFAULT_ARG, defaultO, MANDATORY_ARG, mandatory),
+        EvalUtils.<String, Object>optionMap(
+            thread, DEFAULT_ARG, defaultO, MANDATORY_ARG, mandatory),
         BuildType.LICENSE,
         ast,
-        env);
+        thread);
   }
 
   /** A descriptor of an attribute defined in Skylark. */
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 767b2b1..558b6a2 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
@@ -28,11 +28,11 @@
 import com.google.devtools.build.lib.packages.Type.LabelClass;
 import com.google.devtools.build.lib.skylarkbuildapi.SkylarkAttributesCollectionApi;
 import com.google.devtools.build.lib.skylarkinterface.SkylarkPrinter;
-import com.google.devtools.build.lib.syntax.Environment;
 import com.google.devtools.build.lib.syntax.EvalException;
 import com.google.devtools.build.lib.syntax.Runtime;
 import com.google.devtools.build.lib.syntax.SkylarkList;
 import com.google.devtools.build.lib.syntax.SkylarkType;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
 import java.util.HashSet;
 import java.util.LinkedHashMap;
 import java.util.List;
@@ -170,7 +170,7 @@
             val == null
                 ? Runtime.NONE
                 // Attribute values should be type safe
-                : SkylarkType.convertToSkylark(val, (Environment) null));
+                : SkylarkType.convertToSkylark(val, (StarlarkThread) null));
         return;
       }
       if (a.isExecutable()) {
@@ -226,7 +226,8 @@
         for (TransitiveInfoCollection prereq : allPrereq) {
           builder.put(prereq, original.get(AliasProvider.getDependencyLabel(prereq)));
         }
-        attrBuilder.put(skyname, SkylarkType.convertToSkylark(builder.build(), (Environment) null));
+        attrBuilder.put(
+            skyname, SkylarkType.convertToSkylark(builder.build(), (StarlarkThread) null));
       } else if (type == BuildType.LABEL_DICT_UNARY) {
         Map<Label, TransitiveInfoCollection> prereqsByLabel = new LinkedHashMap<>();
         for (TransitiveInfoCollection target :
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkCustomCommandLine.java b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkCustomCommandLine.java
index 9994782..bfacc14 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkCustomCommandLine.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkCustomCommandLine.java
@@ -38,13 +38,13 @@
 import com.google.devtools.build.lib.skylarkbuildapi.FileRootApi;
 import com.google.devtools.build.lib.skylarkinterface.SkylarkPrinter;
 import com.google.devtools.build.lib.syntax.BaseFunction;
-import com.google.devtools.build.lib.syntax.Environment;
 import com.google.devtools.build.lib.syntax.EvalException;
 import com.google.devtools.build.lib.syntax.Mutability;
 import com.google.devtools.build.lib.syntax.Printer;
 import com.google.devtools.build.lib.syntax.Runtime;
 import com.google.devtools.build.lib.syntax.SkylarkList;
 import com.google.devtools.build.lib.syntax.StarlarkSemantics;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
 import com.google.devtools.build.lib.util.Fingerprint;
 import com.google.devtools.build.lib.vfs.PathFragment;
 import java.io.IOException;
@@ -826,12 +826,12 @@
       throws CommandLineExpansionException {
     ImmutableList<Object> args = ImmutableList.of(arg);
     try (Mutability mutability = Mutability.create("map_fn")) {
-      Environment env =
-          Environment.builder(mutability)
+      StarlarkThread thread =
+          StarlarkThread.builder(mutability)
               .setSemantics(starlarkSemantics)
               .setEventHandler(NullEventHandler.INSTANCE)
               .build();
-      return mapFn.call(args, ImmutableMap.of(), null, env);
+      return mapFn.call(args, ImmutableMap.of(), null, thread);
     } catch (EvalException e) {
       throw new CommandLineExpansionException(errorMessage(e.getMessage(), location, e.getCause()));
     } catch (InterruptedException e) {
@@ -849,8 +849,8 @@
       StarlarkSemantics starlarkSemantics)
       throws CommandLineExpansionException {
     try (Mutability mutability = Mutability.create("map_each")) {
-      Environment env =
-          Environment.builder(mutability)
+      StarlarkThread thread =
+          StarlarkThread.builder(mutability)
               .setSemantics(starlarkSemantics)
               // TODO(b/77140311): Error if we issue print statements
               .setEventHandler(NullEventHandler.INSTANCE)
@@ -859,7 +859,7 @@
       int count = originalValues.size();
       for (int i = 0; i < count; ++i) {
         args[0] = originalValues.get(i);
-        Object ret = mapFn.callWithArgArray(args, null, env, location);
+        Object ret = mapFn.callWithArgArray(args, null, thread, location);
         if (ret instanceof String) {
           consumer.accept((String) ret);
         } else if (ret instanceof SkylarkList) {
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 a37294f..52a5c8b 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
@@ -82,7 +82,6 @@
 import com.google.devtools.build.lib.skylarkbuildapi.SkylarkRuleFunctionsApi;
 import com.google.devtools.build.lib.skylarkinterface.SkylarkPrinter;
 import com.google.devtools.build.lib.syntax.BaseFunction;
-import com.google.devtools.build.lib.syntax.Environment;
 import com.google.devtools.build.lib.syntax.EvalException;
 import com.google.devtools.build.lib.syntax.EvalUtils;
 import com.google.devtools.build.lib.syntax.FuncallExpression;
@@ -94,6 +93,7 @@
 import com.google.devtools.build.lib.syntax.SkylarkType;
 import com.google.devtools.build.lib.syntax.SkylarkUtils;
 import com.google.devtools.build.lib.syntax.StarlarkFunction;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
 import com.google.devtools.build.lib.util.FileTypeSet;
 import com.google.devtools.build.lib.util.Pair;
 import java.util.Map;
@@ -291,11 +291,11 @@
       Object buildSetting,
       Object cfg,
       FuncallExpression ast,
-      Environment env)
+      StarlarkThread thread)
       throws EvalException {
-    SkylarkUtils.checkLoadingOrWorkspacePhase(env, "rule", ast.getLocation());
+    SkylarkUtils.checkLoadingOrWorkspacePhase(thread, "rule", ast.getLocation());
 
-    BazelStarlarkContext bazelContext = BazelStarlarkContext.from(env);
+    BazelStarlarkContext bazelContext = BazelStarlarkContext.from(thread);
     // analysis_test=true implies test=true.
     test |= Boolean.TRUE.equals(analysisTest);
 
@@ -330,7 +330,7 @@
       if (implicitOutputs instanceof StarlarkFunction) {
         StarlarkCallbackHelper callback =
             new StarlarkCallbackHelper(
-                (StarlarkFunction) implicitOutputs, ast, env.getSemantics(), bazelContext);
+                (StarlarkFunction) implicitOutputs, ast, thread.getSemantics(), bazelContext);
         builder.setImplicitOutputsFunction(
             new SkylarkImplicitOutputsFunctionWithCallback(callback, ast.getLocation()));
       } else {
@@ -356,7 +356,7 @@
             hostFragments.getContents(String.class, "host_fragments"));
     builder.setConfiguredTargetFunction(implementation);
     builder.setRuleDefinitionEnvironmentLabelAndHashCode(
-        (Label) env.getGlobals().getLabel(), env.getTransitiveContentHashCode());
+        (Label) thread.getGlobals().getLabel(), thread.getTransitiveContentHashCode());
 
     builder.addRequiredToolchains(
         collectToolchainLabels(
@@ -499,7 +499,7 @@
       String doc,
       Boolean applyToGeneratingRules,
       FuncallExpression ast, // just for getLocation(); TODO(adonovan): simplify
-      Environment env)
+      StarlarkThread thread)
       throws EvalException {
     Location location = ast.getLocation();
     ImmutableList.Builder<String> attrAspects = ImmutableList.builder();
@@ -590,7 +590,7 @@
         collectToolchainLabels(
             toolchains.getContents(String.class, "toolchains"),
             ast.getLocation(),
-            BazelStarlarkContext.from(env).getRepoMapping()),
+            BazelStarlarkContext.from(thread).getRepoMapping()),
         applyToGeneratingRules);
   }
 
@@ -638,10 +638,10 @@
     }
 
     @Override
-    public Object call(Object[] args, FuncallExpression astForLocation, Environment env)
+    public Object call(Object[] args, FuncallExpression astForLocation, StarlarkThread thread)
         throws EvalException, InterruptedException, ConversionException {
       Location loc = astForLocation.getLocation();
-      SkylarkUtils.checkLoadingPhase(env, getName(), loc);
+      SkylarkUtils.checkLoadingPhase(thread, getName(), loc);
       if (ruleClass == null) {
         throw new EvalException(loc, "Invalid rule class hasn't been exported by a bzl file");
       }
@@ -666,7 +666,7 @@
       BuildLangTypedAttributeValuesMap attributeValues =
           new BuildLangTypedAttributeValuesMap((Map<String, Object>) args[0]);
       try {
-        PackageContext pkgContext = env.getThreadLocal(PackageContext.class);
+        PackageContext pkgContext = thread.getThreadLocal(PackageContext.class);
         if (pkgContext == null) {
           throw new EvalException(
               loc,
@@ -674,7 +674,7 @@
                   + "Rules may be instantiated only in a BUILD thread.");
         }
         RuleFactory.createAndAddRule(
-            pkgContext, ruleClass, attributeValues, loc, env, new AttributeContainer(ruleClass));
+            pkgContext, ruleClass, attributeValues, loc, thread, new AttributeContainer(ruleClass));
         return Runtime.NONE;
       } catch (InvalidRuleException | NameConflictException e) {
         throw new EvalException(loc, e.getMessage());
@@ -790,9 +790,9 @@
 
   @Override
   public Label label(
-      String labelString, Boolean relativeToCallerRepository, Location loc, Environment env)
+      String labelString, Boolean relativeToCallerRepository, Location loc, StarlarkThread thread)
       throws EvalException {
-    BazelStarlarkContext context = BazelStarlarkContext.from(env);
+    BazelStarlarkContext context = BazelStarlarkContext.from(thread);
 
     // This function is surprisingly complex.
     //
@@ -848,7 +848,7 @@
     } else {
       // This is the label of the BUILD/.bzl file on the top of the current call stack.
       // (Function enter/exit changes getGlobals.)
-      parentLabel = (Label) env.getGlobals().getLabel();
+      parentLabel = (Label) thread.getGlobals().getLabel();
     }
 
     try {
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 1019d96..424aa90 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
@@ -52,7 +52,6 @@
 import com.google.devtools.build.lib.skylarkinterface.SkylarkValue;
 import com.google.devtools.build.lib.syntax.BaseFunction;
 import com.google.devtools.build.lib.syntax.ClassObject;
-import com.google.devtools.build.lib.syntax.Environment;
 import com.google.devtools.build.lib.syntax.EvalException;
 import com.google.devtools.build.lib.syntax.EvalExceptionWithStackTrace;
 import com.google.devtools.build.lib.syntax.EvalUtils;
@@ -62,6 +61,7 @@
 import com.google.devtools.build.lib.syntax.SkylarkNestedSet;
 import com.google.devtools.build.lib.syntax.SkylarkType;
 import com.google.devtools.build.lib.syntax.StarlarkSemantics;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
 import com.google.devtools.build.lib.vfs.PathFragment;
 import java.util.Collections;
 import java.util.LinkedHashMap;
@@ -97,8 +97,8 @@
     SkylarkRuleContext skylarkRuleContext = null;
     try (Mutability mutability = Mutability.create("configured target")) {
       skylarkRuleContext = new SkylarkRuleContext(ruleContext, null, starlarkSemantics);
-      Environment env =
-          Environment.builder(mutability)
+      StarlarkThread thread =
+          StarlarkThread.builder(mutability)
               .setSemantics(starlarkSemantics)
               .setEventHandler(ruleContext.getAnalysisEnvironment().getEventHandler())
               .build(); // NB: loading phase functions are not available: this is analysis already,
@@ -110,7 +110,7 @@
               ruleContext.getTarget().getPackage().getRepositoryMapping(),
               ruleContext.getSymbolGenerator(),
               ruleContext.getLabel())
-          .storeInThread(env);
+          .storeInThread(thread);
 
       RuleClass ruleClass = ruleContext.getRule().getRuleClassObject();
       if (ruleClass.getRuleClassType().equals(RuleClass.Builder.RuleClassType.WORKSPACE)) {
@@ -134,7 +134,7 @@
               /*args=*/ ImmutableList.of(skylarkRuleContext),
               /*kwargs*/ ImmutableMap.of(),
               /*ast=*/ null,
-              env);
+              thread);
 
       if (ruleContext.hasErrors()) {
         return null;
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 86273f2..34cd906 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
@@ -77,7 +77,6 @@
 import com.google.devtools.build.lib.skylarkinterface.SkylarkPrinter;
 import com.google.devtools.build.lib.skylarkinterface.SkylarkValue;
 import com.google.devtools.build.lib.syntax.ClassObject;
-import com.google.devtools.build.lib.syntax.Environment;
 import com.google.devtools.build.lib.syntax.EvalException;
 import com.google.devtools.build.lib.syntax.EvalUtils;
 import com.google.devtools.build.lib.syntax.Printer;
@@ -89,6 +88,7 @@
 import com.google.devtools.build.lib.syntax.SkylarkList.Tuple;
 import com.google.devtools.build.lib.syntax.SkylarkNestedSet;
 import com.google.devtools.build.lib.syntax.StarlarkSemantics;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
 import com.google.devtools.build.lib.vfs.PathFragment;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -879,10 +879,10 @@
       Object executionRequirementsUnchecked,
       Object inputManifestsUnchecked,
       Location loc,
-      Environment env)
+      StarlarkThread thread)
       throws EvalException {
     checkDeprecated(
-        "ctx.actions.run or ctx.actions.run_shell", "ctx.action", loc, env.getSemantics());
+        "ctx.actions.run or ctx.actions.run_shell", "ctx.action", loc, thread.getSemantics());
     checkMutable("action");
     if ((commandUnchecked == Runtime.NONE) == (executableUnchecked == Runtime.NONE)) {
       throw new EvalException(loc, "You must specify either 'command' or 'executable' argument");
@@ -920,14 +920,14 @@
               executionRequirementsUnchecked,
               inputManifestsUnchecked,
               loc,
-              env.getSemantics());
+              thread.getSemantics());
     }
     return Runtime.NONE;
   }
 
   @Override
-  public String expandLocation(String input, SkylarkList targets, Location loc, Environment env)
-      throws EvalException {
+  public String expandLocation(
+      String input, SkylarkList targets, Location loc, StarlarkThread thread) throws EvalException {
     checkMutable("expand_location");
     try {
       return LocationExpander.withExecPaths(
@@ -941,18 +941,18 @@
 
   @Override
   public Runtime.NoneType fileAction(
-      FileApi output, String content, Boolean executable, Location loc, Environment env)
+      FileApi output, String content, Boolean executable, Location loc, StarlarkThread thread)
       throws EvalException {
-    checkDeprecated("ctx.actions.write", "ctx.file_action", loc, env.getSemantics());
+    checkDeprecated("ctx.actions.write", "ctx.file_action", loc, thread.getSemantics());
     checkMutable("file_action");
     actions().write(output, content, executable, loc);
     return Runtime.NONE;
   }
 
   @Override
-  public Runtime.NoneType emptyAction(String mnemonic, Object inputs, Location loc, Environment env)
-      throws EvalException {
-    checkDeprecated("ctx.actions.do_nothing", "ctx.empty_action", loc, env.getSemantics());
+  public Runtime.NoneType emptyAction(
+      String mnemonic, Object inputs, Location loc, StarlarkThread thread) throws EvalException {
+    checkDeprecated("ctx.actions.do_nothing", "ctx.empty_action", loc, thread.getSemantics());
     checkMutable("empty_action");
     actions().doNothing(mnemonic, inputs, loc);
     return Runtime.NONE;
@@ -965,9 +965,10 @@
       SkylarkDict<?, ?> substitutionsUnchecked,
       Boolean executable,
       Location loc,
-      Environment env)
+      StarlarkThread thread)
       throws EvalException {
-    checkDeprecated("ctx.actions.expand_template", "ctx.template_action", loc, env.getSemantics());
+    checkDeprecated(
+        "ctx.actions.expand_template", "ctx.template_action", loc, thread.getSemantics());
     checkMutable("template_action");
     actions().expandTemplate(template, output, substitutionsUnchecked, executable, loc);
     return Runtime.NONE;
@@ -1032,11 +1033,11 @@
       SkylarkDict<?, ?> labelDictUnchecked,
       SkylarkDict<?, ?> executionRequirementsUnchecked,
       Location loc,
-      Environment env)
+      StarlarkThread thread)
       throws ConversionException, EvalException {
     checkMutable("resolve_command");
     Label ruleLabel = getLabel();
-    Map<Label, Iterable<Artifact>> labelDict = checkLabelDict(labelDictUnchecked, loc, env);
+    Map<Label, Iterable<Artifact>> labelDict = checkLabelDict(labelDictUnchecked, loc, thread);
     // The best way to fix this probably is to convert CommandHelper to Skylark.
     CommandHelper helper =
         CommandHelper.builder(getRuleContext())
@@ -1077,8 +1078,8 @@
             "." + Hashing.murmur3_32().hashUnencodedChars(command).toString() + SCRIPT_SUFFIX);
     List<String> argv = helper.buildCommandLine(command, inputs, constructor);
     return Tuple.<Object>of(
-        MutableList.copyOf(env, inputs),
-        MutableList.copyOf(env, argv),
+        MutableList.copyOf(thread, inputs),
+        MutableList.copyOf(thread, argv),
         helper.getToolsRunfilesSuppliers());
   }
 
@@ -1106,7 +1107,7 @@
   // TODO(bazel-team): find a better way to typecheck this argument.
   @SuppressWarnings("unchecked")
   private static Map<Label, Iterable<Artifact>> checkLabelDict(
-      Map<?, ?> labelDict, Location loc, Environment env) throws EvalException {
+      Map<?, ?> labelDict, Location loc, StarlarkThread thread) throws EvalException {
     Map<Label, Iterable<Artifact>> convertedMap = new HashMap<>();
     for (Map.Entry<?, ?> entry : labelDict.entrySet()) {
       Object key = entry.getKey();
@@ -1117,7 +1118,7 @@
       Object val = entry.getValue();
       Iterable<?> valIter;
       try {
-        valIter = EvalUtils.toIterableStrict(val, loc, env);
+        valIter = EvalUtils.toIterableStrict(val, loc, thread);
       } catch (EvalException ex) {
         // EvalException is thrown only if the type is wrong.
         throw new EvalException(
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/skylark/StarlarkAttributeTransitionProvider.java b/src/main/java/com/google/devtools/build/lib/analysis/skylark/StarlarkAttributeTransitionProvider.java
index eb3d662..eed5fb3 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/skylark/StarlarkAttributeTransitionProvider.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/skylark/StarlarkAttributeTransitionProvider.java
@@ -33,10 +33,10 @@
 import com.google.devtools.build.lib.packages.StructProvider;
 import com.google.devtools.build.lib.skylarkbuildapi.SplitTransitionProviderApi;
 import com.google.devtools.build.lib.skylarkinterface.SkylarkPrinter;
-import com.google.devtools.build.lib.syntax.Environment;
 import com.google.devtools.build.lib.syntax.EvalException;
 import com.google.devtools.build.lib.syntax.Runtime;
 import com.google.devtools.build.lib.syntax.SkylarkType;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
 import java.util.LinkedHashMap;
 import java.util.List;
 
@@ -96,7 +96,7 @@
         Object val = attributeMap.get(attribute, attributeMap.getAttributeType(attribute));
         attributes.put(
             Attribute.getSkylarkName(attribute),
-            val == null ? Runtime.NONE : SkylarkType.convertToSkylark(val, (Environment) null));
+            val == null ? Runtime.NONE : SkylarkType.convertToSkylark(val, (StarlarkThread) null));
       }
       attrObject = StructProvider.STRUCT.create(attributes, ERROR_MESSAGE_FOR_NO_ATTR);
     }
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/skylark/StarlarkRuleTransitionProvider.java b/src/main/java/com/google/devtools/build/lib/analysis/skylark/StarlarkRuleTransitionProvider.java
index 355b636..8c330b4 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/skylark/StarlarkRuleTransitionProvider.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/skylark/StarlarkRuleTransitionProvider.java
@@ -29,10 +29,10 @@
 import com.google.devtools.build.lib.packages.Rule;
 import com.google.devtools.build.lib.packages.StructImpl;
 import com.google.devtools.build.lib.packages.StructProvider;
-import com.google.devtools.build.lib.syntax.Environment;
 import com.google.devtools.build.lib.syntax.EvalException;
 import com.google.devtools.build.lib.syntax.Runtime;
 import com.google.devtools.build.lib.syntax.SkylarkType;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
 import java.util.LinkedHashMap;
 import java.util.List;
 
@@ -90,7 +90,7 @@
         }
         attributes.put(
             Attribute.getSkylarkName(attribute.getPublicName()),
-            val == null ? Runtime.NONE : SkylarkType.convertToSkylark(val, (Environment) null));
+            val == null ? Runtime.NONE : SkylarkType.convertToSkylark(val, (StarlarkThread) null));
       }
       attrObject =
           StructProvider.STRUCT.create(
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 bac7c5d..9a68e94 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
@@ -58,6 +58,7 @@
 import com.google.devtools.build.lib.syntax.SkylarkList;
 import com.google.devtools.build.lib.syntax.SkylarkType;
 import com.google.devtools.build.lib.syntax.StarlarkSemantics;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
 import com.google.devtools.build.lib.util.OsUtils;
 import com.google.devtools.build.lib.util.StringUtilities;
 import com.google.devtools.build.lib.vfs.FileSystem;
@@ -136,8 +137,7 @@
             val == null
                 ? Runtime.NONE
                 // Attribute values should be type safe
-                : SkylarkType.convertToSkylark(val,
-                    (com.google.devtools.build.lib.syntax.Environment) null));
+                : SkylarkType.convertToSkylark(val, (StarlarkThread) null));
       }
     }
     attrObject = StructProvider.STRUCT.create(attrBuilder.build(), "No such attribute '%s'");
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkRepositoryFunction.java b/src/main/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkRepositoryFunction.java
index e73380a..72b013e 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkRepositoryFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkRepositoryFunction.java
@@ -39,6 +39,7 @@
 import com.google.devtools.build.lib.syntax.EvalException;
 import com.google.devtools.build.lib.syntax.Mutability;
 import com.google.devtools.build.lib.syntax.StarlarkSemantics;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
 import com.google.devtools.build.lib.vfs.Path;
 import com.google.devtools.build.lib.vfs.PathFragment;
 import com.google.devtools.build.skyframe.SkyFunction.Environment;
@@ -122,8 +123,8 @@
         Preconditions.checkNotNull(blacklistedPackagesValue).getPatterns();
 
     try (Mutability mutability = Mutability.create("Starlark repository")) {
-      com.google.devtools.build.lib.syntax.Environment buildEnv =
-          com.google.devtools.build.lib.syntax.Environment.builder(mutability)
+      StarlarkThread thread =
+          StarlarkThread.builder(mutability)
               .setSemantics(starlarkSemantics)
               .setEventHandler(env.getListener())
               .build();
@@ -136,7 +137,7 @@
               rule.getPackage().getRepositoryMapping(),
               new SymbolGenerator<>(key),
               /* analysisRuleLabel= */ null)
-          .storeInThread(buildEnv);
+          .storeInThread(thread);
 
       SkylarkRepositoryContext skylarkRepositoryContext =
           new SkylarkRepositoryContext(
@@ -177,7 +178,7 @@
               /*args=*/ ImmutableList.of(skylarkRepositoryContext),
               /*kwargs=*/ ImmutableMap.of(),
               null,
-              buildEnv);
+              thread);
       RepositoryResolvedEvent resolved =
           new RepositoryResolvedEvent(
               rule, skylarkRepositoryContext.getAttr(), outputDirectory, retValue);
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 6e55be5..49bc005 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
@@ -49,6 +49,7 @@
 import com.google.devtools.build.lib.syntax.Runtime;
 import com.google.devtools.build.lib.syntax.SkylarkList;
 import com.google.devtools.build.lib.syntax.SkylarkUtils;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
 import java.util.Map;
 
 /**
@@ -66,9 +67,9 @@
       Boolean configure,
       String doc,
       FuncallExpression ast,
-      com.google.devtools.build.lib.syntax.Environment funcallEnv)
+      StarlarkThread funcallThread)
       throws EvalException {
-    SkylarkUtils.checkLoadingOrWorkspacePhase(funcallEnv, "repository_rule", ast.getLocation());
+    SkylarkUtils.checkLoadingOrWorkspacePhase(funcallThread, "repository_rule", ast.getLocation());
     // We'll set the name later, pass the empty string for now.
     RuleClass.Builder builder = new RuleClass.Builder("", RuleClassType.WORKSPACE, true);
 
@@ -90,7 +91,8 @@
     }
     builder.setConfiguredTargetFunction(implementation);
     builder.setRuleDefinitionEnvironmentLabelAndHashCode(
-        (Label) funcallEnv.getGlobals().getLabel(), funcallEnv.getTransitiveContentHashCode());
+        (Label) funcallThread.getGlobals().getLabel(),
+        funcallThread.getTransitiveContentHashCode());
     builder.setWorkspaceOnly();
     return new RepositoryRuleFunction(builder, ast.getLocation());
   }
@@ -130,7 +132,9 @@
 
     @Override
     public Object call(
-        Object[] args, FuncallExpression ast, com.google.devtools.build.lib.syntax.Environment env)
+        Object[] args,
+        FuncallExpression ast,
+        com.google.devtools.build.lib.syntax.StarlarkThread thread)
         throws EvalException, InterruptedException {
       String ruleClassName = null;
       Expression function = ast.getFunction();
@@ -152,7 +156,7 @@
       }
       try {
         RuleClass ruleClass = builder.build(ruleClassName, ruleClassName);
-        PackageContext context = PackageFactory.getContext(env, ast.getLocation());
+        PackageContext context = PackageFactory.getContext(thread, ast.getLocation());
         Package.Builder packageBuilder = context.getBuilder();
 
         @SuppressWarnings("unchecked")
@@ -167,12 +171,12 @@
                 .append(" (rule definition at ")
                 .append(ruleClassDefinitionLocation.toString())
                 .append("):");
-        for (DebugFrame frame : env.listFrames(ast.getLocation())) {
+        for (DebugFrame frame : thread.listFrames(ast.getLocation())) {
           callStack.append("\n - ").append(frame.location().toString());
         }
 
         WorkspaceFactoryHelper.addMainRepoEntry(
-            packageBuilder, externalRepoName, env.getSemantics());
+            packageBuilder, externalRepoName, thread.getSemantics());
 
         WorkspaceFactoryHelper.addRepoMappings(
             packageBuilder, attributeValues, externalRepoName, ast.getLocation());
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/cpp/BazelCcModule.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/cpp/BazelCcModule.java
index 5e393c8..0c5dbf3 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/rules/cpp/BazelCcModule.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/cpp/BazelCcModule.java
@@ -31,10 +31,10 @@
 import com.google.devtools.build.lib.rules.cpp.FeatureConfigurationForStarlark;
 import com.google.devtools.build.lib.rules.cpp.LibraryToLink;
 import com.google.devtools.build.lib.skylarkbuildapi.cpp.BazelCcModuleApi;
-import com.google.devtools.build.lib.syntax.Environment;
 import com.google.devtools.build.lib.syntax.EvalException;
 import com.google.devtools.build.lib.syntax.SkylarkList;
 import com.google.devtools.build.lib.syntax.SkylarkList.Tuple;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
 
 /**
  * A module that contains Skylark utilities for C++ support.
@@ -82,7 +82,7 @@
       boolean disallowPicOutputs,
       boolean disallowNopicOutputs,
       Location location,
-      Environment environment)
+      StarlarkThread thread)
       throws EvalException, InterruptedException {
     return compile(
         skylarkActionFactoryApi,
@@ -122,7 +122,7 @@
       boolean linkDepsStatically,
       SkylarkList<Artifact> additionalInputs,
       Location location,
-      Environment env)
+      StarlarkThread thread)
       throws InterruptedException, EvalException {
     return super.link(
         actions,
@@ -138,7 +138,7 @@
         additionalInputs,
         /* grepIncludes= */ null,
         location,
-        env);
+        thread);
   }
 
   @Override
diff --git a/src/main/java/com/google/devtools/build/lib/cmdline/Label.java b/src/main/java/com/google/devtools/build/lib/cmdline/Label.java
index 8ab41a9..a58f47a 100644
--- a/src/main/java/com/google/devtools/build/lib/cmdline/Label.java
+++ b/src/main/java/com/google/devtools/build/lib/cmdline/Label.java
@@ -30,7 +30,7 @@
 import com.google.devtools.build.lib.skylarkinterface.SkylarkModuleCategory;
 import com.google.devtools.build.lib.skylarkinterface.SkylarkPrinter;
 import com.google.devtools.build.lib.skylarkinterface.SkylarkValue;
-import com.google.devtools.build.lib.syntax.Environment;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
 import com.google.devtools.build.lib.util.StringUtilities;
 import com.google.devtools.build.lib.vfs.PathFragment;
 import com.google.devtools.build.skyframe.SkyFunctionName;
@@ -503,7 +503,7 @@
    * {@code //wiz:quux} relative to {@code //foo/bar:baz} is {@code //wiz:quux}.
    *
    * @param relName the relative label name; must be non-empty.
-   * @param env the Starlark thread, which must provide a thread-local {@code HasRepoMapping}.
+   * @param thread the Starlark thread, which must provide a thread-local {@code HasRepoMapping}.
    */
   @SkylarkCallable(
       name = "relative",
@@ -537,9 +537,9 @@
             type = String.class,
             doc = "The label that will be resolved relative to this one.")
       },
-      useEnvironment = true)
-  public Label getRelative(String relName, Environment env) throws LabelSyntaxException {
-    HasRepoMapping hrm = env.getThreadLocal(HasRepoMapping.class);
+      useStarlarkThread = true)
+  public Label getRelative(String relName, StarlarkThread thread) throws LabelSyntaxException {
+    HasRepoMapping hrm = thread.getThreadLocal(HasRepoMapping.class);
     return getRelativeWithRemapping(relName, hrm.getRepoMapping());
   }
 
diff --git a/src/main/java/com/google/devtools/build/lib/packages/BazelLibrary.java b/src/main/java/com/google/devtools/build/lib/packages/BazelLibrary.java
index 44fa1be..0fdcc80 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/BazelLibrary.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/BazelLibrary.java
@@ -16,9 +16,9 @@
 
 import com.google.common.collect.ImmutableMap;
 import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
-import com.google.devtools.build.lib.syntax.Environment.GlobalFrame;
 import com.google.devtools.build.lib.syntax.MethodLibrary;
 import com.google.devtools.build.lib.syntax.Runtime;
+import com.google.devtools.build.lib.syntax.StarlarkThread.GlobalFrame;
 
 /**
  * A helper class containing built in skylark functions for Bazel (BUILD files and .bzl files).
diff --git a/src/main/java/com/google/devtools/build/lib/packages/BazelStarlarkContext.java b/src/main/java/com/google/devtools/build/lib/packages/BazelStarlarkContext.java
index 2cf9109..9bd2299 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/BazelStarlarkContext.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/BazelStarlarkContext.java
@@ -19,21 +19,21 @@
 import com.google.devtools.build.lib.analysis.RuleDefinitionContext;
 import com.google.devtools.build.lib.cmdline.Label;
 import com.google.devtools.build.lib.cmdline.RepositoryName;
-import com.google.devtools.build.lib.syntax.Environment;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
 import javax.annotation.Nullable;
 
 /** Contextual information associated with each Starlark thread created by Bazel. */
 public class BazelStarlarkContext implements RuleDefinitionContext, Label.HasRepoMapping {
 
   /** Return the Bazel information associated with the specified Starlark thread. */
-  public static BazelStarlarkContext from(Environment env) {
-    return env.getThreadLocal(BazelStarlarkContext.class);
+  public static BazelStarlarkContext from(StarlarkThread thread) {
+    return thread.getThreadLocal(BazelStarlarkContext.class);
   }
 
   /** Save this BazelStarlarkContext in the specified Starlark thread. */
-  public void storeInThread(Environment env) {
-    env.setThreadLocal(BazelStarlarkContext.class, this);
-    env.setThreadLocal(Label.HasRepoMapping.class, this);
+  public void storeInThread(StarlarkThread thread) {
+    thread.setThreadLocal(BazelStarlarkContext.class, this);
+    thread.setThreadLocal(Label.HasRepoMapping.class, this);
   }
 
   private final String toolsRepository;
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 e7375ec..6aabec1 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,10 +17,10 @@
 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.Environment;
 import com.google.devtools.build.lib.syntax.EvalException;
 import com.google.devtools.build.lib.syntax.FunctionSignature;
 import com.google.devtools.build.lib.syntax.SkylarkType;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
 import com.google.devtools.build.lib.util.Pair;
 import javax.annotation.Nullable;
 
@@ -38,7 +38,7 @@
  * </pre>
  *
  * To allow construction from Skylark and custom construction logic, override {@link
- * ProviderFromFunction#createInstanceFromSkylark(Object[], Environment, Location)}.
+ * ProviderFromFunction#createInstanceFromSkylark(Object[], StarlarkThread, Location)}.
  *
  * @deprecated use {@link BuiltinProvider} instead.
  */
@@ -128,8 +128,8 @@
   }
 
   @Override
-  protected InfoInterface createInstanceFromSkylark(Object[] args, Environment env, Location loc)
-      throws EvalException {
+  protected InfoInterface createInstanceFromSkylark(
+      Object[] args, StarlarkThread thread, Location loc) throws EvalException {
     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 c355dc9..56124b8 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
@@ -48,8 +48,6 @@
 import com.google.devtools.build.lib.syntax.CallUtils;
 import com.google.devtools.build.lib.syntax.ClassObject;
 import com.google.devtools.build.lib.syntax.DefStatement;
-import com.google.devtools.build.lib.syntax.Environment;
-import com.google.devtools.build.lib.syntax.Environment.Extension;
 import com.google.devtools.build.lib.syntax.EvalException;
 import com.google.devtools.build.lib.syntax.EvalUtils;
 import com.google.devtools.build.lib.syntax.Expression;
@@ -72,6 +70,8 @@
 import com.google.devtools.build.lib.syntax.SkylarkUtils;
 import com.google.devtools.build.lib.syntax.SkylarkUtils.Phase;
 import com.google.devtools.build.lib.syntax.StarlarkSemantics;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
+import com.google.devtools.build.lib.syntax.StarlarkThread.Extension;
 import com.google.devtools.build.lib.syntax.Statement;
 import com.google.devtools.build.lib.syntax.StringLiteral;
 import com.google.devtools.build.lib.syntax.ValidationEnvironment;
@@ -138,22 +138,16 @@
         throws EvalException;
   }
 
-  /**
-   * An extension to the global namespace of the BUILD language.
-   */
-  // TODO(bazel-team): this is largely unrelated to syntax.Environment.Extension,
+  /** An extension to the global namespace of the BUILD language. */
+  // TODO(bazel-team): this is largely unrelated to syntax.StarlarkThread.Extension,
   // and should probably be renamed PackageFactory.RuntimeExtension, since really,
   // we're extending the Runtime with more classes.
   public interface EnvironmentExtension {
-    /**
-     * Update the global environment with the identifiers this extension contributes.
-     */
-    void update(Environment environment);
+    /** Update the global environment with the identifiers this extension contributes. */
+    void update(StarlarkThread thread);
 
-    /**
-     * Update the global environment of WORKSPACE files.
-     */
-    void updateWorkspace(Environment environment);
+    /** Update the global environment of WORKSPACE files. */
+    void updateWorkspace(StarlarkThread thread);
 
     /**
      * Returns the extra functions needed to be added to the Skylark native module.
@@ -543,7 +537,7 @@
       },
       documented = false,
       useAst = true,
-      useEnvironment = true)
+      useStarlarkThread = true)
   private static final BuiltinFunction.Factory newGlobFunction =
       new BuiltinFunction.Factory("glob") {
         public BuiltinFunction create(final PackageContext originalContext) {
@@ -554,10 +548,16 @@
                 Integer excludeDirectories,
                 Object allowEmpty,
                 FuncallExpression ast,
-                Environment env)
+                StarlarkThread thread)
                 throws EvalException, ConversionException, InterruptedException {
               return callGlob(
-                  originalContext, include, exclude, excludeDirectories != 0, allowEmpty, ast, env);
+                  originalContext,
+                  include,
+                  exclude,
+                  excludeDirectories != 0,
+                  allowEmpty,
+                  ast,
+                  thread);
             }
           };
         }
@@ -570,13 +570,13 @@
       boolean excludeDirs,
       Object allowEmptyArgument,
       FuncallExpression ast,
-      Environment env)
+      StarlarkThread thread)
       throws EvalException, ConversionException, InterruptedException {
-    // Skylark build extensions need to get the PackageContext from the Environment;
-    // async glob functions cannot do the same because the Environment is not thread safe.
+    // Skylark build extensions need to get the PackageContext from the StarlarkThread;
+    // async glob functions cannot do the same because the StarlarkThread is not thread safe.
     PackageContext context;
     if (originalContext == null) {
-      context = getContext(env, ast.getLocation());
+      context = getContext(thread, ast.getLocation());
     } else {
       context = originalContext;
     }
@@ -587,7 +587,7 @@
     List<String> matches;
     boolean allowEmpty;
     if (allowEmptyArgument == Runtime.UNBOUND) {
-      allowEmpty = !env.getSemantics().incompatibleDisallowEmptyGlob();
+      allowEmpty = !thread.getSemantics().incompatibleDisallowEmptyGlob();
     } else if (allowEmptyArgument instanceof Boolean) {
       allowEmpty = (Boolean) allowEmptyArgument;
     } else {
@@ -613,7 +613,7 @@
       throw new EvalException(ast.getLocation(), e.getMessage());
     }
 
-    return MutableList.copyOf(env, matches);
+    return MutableList.copyOf(thread, matches);
   }
 
   /**
@@ -635,25 +635,25 @@
       },
       documented = false,
       useAst = true,
-      useEnvironment = true)
+      useStarlarkThread = true)
   private static final BuiltinFunction.Factory newExistingRuleFunction =
       new BuiltinFunction.Factory("existing_rule") {
         public BuiltinFunction create(final PackageContext originalContext) {
           return new BuiltinFunction("existing_rule", this) {
-            public Object invoke(String name, FuncallExpression ast, Environment env)
+            public Object invoke(String name, FuncallExpression ast, StarlarkThread thread)
                 throws EvalException {
-              return callExistingRule(name, ast, env);
+              return callExistingRule(name, ast, thread);
             }
           };
         }
       };
 
-  static Object callExistingRule(String name, FuncallExpression ast, Environment env)
+  static Object callExistingRule(String name, FuncallExpression ast, StarlarkThread thread)
       throws EvalException {
 
-    PackageContext context = getContext(env, ast.getLocation());
+    PackageContext context = getContext(thread, ast.getLocation());
     Target target = context.pkgBuilder.getTarget(name);
-    SkylarkDict<String, Object> rule = targetDict(target, ast.getLocation(), env);
+    SkylarkDict<String, Object> rule = targetDict(target, ast.getLocation(), thread);
 
     if (rule != null) {
       return rule;
@@ -676,31 +676,31 @@
               + "<p><i>Note: If possible, avoid using this function. It makes BUILD files brittle "
               + "and order-dependent.</i>",
       useAst = true,
-      useEnvironment = true)
+      useStarlarkThread = true)
   private static final BuiltinFunction.Factory newExistingRulesFunction =
       new BuiltinFunction.Factory("existing_rules") {
         public BuiltinFunction create(final PackageContext originalContext) {
           return new BuiltinFunction("existing_rules", this) {
             public SkylarkDict<String, SkylarkDict<String, Object>> invoke(
-                FuncallExpression ast, Environment env) throws EvalException {
-              return callExistingRules(ast, env);
+                FuncallExpression ast, StarlarkThread thread) throws EvalException {
+              return callExistingRules(ast, thread);
             }
           };
         }
       };
 
   static SkylarkDict<String, SkylarkDict<String, Object>> callExistingRules(
-      FuncallExpression ast, Environment env) throws EvalException {
-    PackageContext context = getContext(env, ast.getLocation());
+      FuncallExpression ast, StarlarkThread thread) throws EvalException {
+    PackageContext context = getContext(thread, ast.getLocation());
     Collection<Target> targets = context.pkgBuilder.getTargets();
     Location loc = ast.getLocation();
 
-    SkylarkDict<String, SkylarkDict<String, Object>> rules = SkylarkDict.of(env);
+    SkylarkDict<String, SkylarkDict<String, Object>> rules = SkylarkDict.of(thread);
     for (Target t : targets) {
       if (t instanceof Rule) {
-        SkylarkDict<String, Object> rule = targetDict(t, loc, env);
+        SkylarkDict<String, Object> rule = targetDict(t, loc, thread);
         Preconditions.checkNotNull(rule);
-        rules.put(t.getName(), rule, loc, env);
+        rules.put(t.getName(), rule, loc, thread);
       }
     }
 
@@ -712,44 +712,68 @@
    * Syntax is as follows:
    *
    * <pre>{@code
-   *   environment_group(
-   *       name = "sample_group",
-   *       environments = [":env1", ":env2", ...],
-   *       defaults = [":env1", ...]
-   *   )
+   * environment_group(
+   *     name = "sample_group",
+   *     environments = [":env1", ":env2", ...],
+   *     defaults = [":env1", ...]
+   * )
    * }</pre>
    *
    * <p>Where ":env1", "env2", ... are all environment rules declared in the same package. All
    * parameters are mandatory.
    */
-  @SkylarkSignature(name = "environment_group", returnType = Runtime.NoneType.class,
-      doc = "Defines a set of related environments that can be tagged onto rules to prevent"
-      + "incompatible rules from depending on each other.",
+  @SkylarkSignature(
+      name = "environment_group",
+      returnType = Runtime.NoneType.class,
+      doc =
+          "Defines a set of related environments that can be tagged onto rules to prevent"
+              + "incompatible rules from depending on each other.",
       parameters = {
-        @Param(name = "name", type = String.class, positional = false, named = true,
+        @Param(
+            name = "name",
+            type = String.class,
+            positional = false,
+            named = true,
             doc = "The name of the rule."),
         // Both parameter below are lists of label designators
-        @Param(name = "environments", type = SkylarkList.class, generic1 = Object.class,
-            positional = false, named = true,
+        @Param(
+            name = "environments",
+            type = SkylarkList.class,
+            generic1 = Object.class,
+            positional = false,
+            named = true,
             doc = "A list of Labels for the environments to be grouped, from the same package."),
-        @Param(name = "defaults", type = SkylarkList.class, generic1 = Object.class,
-            positional = false, named = true,
-            doc = "A list of Labels.")}, // TODO(bazel-team): document what that is
-      documented = false, useLocation = true)
+        @Param(
+            name = "defaults",
+            type = SkylarkList.class,
+            generic1 = Object.class,
+            positional = false,
+            named = true,
+            doc = "A list of Labels.")
+      }, // TODO(bazel-team): document what that is
+      documented = false,
+      useLocation = true)
   private static final BuiltinFunction.Factory newEnvironmentGroupFunction =
       new BuiltinFunction.Factory("environment_group") {
         public BuiltinFunction create(final PackageContext context) {
           return new BuiltinFunction("environment_group", this) {
             public Runtime.NoneType invoke(
-                String name, SkylarkList environmentsList, SkylarkList defaultsList,
-                Location loc) throws EvalException, ConversionException {
-              List<Label> environments = BuildType.LABEL_LIST.convert(environmentsList,
-                  "'environment_group argument'", context.pkgBuilder.getBuildFileLabel());
-              List<Label> defaults = BuildType.LABEL_LIST.convert(defaultsList,
-                  "'environment_group argument'", context.pkgBuilder.getBuildFileLabel());
+                String name, SkylarkList environmentsList, SkylarkList defaultsList, Location loc)
+                throws EvalException, ConversionException {
+              List<Label> environments =
+                  BuildType.LABEL_LIST.convert(
+                      environmentsList,
+                      "'environment_group argument'",
+                      context.pkgBuilder.getBuildFileLabel());
+              List<Label> defaults =
+                  BuildType.LABEL_LIST.convert(
+                      defaultsList,
+                      "'environment_group argument'",
+                      context.pkgBuilder.getBuildFileLabel());
 
               if (environments.isEmpty()) {
-                throw new EvalException(location,
+                throw new EvalException(
+                    location,
                     "environment group " + name + " must contain at least one environment");
               }
               try {
@@ -757,8 +781,8 @@
                     name, environments, defaults, context.eventHandler, loc);
                 return Runtime.NONE;
               } catch (LabelSyntaxException e) {
-                throw new EvalException(loc,
-                    "environment group has invalid name: " + name + ": " + e.getMessage());
+                throw new EvalException(
+                    loc, "environment group has invalid name: " + name + ": " + e.getMessage());
               } catch (Package.NameConflictException e) {
                 throw new EvalException(loc, e.getMessage());
               }
@@ -769,40 +793,36 @@
 
   /** Returns a function-value implementing "exports_files" in the specified package context. */
   @SkylarkSignature(
-    name = "exports_files",
-    returnType = Runtime.NoneType.class,
-    doc = "Declare a set of files as exported",
-    parameters = {
-      @Param(
-        name = "srcs",
-        type = SkylarkList.class,
-        generic1 = String.class,
-        doc = "A list of strings, the names of the files to export."
-      ),
-      // TODO(blaze-team): make it possible to express a list of label designators,
-      // i.e. a java List or Skylark list of Label or String.
-      @Param(
-        name = "visibility",
-        type = SkylarkList.class,
-        noneable = true,
-        defaultValue = "None",
-        doc =
-            "A list of Labels specifying the visibility of the exported files "
-                + "(defaults to public)."
-      ),
-      @Param(
-        name = "licenses",
-        type = SkylarkList.class,
-        generic1 = String.class,
-        noneable = true,
-        defaultValue = "None",
-        doc = "A list of strings specifying the licenses used in the exported code."
-      )
-    },
-    documented = false,
-    useAst = true,
-    useEnvironment = true
-  )
+      name = "exports_files",
+      returnType = Runtime.NoneType.class,
+      doc = "Declare a set of files as exported",
+      parameters = {
+        @Param(
+            name = "srcs",
+            type = SkylarkList.class,
+            generic1 = String.class,
+            doc = "A list of strings, the names of the files to export."),
+        // TODO(blaze-team): make it possible to express a list of label designators,
+        // i.e. a java List or Skylark list of Label or String.
+        @Param(
+            name = "visibility",
+            type = SkylarkList.class,
+            noneable = true,
+            defaultValue = "None",
+            doc =
+                "A list of Labels specifying the visibility of the exported files "
+                    + "(defaults to public)."),
+        @Param(
+            name = "licenses",
+            type = SkylarkList.class,
+            generic1 = String.class,
+            noneable = true,
+            defaultValue = "None",
+            doc = "A list of strings specifying the licenses used in the exported code.")
+      },
+      documented = false,
+      useAst = true,
+      useStarlarkThread = true)
   private static final BuiltinFunction.Factory newExportsFilesFunction =
       new BuiltinFunction.Factory("exports_files") {
         public BuiltinFunction create() {
@@ -812,17 +832,22 @@
                 Object visibility,
                 Object licenses,
                 FuncallExpression ast,
-                Environment env)
+                StarlarkThread thread)
                 throws EvalException, ConversionException {
-              return callExportsFiles(srcs, visibility, licenses, ast, env);
+              return callExportsFiles(srcs, visibility, licenses, ast, thread);
             }
           };
         }
       };
 
-  static Runtime.NoneType callExportsFiles(Object srcs, Object visibilityO, Object licensesO,
-      FuncallExpression ast, Environment env) throws EvalException, ConversionException {
-    Package.Builder pkgBuilder = getContext(env, ast.getLocation()).pkgBuilder;
+  static Runtime.NoneType callExportsFiles(
+      Object srcs,
+      Object visibilityO,
+      Object licensesO,
+      FuncallExpression ast,
+      StarlarkThread thread)
+      throws EvalException, ConversionException {
+    Package.Builder pkgBuilder = getContext(thread, ast.getLocation()).pkgBuilder;
     List<String> files = Type.STRING_LIST.convert(srcs, "'exports_files' operand");
 
     RuleVisibility visibility;
@@ -868,7 +893,7 @@
             == ThirdPartyLicenseExistencePolicy.NEVER_CHECK) {
           checkLicenses = false;
         } else {
-          checkLicenses = !env.getSemantics().incompatibleDisableThirdPartyLicenseChecking();
+          checkLicenses = !thread.getSemantics().incompatibleDisableThirdPartyLicenseChecking();
         }
 
         if (checkLicenses
@@ -918,28 +943,28 @@
         }
       };
 
-  /**
-   * Returns a function-value implementing "distribs" in the specified package
-   * context.
-   */
+  /** Returns a function-value implementing "distribs" in the specified package context. */
   // TODO(bazel-team): Remove in favor of package.distribs.
   // TODO(bazel-team): Remove all these new*Function-s and/or have static functions
-  // that consult the context dynamically via getContext(env, loc) since we have that,
+  // that consult the context dynamically via getContext(thread, loc) since we have that,
   // and share the functions with the native package... which requires unifying the List types.
-  @SkylarkSignature(name = "distribs", returnType = Runtime.NoneType.class,
+  @SkylarkSignature(
+      name = "distribs",
+      returnType = Runtime.NoneType.class,
       doc = "Declare the distribution(s) for the code in the current package.",
       parameters = {
-        @Param(name = "distribution_strings", type = Object.class,
-            doc = "The distributions.")},
-      documented = false, useLocation = true)
+        @Param(name = "distribution_strings", type = Object.class, doc = "The distributions.")
+      },
+      documented = false,
+      useLocation = true)
   private static final BuiltinFunction.Factory newDistribsFunction =
       new BuiltinFunction.Factory("distribs") {
         public BuiltinFunction create(final PackageContext context) {
           return new BuiltinFunction("distribs", this) {
             public Runtime.NoneType invoke(Object object, Location loc) {
               try {
-                Set<DistributionType> distribs = BuildType.DISTRIBUTIONS.convert(object,
-                    "'distribs' operand");
+                Set<DistributionType> distribs =
+                    BuildType.DISTRIBUTIONS.convert(object, "'distribs' operand");
                 context.pkgBuilder.setDefaultDistribs(distribs);
               } catch (ConversionException e) {
                 context.eventHandler.handle(Event.error(loc, e.getMessage()));
@@ -982,7 +1007,7 @@
       },
       documented = false,
       useAst = true,
-      useEnvironment = true)
+      useStarlarkThread = true)
   private static final BuiltinFunction.Factory newPackageGroupFunction =
       new BuiltinFunction.Factory("package_group") {
         public BuiltinFunction create() {
@@ -992,9 +1017,9 @@
                 SkylarkList packages,
                 SkylarkList includes,
                 FuncallExpression ast,
-                Environment env)
+                StarlarkThread thread)
                 throws EvalException, ConversionException {
-              return callPackageFunction(name, packages, includes, ast, env);
+              return callPackageFunction(name, packages, includes, ast, thread);
             }
           };
         }
@@ -1002,12 +1027,12 @@
 
   @Nullable
   private static SkylarkDict<String, Object> targetDict(
-      Target target, Location loc, Environment env)
+      Target target, Location loc, StarlarkThread thread)
       throws NotRepresentableException, EvalException {
     if (target == null || !(target instanceof Rule)) {
       return null;
     }
-    SkylarkDict<String, Object> values = SkylarkDict.<String, Object>of(env);
+    SkylarkDict<String, Object> values = SkylarkDict.<String, Object>of(thread);
 
     Rule rule = (Rule) target;
     AttributeContainer cont = rule.getAttributeContainer();
@@ -1027,7 +1052,7 @@
         if (val == null) {
           continue;
         }
-        values.put(attr.getName(), val, loc, env);
+        values.put(attr.getName(), val, loc, thread);
       } catch (NotRepresentableException e) {
         throw new NotRepresentableException(
             String.format(
@@ -1035,8 +1060,8 @@
       }
     }
 
-    values.put("name", rule.getName(), loc, env);
-    values.put("kind", rule.getRuleClass(), loc, env);
+    values.put("name", rule.getName(), loc, thread);
+    values.put("kind", rule.getRuleClass(), loc, thread);
     return values;
   }
 
@@ -1156,9 +1181,10 @@
         String.format("cannot represent %s (%s) in Starlark", val, val.getClass()));
   }
 
-  static Runtime.NoneType callPackageFunction(String name, Object packagesO, Object includesO,
-      FuncallExpression ast, Environment env) throws EvalException, ConversionException {
-    PackageContext context = getContext(env, ast.getLocation());
+  static Runtime.NoneType callPackageFunction(
+      String name, Object packagesO, Object includesO, FuncallExpression ast, StarlarkThread thread)
+      throws EvalException, ConversionException {
+    PackageContext context = getContext(thread, ast.getLocation());
 
     List<String> packages = Type.STRING_LIST.convert(
         packagesO, "'package_group.packages argument'");
@@ -1211,15 +1237,15 @@
 
     return new BaseFunction("package", FunctionSignature.namedOnly(0, argumentNames)) {
       @Override
-      public Object call(Object[] arguments, FuncallExpression ast, Environment env)
+      public Object call(Object[] arguments, FuncallExpression ast, StarlarkThread thread)
           throws EvalException {
 
-        Package.Builder pkgBuilder = getContext(env, ast.getLocation()).pkgBuilder;
+        Package.Builder pkgBuilder = getContext(thread, ast.getLocation()).pkgBuilder;
 
         // Validate parameter list
         if (pkgBuilder.isPackageFunctionUsed()) {
-          throw new EvalException(ast.getLocation(),
-              "'package' can only be used once per BUILD file");
+          throw new EvalException(
+              ast.getLocation(), "'package' can only be used once per BUILD file");
         }
         pkgBuilder.setPackageFunctionUsed();
 
@@ -1235,8 +1261,8 @@
         }
 
         if (!foundParameter) {
-          throw new EvalException(ast.getLocation(),
-              "at least one argument must be given to the 'package' function");
+          throw new EvalException(
+              ast.getLocation(), "at least one argument must be given to the 'package' function");
         }
 
         return Runtime.NONE;
@@ -1244,13 +1270,10 @@
     };
   }
 
-
-  /**
-   * Get the PackageContext by looking up in the environment.
-   */
-  public static PackageContext getContext(Environment env, Location location)
+  /** Get the PackageContext by looking up in the environment. */
+  public static PackageContext getContext(StarlarkThread thread, Location location)
       throws EvalException {
-    PackageContext value = env.getThreadLocal(PackageContext.class);
+    PackageContext value = thread.getThreadLocal(PackageContext.class);
     if (value == null) {
       // if PackageContext is missing, we're not called from a BUILD file. This happens if someone
       // uses native.some_func() in the wrong place.
@@ -1294,11 +1317,11 @@
     }
 
     @SuppressWarnings({"unchecked", "unused"})
-    public Runtime.NoneType invoke(Map<String, Object> kwargs, Location loc, Environment env)
+    public Runtime.NoneType invoke(Map<String, Object> kwargs, Location loc, StarlarkThread thread)
         throws EvalException, InterruptedException {
-      SkylarkUtils.checkLoadingOrWorkspacePhase(env, ruleClassName, loc);
+      SkylarkUtils.checkLoadingOrWorkspacePhase(thread, ruleClassName, loc);
       try {
-        addRule(getContext(env, loc), kwargs, loc, env);
+        addRule(getContext(thread, loc), kwargs, loc, thread);
       } catch (RuleFactory.InvalidRuleException | Package.NameConflictException e) {
         throw new EvalException(loc, e.getMessage());
       }
@@ -1306,13 +1329,13 @@
     }
 
     private void addRule(
-        PackageContext context, Map<String, Object> kwargs, Location loc, Environment env)
+        PackageContext context, Map<String, Object> kwargs, Location loc, StarlarkThread thread)
         throws RuleFactory.InvalidRuleException, Package.NameConflictException,
             InterruptedException {
       BuildLangTypedAttributeValuesMap attributeValues =
           new BuildLangTypedAttributeValuesMap(kwargs);
       RuleFactory.createAndAddRule(
-          context, ruleClass, attributeValues, loc, env, new AttributeContainer(ruleClass));
+          context, ruleClass, attributeValues, loc, thread, new AttributeContainer(ruleClass));
     }
 
     @Override
@@ -1561,9 +1584,9 @@
    * execution of one BUILD file. (We use a PackageContext object in preference to storing these
    * values in mutable fields of the PackageFactory.)
    *
-   * <p>PLEASE NOTE: the PackageContext is referred to by the Environment, but should become
-   * unreachable once the Environment is discarded at the end of evaluation. Please be aware of your
-   * memory footprint when making changes here!
+   * <p>PLEASE NOTE: the PackageContext is referred to by the StarlarkThread, but should become
+   * unreachable once the StarlarkThread is discarded at the end of evaluation. Please be aware of
+   * your memory footprint when making changes here!
    */
   public static class PackageContext {
     final Package.Builder pkgBuilder;
@@ -1629,10 +1652,10 @@
     return StructProvider.STRUCT.create(builder.build(), "no native function or rule '%s'");
   }
 
-  private void buildPkgEnv(Environment pkgEnv, PackageContext context) {
+  private void buildPkgThread(StarlarkThread pkgThread, PackageContext context) {
     // TODO(bazel-team): remove the naked functions that are redundant with the nativeModule,
     // or if not possible, at least make them straight copies from the native module variant.
-    // or better, use a common Environment.Frame for these common bindings
+    // or better, use a common StarlarkThread.Frame for these common bindings
     // (that shares a backing ImmutableMap for the bindings?)
     Object packageNameFunction;
     Object repositoryNameFunction;
@@ -1645,7 +1668,7 @@
           "error getting package_name or repository_name functions from the native module",
           exception);
     }
-    pkgEnv
+    pkgThread
         .setup("distribs", newDistribsFunction.apply(context))
         .setup("glob", newGlobFunction.apply(context))
         .setup("licenses", newLicensesFunction.apply(context))
@@ -1659,16 +1682,16 @@
         .setup("existing_rules", newExistingRulesFunction.apply(context));
 
     for (Map.Entry<String, BuiltinRuleFunction> entry : ruleFunctions.entrySet()) {
-      pkgEnv.setup(entry.getKey(), entry.getValue());
+      pkgThread.setup(entry.getKey(), entry.getValue());
     }
 
     for (EnvironmentExtension extension : environmentExtensions) {
-      extension.update(pkgEnv);
+      extension.update(pkgThread);
     }
 
     // TODO(adonovan): save this as a field in LOADING-phase BazelSkylarkContext.
     // It needn't be a separate thread-local.
-    pkgEnv.setThreadLocal(PackageContext.class, context);
+    pkgThread.setThreadLocal(PackageContext.class, context);
   }
 
   /**
@@ -1715,14 +1738,14 @@
     StoredEventHandler eventHandler = new StoredEventHandler();
 
     try (Mutability mutability = Mutability.create("package %s", packageId)) {
-      Environment pkgEnv =
-          Environment.builder(mutability)
+      StarlarkThread pkgThread =
+          StarlarkThread.builder(mutability)
               .setGlobals(BazelLibrary.GLOBALS)
               .setSemantics(starlarkSemantics)
               .setEventHandler(eventHandler)
               .setImportedExtensions(imports)
               .build();
-      SkylarkUtils.setPhase(pkgEnv, Phase.LOADING);
+      SkylarkUtils.setPhase(pkgThread, Phase.LOADING);
 
       new BazelStarlarkContext(
               ruleClassProvider.getToolsRepository(),
@@ -1730,7 +1753,7 @@
               repositoryMapping,
               new SymbolGenerator<>(packageId),
               /*analysisRuleLabel=*/ null)
-          .storeInThread(pkgEnv);
+          .storeInThread(pkgThread);
 
       pkgBuilder.setFilename(buildFilePath)
           .setDefaultVisibility(defaultVisibility)
@@ -1748,7 +1771,7 @@
 
       // Stuff that closes over the package context:
       PackageContext context = new PackageContext(pkgBuilder, globber, eventHandler);
-      buildPkgEnv(pkgEnv, context);
+      buildPkgThread(pkgThread, context);
 
       if (!validatePackageIdentifier(packageId, file.getLocation(), eventHandler)) {
         pkgBuilder.setContainsErrors();
@@ -1780,7 +1803,7 @@
         }
       }
 
-      if (!ValidationEnvironment.validateFile(file, pkgEnv, /*isBuildFile=*/ true, eventHandler)
+      if (!ValidationEnvironment.validateFile(file, pkgThread, /*isBuildFile=*/ true, eventHandler)
           || !checkBuildSyntax(file, eventHandler)) {
         pkgBuilder.setContainsErrors();
       }
@@ -1789,7 +1812,7 @@
       // as containing errors" is strewn all over this class.  Refactor to use an
       // event sensor--and see if we can simplify the calling code in
       // createPackage().
-      if (!file.exec(pkgEnv, eventHandler)) {
+      if (!file.exec(pkgThread, eventHandler)) {
         pkgBuilder.setContainsErrors();
       }
     }
@@ -1877,10 +1900,10 @@
   /** Empty EnvironmentExtension */
   public static class EmptyEnvironmentExtension implements EnvironmentExtension {
     @Override
-    public void update(Environment environment) {}
+    public void update(StarlarkThread thread) {}
 
     @Override
-    public void updateWorkspace(Environment environment) {}
+    public void updateWorkspace(StarlarkThread thread) {}
 
     @Override
     public Iterable<PackageArgument<?>> getPackageArguments() {
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
index a293393..0934f6a 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/ProviderFromFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/ProviderFromFunction.java
@@ -16,11 +16,11 @@
 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.Environment;
 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.SkylarkType;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
 import javax.annotation.Nullable;
 
 /**
@@ -51,10 +51,10 @@
   }
 
   @Override
-  protected Object call(Object[] args, @Nullable FuncallExpression ast, Environment env)
+  protected Object call(Object[] args, @Nullable FuncallExpression ast, StarlarkThread thread)
       throws EvalException, InterruptedException {
     Location loc = ast != null ? ast.getLocation() : Location.BUILTIN;
-    return createInstanceFromSkylark(args, env, loc);
+    return createInstanceFromSkylark(args, thread, loc);
   }
 
   /**
@@ -67,5 +67,5 @@
    * @param args an array of argument values sorted as per the signature ({@see BaseFunction#call})
    */
   protected abstract InfoInterface createInstanceFromSkylark(
-      Object[] args, Environment env, Location loc) throws EvalException;
+      Object[] args, StarlarkThread thread, Location loc) throws EvalException;
 }
diff --git a/src/main/java/com/google/devtools/build/lib/packages/RuleClassProvider.java b/src/main/java/com/google/devtools/build/lib/packages/RuleClassProvider.java
index ecff083..4c59884 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/RuleClassProvider.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/RuleClassProvider.java
@@ -20,15 +20,16 @@
 import com.google.devtools.build.lib.cmdline.RepositoryName;
 import com.google.devtools.build.lib.events.EventHandler;
 import com.google.devtools.build.lib.packages.RuleClass.Builder.ThirdPartyLicenseExistencePolicy;
-import com.google.devtools.build.lib.syntax.Environment;
-import com.google.devtools.build.lib.syntax.Environment.Extension;
 import com.google.devtools.build.lib.syntax.Mutability;
 import com.google.devtools.build.lib.syntax.StarlarkSemantics;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
+import com.google.devtools.build.lib.syntax.StarlarkThread.Extension;
 import java.util.Map;
 import javax.annotation.Nullable;
 
 /**
- * The collection of the supported build rules. Provides an Environment for Skylark rule creation.
+ * The collection of the supported build rules. Provides an StarlarkThread for Skylark rule
+ * creation.
  */
 public interface RuleClassProvider extends RuleDefinitionContext {
 
@@ -48,7 +49,7 @@
   Map<String, RuleClass> getRuleClassMap();
 
   /**
-   * Returns a new Skylark Environment instance for rule creation. Implementations need to be thread
+   * Returns a new StarlarkThread instance for rule creation. Implementations need to be thread
    * safe. Be sure to close() the mutability before you return the results of said evaluation.
    *
    * @param label the location of the rule.
@@ -58,9 +59,9 @@
    * @param astFileContentHashCode the hash code identifying this environment.
    * @param importMap map from import string to Extension
    * @param repoMapping map of RepositoryNames to be remapped
-   * @return an Environment, in which to evaluate load time skylark forms.
+   * @return an StarlarkThread, in which to evaluate load time skylark forms.
    */
-  Environment createSkylarkRuleClassEnvironment(
+  StarlarkThread createRuleClassStarlarkThread(
       Label label,
       Mutability mutability,
       StarlarkSemantics starlarkSemantics,
diff --git a/src/main/java/com/google/devtools/build/lib/packages/RuleFactory.java b/src/main/java/com/google/devtools/build/lib/packages/RuleFactory.java
index 0530c17..82f31f7 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/RuleFactory.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/RuleFactory.java
@@ -24,9 +24,9 @@
 import com.google.devtools.build.lib.packages.Package.NameConflictException;
 import com.google.devtools.build.lib.packages.PackageFactory.PackageContext;
 import com.google.devtools.build.lib.syntax.BaseFunction;
-import com.google.devtools.build.lib.syntax.Environment;
 import com.google.devtools.build.lib.syntax.FuncallExpression;
 import com.google.devtools.build.lib.syntax.StarlarkFunction;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
 import com.google.devtools.build.lib.util.Pair;
 import java.util.Map;
 import java.util.Set;
@@ -80,7 +80,7 @@
       BuildLangTypedAttributeValuesMap attributeValues,
       EventHandler eventHandler,
       Location location,
-      @Nullable Environment env,
+      @Nullable StarlarkThread thread,
       AttributeContainer attributeContainer)
       throws InvalidRuleException, InterruptedException {
     Preconditions.checkNotNull(ruleClass);
@@ -110,7 +110,7 @@
     }
 
     AttributesAndLocation generator =
-        generatorAttributesForMacros(attributeValues, env, location, label);
+        generatorAttributesForMacros(attributeValues, thread, location, label);
     try {
       // Examines --incompatible_disable_third_party_license_checking to see if we should check
       // third party targets for license existence.
@@ -119,7 +119,7 @@
       // in RuleClass). This lets Bazel and Blaze migrate away from license logic on independent
       // timelines. See --incompatible_disable_third_party_license_checking comments for details.
       boolean checkThirdPartyLicenses =
-          env != null && !env.getSemantics().incompatibleDisableThirdPartyLicenseChecking();
+          thread != null && !thread.getSemantics().incompatibleDisableThirdPartyLicenseChecking();
       return ruleClass.createRule(
           pkgBuilder,
           label,
@@ -141,15 +141,15 @@
    * @param attributeValues a {@link BuildLangTypedAttributeValuesMap} mapping attribute names to
    *     attribute values of build-language type. Each attribute must be defined for this class of
    *     rule, and have a build-language-typed value which can be converted to the appropriate
-   *     native type of the attribute (i.e. via {@link BuildType#selectableConvert}). There must
-   *     be a map entry for each non-optional attribute of this class of rule.
-   * @param eventHandler a eventHandler on which errors and warnings are reported during
-   *     rule creation
+   *     native type of the attribute (i.e. via {@link BuildType#selectableConvert}). There must be
+   *     a map entry for each non-optional attribute of this class of rule.
+   * @param eventHandler a eventHandler on which errors and warnings are reported during rule
+   *     creation
    * @param location the location at which this rule was declared
-   * @param env the lexical environment of the function call which declared this rule (optional)
+   * @param thread the lexical environment of the function call which declared this rule (optional)
    * @param attributeContainer the {@link AttributeContainer} the rule will contain
-   * @throws InvalidRuleException if the rule could not be constructed for any
-   *     reason (e.g. no {@code name} attribute is defined)
+   * @throws InvalidRuleException if the rule could not be constructed for any reason (e.g. no
+   *     {@code name} attribute is defined)
    * @throws NameConflictException if the rule's name or output files conflict with others in this
    *     package
    * @throws InterruptedException if interrupted
@@ -160,7 +160,7 @@
       BuildLangTypedAttributeValuesMap attributeValues,
       EventHandler eventHandler,
       Location location,
-      @Nullable Environment env,
+      @Nullable StarlarkThread thread,
       AttributeContainer attributeContainer)
       throws InvalidRuleException, NameConflictException, InterruptedException {
     Rule rule =
@@ -170,7 +170,7 @@
             attributeValues,
             eventHandler,
             location,
-            env,
+            thread,
             attributeContainer);
     pkgBuilder.addRule(rule);
     return rule;
@@ -187,7 +187,7 @@
    *     native type of the attribute (i.e. via {@link BuildType#selectableConvert}). There must be
    *     a map entry for each non-optional attribute of this class of rule.
    * @param loc the location of the rule expression
-   * @param env the lexical environment of the function call which declared this rule (optional)
+   * @param thread the lexical environment of the function call which declared this rule (optional)
    * @param attributeContainer the {@link AttributeContainer} the rule will contain
    * @throws InvalidRuleException if the rule could not be constructed for any reason (e.g. no
    *     {@code name} attribute is defined)
@@ -200,7 +200,7 @@
       RuleClass ruleClass,
       BuildLangTypedAttributeValuesMap attributeValues,
       Location loc,
-      @Nullable Environment env,
+      @Nullable StarlarkThread thread,
       AttributeContainer attributeContainer)
       throws InvalidRuleException, NameConflictException, InterruptedException {
     return createAndAddRule(
@@ -209,7 +209,7 @@
         attributeValues,
         context.eventHandler,
         loc,
-        env,
+        thread,
         attributeContainer);
   }
 
@@ -298,19 +298,19 @@
   }
 
   /**
-   * If the rule was created by a macro, this method sets the appropriate values for the
-   * attributes generator_{name, function, location} and returns all attributes.
+   * If the rule was created by a macro, this method sets the appropriate values for the attributes
+   * generator_{name, function, location} and returns all attributes.
    *
    * <p>Otherwise, it returns the given attributes without any changes.
    */
   private static AttributesAndLocation generatorAttributesForMacros(
       BuildLangTypedAttributeValuesMap args,
-      @Nullable Environment env,
+      @Nullable StarlarkThread thread,
       Location location,
       Label label) {
     // Returns the original arguments if a) there is only the rule itself on the stack
     // trace (=> no macro) or b) the attributes have already been set by Python pre-processing.
-    if (env == null) {
+    if (thread == null) {
       return new AttributesAndLocation(args, location);
     }
     boolean hasName = args.containsAttributeNamed("generator_name");
@@ -319,7 +319,7 @@
     if (hasName || hasFunc) {
       return new AttributesAndLocation(args, location);
     }
-    Pair<FuncallExpression, BaseFunction> topCall = env.getTopCall();
+    Pair<FuncallExpression, BaseFunction> topCall = thread.getTopCall();
     if (topCall == null || !(topCall.second instanceof StarlarkFunction)) {
       return new AttributesAndLocation(args, location);
     }
diff --git a/src/main/java/com/google/devtools/build/lib/packages/SkylarkInfo.java b/src/main/java/com/google/devtools/build/lib/packages/SkylarkInfo.java
index c18438f..85960f9 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/SkylarkInfo.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/SkylarkInfo.java
@@ -27,12 +27,12 @@
 import com.google.devtools.build.lib.events.Location;
 import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
 import com.google.devtools.build.lib.syntax.Concatable;
-import com.google.devtools.build.lib.syntax.Environment;
 import com.google.devtools.build.lib.syntax.EvalException;
 import com.google.devtools.build.lib.syntax.EvalUtils;
 import com.google.devtools.build.lib.syntax.SkylarkClassObject;
 import com.google.devtools.build.lib.syntax.SkylarkType;
 import com.google.devtools.build.lib.syntax.StarlarkSemantics;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
 import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
@@ -337,7 +337,7 @@
       this.values = new Object[values.length];
       for (int i = 0; i < values.length; i++) {
         // TODO(b/74396075): Phase out this unnecessary conversion.
-        this.values[i] = SkylarkType.convertToSkylark(values[i], (Environment) null);
+        this.values[i] = SkylarkType.convertToSkylark(values[i], (StarlarkThread) null);
       }
     }
 
diff --git a/src/main/java/com/google/devtools/build/lib/packages/SkylarkNativeModule.java b/src/main/java/com/google/devtools/build/lib/packages/SkylarkNativeModule.java
index ec4ce5b..f818957 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/SkylarkNativeModule.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/SkylarkNativeModule.java
@@ -18,13 +18,13 @@
 import com.google.devtools.build.lib.events.Location;
 import com.google.devtools.build.lib.packages.Type.ConversionException;
 import com.google.devtools.build.lib.skylarkbuildapi.SkylarkNativeModuleApi;
-import com.google.devtools.build.lib.syntax.Environment;
 import com.google.devtools.build.lib.syntax.EvalException;
 import com.google.devtools.build.lib.syntax.FuncallExpression;
 import com.google.devtools.build.lib.syntax.Runtime;
 import com.google.devtools.build.lib.syntax.SkylarkDict;
 import com.google.devtools.build.lib.syntax.SkylarkList;
 import com.google.devtools.build.lib.syntax.SkylarkUtils;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
 
 /**
  * A class for the Skylark native module. TODO(laurentlb): Some definitions are duplicated from
@@ -39,22 +39,22 @@
       Integer excludeDirectories,
       Object allowEmpty,
       FuncallExpression ast,
-      Environment env)
+      StarlarkThread thread)
       throws EvalException, ConversionException, InterruptedException {
-    SkylarkUtils.checkLoadingPhase(env, "native.glob", ast.getLocation());
+    SkylarkUtils.checkLoadingPhase(thread, "native.glob", ast.getLocation());
     try {
       return PackageFactory.callGlob(
-          null, include, exclude, excludeDirectories != 0, allowEmpty, ast, env);
+          null, include, exclude, excludeDirectories != 0, allowEmpty, ast, thread);
     } catch (IllegalArgumentException e) {
       throw new EvalException(ast.getLocation(), "illegal argument in call to glob", e);
     }
   }
 
   @Override
-  public Object existingRule(String name, FuncallExpression ast, Environment env)
+  public Object existingRule(String name, FuncallExpression ast, StarlarkThread thread)
       throws EvalException, InterruptedException {
-    SkylarkUtils.checkLoadingOrWorkspacePhase(env, "native.existing_rule", ast.getLocation());
-    return PackageFactory.callExistingRule(name, ast, env);
+    SkylarkUtils.checkLoadingOrWorkspacePhase(thread, "native.existing_rule", ast.getLocation());
+    return PackageFactory.callExistingRule(name, ast, thread);
   }
 
   /*
@@ -63,43 +63,48 @@
   */
   @Override
   public SkylarkDict<String, SkylarkDict<String, Object>> existingRules(
-      FuncallExpression ast, Environment env)
-      throws EvalException, InterruptedException {
-    SkylarkUtils.checkLoadingOrWorkspacePhase(env, "native.existing_rules", ast.getLocation());
-    return PackageFactory.callExistingRules(ast, env);
+      FuncallExpression ast, StarlarkThread thread) throws EvalException, InterruptedException {
+    SkylarkUtils.checkLoadingOrWorkspacePhase(thread, "native.existing_rules", ast.getLocation());
+    return PackageFactory.callExistingRules(ast, thread);
   }
 
   @Override
-  public Runtime.NoneType packageGroup(String name, SkylarkList<?> packages,
+  public Runtime.NoneType packageGroup(
+      String name,
+      SkylarkList<?> packages,
       SkylarkList<?> includes,
-      FuncallExpression ast, Environment env) throws EvalException {
-    SkylarkUtils.checkLoadingPhase(env, "native.package_group", ast.getLocation());
-    return PackageFactory.callPackageFunction(name, packages, includes, ast, env);
+      FuncallExpression ast,
+      StarlarkThread thread)
+      throws EvalException {
+    SkylarkUtils.checkLoadingPhase(thread, "native.package_group", ast.getLocation());
+    return PackageFactory.callPackageFunction(name, packages, includes, ast, thread);
   }
 
   @Override
-  public Runtime.NoneType exportsFiles(SkylarkList<?> srcs, Object visibility, Object licenses,
-      FuncallExpression ast, Environment env)
+  public Runtime.NoneType exportsFiles(
+      SkylarkList<?> srcs,
+      Object visibility,
+      Object licenses,
+      FuncallExpression ast,
+      StarlarkThread thread)
       throws EvalException {
-    SkylarkUtils.checkLoadingPhase(env, "native.exports_files", ast.getLocation());
-    return PackageFactory.callExportsFiles(srcs, visibility, licenses, ast, env);
+    SkylarkUtils.checkLoadingPhase(thread, "native.exports_files", ast.getLocation());
+    return PackageFactory.callExportsFiles(srcs, visibility, licenses, ast, thread);
   }
 
   @Override
-  public String packageName(FuncallExpression ast, Environment env)
-      throws EvalException {
-    SkylarkUtils.checkLoadingPhase(env, "native.package_name", ast.getLocation());
+  public String packageName(FuncallExpression ast, StarlarkThread thread) throws EvalException {
+    SkylarkUtils.checkLoadingPhase(thread, "native.package_name", ast.getLocation());
     PackageIdentifier packageId =
-        PackageFactory.getContext(env, ast.getLocation()).getBuilder().getPackageIdentifier();
+        PackageFactory.getContext(thread, ast.getLocation()).getBuilder().getPackageIdentifier();
     return packageId.getPackageFragment().getPathString();
   }
 
   @Override
-  public String repositoryName(Location location, Environment env)
-      throws EvalException {
-    SkylarkUtils.checkLoadingPhase(env, "native.repository_name", location);
+  public String repositoryName(Location location, StarlarkThread thread) throws EvalException {
+    SkylarkUtils.checkLoadingPhase(thread, "native.repository_name", location);
     PackageIdentifier packageId =
-        PackageFactory.getContext(env, location).getBuilder().getPackageIdentifier();
+        PackageFactory.getContext(thread, location).getBuilder().getPackageIdentifier();
     return packageId.getRepository().toString();
   }
 }
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 4d42b45..bdb9451 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,9 +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.Environment;
 import com.google.devtools.build.lib.syntax.FunctionSignature;
 import com.google.devtools.build.lib.syntax.SkylarkType;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
 import java.util.Map;
 import java.util.Objects;
 import javax.annotation.Nullable;
@@ -148,7 +148,8 @@
   }
 
   @Override
-  protected SkylarkInfo createInstanceFromSkylark(Object[] args, Environment env, Location loc) {
+  protected SkylarkInfo createInstanceFromSkylark(
+      Object[] args, StarlarkThread thread, Location loc) {
     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/StarlarkCallbackHelper.java b/src/main/java/com/google/devtools/build/lib/packages/StarlarkCallbackHelper.java
index d88edae..d545ccb 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/StarlarkCallbackHelper.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/StarlarkCallbackHelper.java
@@ -17,12 +17,12 @@
 import com.google.devtools.build.lib.events.EventHandler;
 import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
 import com.google.devtools.build.lib.syntax.ClassObject;
-import com.google.devtools.build.lib.syntax.Environment;
 import com.google.devtools.build.lib.syntax.EvalException;
 import com.google.devtools.build.lib.syntax.FuncallExpression;
 import com.google.devtools.build.lib.syntax.Mutability;
 import com.google.devtools.build.lib.syntax.StarlarkFunction;
 import com.google.devtools.build.lib.syntax.StarlarkSemantics;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
 
 /**
  * A helper class for calling Starlark functions from Java, where the argument values are supplied
@@ -71,13 +71,13 @@
   public Object call(EventHandler eventHandler, ClassObject ctx, Object... arguments)
       throws EvalException, InterruptedException {
     try (Mutability mutability = Mutability.create("callback %s", callback)) {
-      Environment env =
-          Environment.builder(mutability)
+      StarlarkThread thread =
+          StarlarkThread.builder(mutability)
               .setSemantics(starlarkSemantics)
               .setEventHandler(eventHandler)
               .build();
-      context.storeInThread(env);
-      return callback.call(buildArgumentList(ctx, arguments), null, ast, env);
+      context.storeInThread(thread);
+      return callback.call(buildArgumentList(ctx, arguments), null, ast, thread);
     } catch (ClassCastException | IllegalArgumentException e) {
       throw new EvalException(ast.getLocation(), e.getMessage());
     }
diff --git a/src/main/java/com/google/devtools/build/lib/packages/StructImpl.java b/src/main/java/com/google/devtools/build/lib/packages/StructImpl.java
index 509a834..ab9f88c 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/StructImpl.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/StructImpl.java
@@ -24,7 +24,6 @@
 import com.google.devtools.build.lib.skylarkbuildapi.StructApi;
 import com.google.devtools.build.lib.skylarkinterface.SkylarkPrinter;
 import com.google.devtools.build.lib.syntax.ClassObject;
-import com.google.devtools.build.lib.syntax.Environment;
 import com.google.devtools.build.lib.syntax.EvalException;
 import com.google.devtools.build.lib.syntax.EvalUtils;
 import com.google.devtools.build.lib.syntax.Printer;
@@ -32,6 +31,7 @@
 import com.google.devtools.build.lib.syntax.SkylarkDict;
 import com.google.devtools.build.lib.syntax.SkylarkList;
 import com.google.devtools.build.lib.syntax.SkylarkType;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
 import com.google.protobuf.TextFormat;
 import java.io.Serializable;
 import java.util.ArrayList;
@@ -69,7 +69,7 @@
     for (Map.Entry<String, Object> e : values.entrySet()) {
       builder.put(
           Attribute.getSkylarkName(e.getKey()),
-          SkylarkType.convertToSkylark(e.getValue(), (Environment) null));
+          SkylarkType.convertToSkylark(e.getValue(), (StarlarkThread) null));
     }
     return builder.build();
   }
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 6ffdf5b..230abe9 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
@@ -33,9 +33,6 @@
 import com.google.devtools.build.lib.syntax.BuiltinFunction;
 import com.google.devtools.build.lib.syntax.CallUtils;
 import com.google.devtools.build.lib.syntax.ClassObject;
-import com.google.devtools.build.lib.syntax.Environment;
-import com.google.devtools.build.lib.syntax.Environment.Extension;
-import com.google.devtools.build.lib.syntax.Environment.GlobalFrame;
 import com.google.devtools.build.lib.syntax.EvalException;
 import com.google.devtools.build.lib.syntax.FuncallExpression;
 import com.google.devtools.build.lib.syntax.FunctionSignature;
@@ -45,6 +42,9 @@
 import com.google.devtools.build.lib.syntax.SkylarkUtils;
 import com.google.devtools.build.lib.syntax.SkylarkUtils.Phase;
 import com.google.devtools.build.lib.syntax.StarlarkSemantics;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
+import com.google.devtools.build.lib.syntax.StarlarkThread.Extension;
+import com.google.devtools.build.lib.syntax.StarlarkThread.GlobalFrame;
 import com.google.devtools.build.lib.syntax.ValidationEnvironment;
 import com.google.devtools.build.lib.vfs.Path;
 import com.google.devtools.build.lib.vfs.PathFragment;
@@ -176,15 +176,15 @@
     } else {
       importMap = parentImportMap;
     }
-    Environment workspaceEnv =
-        Environment.builder(mutability)
+    StarlarkThread workspaceThread =
+        StarlarkThread.builder(mutability)
             .setSemantics(starlarkSemantics)
             .setGlobals(BazelLibrary.GLOBALS)
             .setEventHandler(localReporter)
             .setImportedExtensions(importMap)
             .build();
-    SkylarkUtils.setPhase(workspaceEnv, Phase.WORKSPACE);
-    addWorkspaceFunctions(workspaceEnv, localReporter);
+    SkylarkUtils.setPhase(workspaceThread, Phase.WORKSPACE);
+    addWorkspaceFunctions(workspaceThread, localReporter);
 
     // The workspace environment doesn't need the tools repository or the fragment map
     // because executing workspace rules happens before analysis and it doesn't need a
@@ -196,11 +196,11 @@
             /* repoMapping= */ ImmutableMap.of(),
             new SymbolGenerator<>(workspaceFileKey),
             /* analysisRuleLabel= */ null)
-        .storeInThread(workspaceEnv);
+        .storeInThread(workspaceThread);
 
     for (Map.Entry<String, Object> binding : parentVariableBindings.entrySet()) {
       try {
-        workspaceEnv.update(binding.getKey(), binding.getValue());
+        workspaceThread.update(binding.getKey(), binding.getValue());
       } catch (EvalException e) {
         // This should never happen because everything was already evaluated.
         throw new IllegalStateException(e);
@@ -208,9 +208,9 @@
     }
 
     if (!ValidationEnvironment.validateFile(
-            file, workspaceEnv, /*isBuildFile=*/ true, localReporter)
+            file, workspaceThread, /*isBuildFile=*/ true, localReporter)
         || !PackageFactory.checkBuildSyntax(file, localReporter)
-        || !file.exec(workspaceEnv, localReporter)) {
+        || !file.exec(workspaceThread, localReporter)) {
       localReporter.handle(Event.error("Error evaluating WORKSPACE file"));
     }
 
@@ -221,7 +221,7 @@
     // also have a package builder specific to the current part and should be reinitialized for
     // each workspace file.
     ImmutableMap.Builder<String, Object> bindingsBuilder = ImmutableMap.builder();
-    GlobalFrame globals = workspaceEnv.getGlobals();
+    GlobalFrame globals = workspaceThread.getGlobals();
     for (String s : globals.getBindings().keySet()) {
       Object o = globals.get(s);
       if (!isAWorkspaceFunction(s, o)) {
@@ -294,10 +294,10 @@
       final RuleFactory ruleFactory, final String ruleClassName, final boolean allowOverride) {
     return new BuiltinFunction(
         ruleClassName, FunctionSignature.KWARGS, BuiltinFunction.USE_AST_ENV) {
-      public Object invoke(Map<String, Object> kwargs, FuncallExpression ast, Environment env)
+      public Object invoke(Map<String, Object> kwargs, FuncallExpression ast, StarlarkThread thread)
           throws EvalException, InterruptedException {
         try {
-          Package.Builder builder = PackageFactory.getContext(env, ast.getLocation()).pkgBuilder;
+          Package.Builder builder = PackageFactory.getContext(thread, ast.getLocation()).pkgBuilder;
           String externalRepoName = (String) kwargs.get("name");
           if (!allowOverride
               && externalRepoName != null
@@ -312,7 +312,7 @@
           // Add an entry in every repository from @<mainRepoName> to "@" to avoid treating
           // @<mainRepoName> as a separate repository. This will be overridden if the main
           // repository has a repo_mapping entry from <mainRepoName> to something.
-          WorkspaceFactoryHelper.addMainRepoEntry(builder, externalRepoName, env.getSemantics());
+          WorkspaceFactoryHelper.addMainRepoEntry(builder, externalRepoName, thread.getSemantics());
           WorkspaceFactoryHelper.addRepoMappings(
               builder, kwargs, externalRepoName, ast.getLocation());
           RuleClass ruleClass = ruleFactory.getRuleClass(ruleClassName);
@@ -359,23 +359,24 @@
     return map.putAll(ruleFunctions).build();
   }
 
-  private void addWorkspaceFunctions(Environment workspaceEnv, StoredEventHandler localReporter) {
+  private void addWorkspaceFunctions(
+      StarlarkThread workspaceThread, StoredEventHandler localReporter) {
     try {
       for (Map.Entry<String, Object> function : workspaceFunctions.entrySet()) {
-        workspaceEnv.update(function.getKey(), function.getValue());
+        workspaceThread.update(function.getKey(), function.getValue());
       }
       if (installDir != null) {
-        workspaceEnv.update("__embedded_dir__", installDir.getPathString());
+        workspaceThread.update("__embedded_dir__", installDir.getPathString());
       }
       if (workspaceDir != null) {
-        workspaceEnv.update("__workspace_dir__", workspaceDir.getPathString());
+        workspaceThread.update("__workspace_dir__", workspaceDir.getPathString());
       }
-      workspaceEnv.update("DEFAULT_SYSTEM_JAVABASE", getDefaultSystemJavabase());
+      workspaceThread.update("DEFAULT_SYSTEM_JAVABASE", getDefaultSystemJavabase());
 
       for (EnvironmentExtension extension : environmentExtensions) {
-        extension.updateWorkspace(workspaceEnv);
+        extension.updateWorkspace(workspaceThread);
       }
-      workspaceEnv.setThreadLocal(
+      workspaceThread.setThreadLocal(
           PackageFactory.PackageContext.class,
           new PackageFactory.PackageContext(builder, null, localReporter));
     } catch (EvalException e) {
diff --git a/src/main/java/com/google/devtools/build/lib/packages/WorkspaceFileValue.java b/src/main/java/com/google/devtools/build/lib/packages/WorkspaceFileValue.java
index f1a5101..b1bb21d 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/WorkspaceFileValue.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/WorkspaceFileValue.java
@@ -21,7 +21,7 @@
 import com.google.devtools.build.lib.concurrent.BlazeInterners;
 import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
 import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
-import com.google.devtools.build.lib.syntax.Environment.Extension;
+import com.google.devtools.build.lib.syntax.StarlarkThread.Extension;
 import com.google.devtools.build.lib.vfs.PathFragment;
 import com.google.devtools.build.lib.vfs.RootedPath;
 import com.google.devtools.build.skyframe.SkyFunctionName;
@@ -99,8 +99,6 @@
   private final int idx;
   private final RootedPath path;
   private final boolean hasNext;
-  // TODO(dmarting): The bindings bind to "Object" which we should ultimately replace by a super
-  // type in the Environment class (that would ease the serialization of this object).
   private final ImmutableMap<String, Object> bindings;
   private final ImmutableMap<String, Extension> importMap;
   private final ImmutableMap<String, Integer> importToChunkMap;
diff --git a/src/main/java/com/google/devtools/build/lib/packages/WorkspaceGlobals.java b/src/main/java/com/google/devtools/build/lib/packages/WorkspaceGlobals.java
index 816894d..04b9f5b 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/WorkspaceGlobals.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/WorkspaceGlobals.java
@@ -29,12 +29,12 @@
 import com.google.devtools.build.lib.packages.Package.NameConflictException;
 import com.google.devtools.build.lib.packages.RuleFactory.InvalidRuleException;
 import com.google.devtools.build.lib.skylarkbuildapi.WorkspaceGlobalsApi;
-import com.google.devtools.build.lib.syntax.Environment;
 import com.google.devtools.build.lib.syntax.EvalException;
 import com.google.devtools.build.lib.syntax.FuncallExpression;
 import com.google.devtools.build.lib.syntax.Runtime.NoneType;
 import com.google.devtools.build.lib.syntax.SkylarkDict;
 import com.google.devtools.build.lib.syntax.SkylarkList;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
 import com.google.devtools.build.lib.vfs.PathFragment;
 import java.util.List;
 import java.util.Map;
@@ -66,7 +66,7 @@
       String name,
       SkylarkDict<String, Object> managedDirectories,
       FuncallExpression ast,
-      Environment env)
+      StarlarkThread thread)
       throws EvalException, InterruptedException {
     if (allowOverride) {
       if (!isLegalWorkspaceName(name)) {
@@ -76,8 +76,8 @@
       if (errorMessage != null) {
         throw new EvalException(ast.getLocation(), errorMessage);
       }
-      PackageFactory.getContext(env, ast.getLocation()).pkgBuilder.setWorkspaceName(name);
-      Package.Builder builder = PackageFactory.getContext(env, ast.getLocation()).pkgBuilder;
+      PackageFactory.getContext(thread, ast.getLocation()).pkgBuilder.setWorkspaceName(name);
+      Package.Builder builder = PackageFactory.getContext(thread, ast.getLocation()).pkgBuilder;
       RuleClass localRepositoryRuleClass = ruleFactory.getRuleClass("local_repository");
       RuleClass bindRuleClass = ruleFactory.getRuleClass("bind");
       Map<String, Object> kwargs = ImmutableMap.<String, Object>of("name", name, "path", ".");
@@ -91,7 +91,7 @@
       }
       // Add entry in repository map from "@name" --> "@" to avoid issue where bazel
       // treats references to @name as a separate external repo
-      if (env.getSemantics().incompatibleRemapMainRepo()) {
+      if (thread.getSemantics().incompatibleRemapMainRepo()) {
         builder.addRepositoryMappingEntry(
             RepositoryName.MAIN,
             RepositoryName.createFromValidStrippedName(name),
@@ -210,8 +210,8 @@
   }
 
   private static List<String> renamePatterns(
-      List<String> patterns, Package.Builder builder, Environment env) {
-    RepositoryName myName = getRepositoryName((Label) env.getGlobals().getLabel());
+      List<String> patterns, Package.Builder builder, StarlarkThread thread) {
+    RepositoryName myName = getRepositoryName((Label) thread.getGlobals().getLabel());
     Map<RepositoryName, RepositoryName> renaming = builder.getRepositoryMappingFor(myName);
     return patterns.stream()
         .map(patternEntry -> TargetPattern.renameRepository(patternEntry, renaming))
@@ -220,34 +220,34 @@
 
   @Override
   public NoneType registerExecutionPlatforms(
-      SkylarkList<?> platformLabels, Location location, Environment env)
+      SkylarkList<?> platformLabels, Location location, StarlarkThread thread)
       throws EvalException, InterruptedException {
     // Add to the package definition for later.
-    Package.Builder builder = PackageFactory.getContext(env, location).pkgBuilder;
+    Package.Builder builder = PackageFactory.getContext(thread, location).pkgBuilder;
     List<String> patterns = platformLabels.getContents(String.class, "platform_labels");
-    builder.addRegisteredExecutionPlatforms(renamePatterns(patterns, builder, env));
+    builder.addRegisteredExecutionPlatforms(renamePatterns(patterns, builder, thread));
     return NONE;
   }
 
   @Override
   public NoneType registerToolchains(
-      SkylarkList<?> toolchainLabels, Location location, Environment env)
+      SkylarkList<?> toolchainLabels, Location location, StarlarkThread thread)
       throws EvalException, InterruptedException {
     // Add to the package definition for later.
-    Package.Builder builder = PackageFactory.getContext(env, location).pkgBuilder;
+    Package.Builder builder = PackageFactory.getContext(thread, location).pkgBuilder;
     List<String> patterns = toolchainLabels.getContents(String.class, "toolchain_labels");
-    builder.addRegisteredToolchains(renamePatterns(patterns, builder, env));
+    builder.addRegisteredToolchains(renamePatterns(patterns, builder, thread));
     return NONE;
   }
 
   @Override
-  public NoneType bind(String name, Object actual, FuncallExpression ast, Environment env)
+  public NoneType bind(String name, Object actual, FuncallExpression ast, StarlarkThread thread)
       throws EvalException, InterruptedException {
     Label nameLabel;
     try {
       nameLabel = Label.parseAbsolute("//external:" + name, ImmutableMap.of());
       try {
-        Package.Builder builder = PackageFactory.getContext(env, ast.getLocation()).pkgBuilder;
+        Package.Builder builder = PackageFactory.getContext(thread, ast.getLocation()).pkgBuilder;
         RuleClass ruleClass = ruleFactory.getRuleClass("bind");
         WorkspaceFactoryHelper.addBindRule(
             builder,
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidDex2OatInfo.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidDex2OatInfo.java
index db350a0..5e92b20 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidDex2OatInfo.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidDex2OatInfo.java
@@ -19,9 +19,9 @@
 import com.google.devtools.build.lib.packages.NativeInfo;
 import com.google.devtools.build.lib.packages.NativeProvider;
 import com.google.devtools.build.lib.skylarkbuildapi.android.AndroidDex2OatInfoApi;
-import com.google.devtools.build.lib.syntax.Environment;
 import com.google.devtools.build.lib.syntax.FunctionSignature;
 import com.google.devtools.build.lib.syntax.SkylarkType;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
 
 /**
  * Supplies the pregenerate_oat_files_for_tests attribute of type boolean provided by android_device
@@ -45,7 +45,7 @@
       new NativeProvider<AndroidDex2OatInfo>(AndroidDex2OatInfo.class, NAME, SIGNATURE) {
         @Override
         protected AndroidDex2OatInfo createInstanceFromSkylark(
-            Object[] args, Environment env, Location loc) {
+            Object[] args, StarlarkThread thread, Location loc) {
           return new AndroidDex2OatInfo(/*dex2OatEnabled=*/ (Boolean) args[0]);
         }
       };
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidManifestInfo.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidManifestInfo.java
index bc9f7be..ba74796 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidManifestInfo.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidManifestInfo.java
@@ -19,9 +19,9 @@
 import com.google.devtools.build.lib.packages.NativeInfo;
 import com.google.devtools.build.lib.packages.NativeProvider;
 import com.google.devtools.build.lib.skylarkbuildapi.android.AndroidManifestInfoApi;
-import com.google.devtools.build.lib.syntax.Environment;
 import com.google.devtools.build.lib.syntax.FunctionSignature;
 import com.google.devtools.build.lib.syntax.SkylarkType;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
 
 /** A provider of information about this target's manifest. */
 public class AndroidManifestInfo extends NativeInfo implements AndroidManifestInfoApi<Artifact> {
@@ -47,7 +47,7 @@
       new NativeProvider<AndroidManifestInfo>(AndroidManifestInfo.class, NAME, SIGNATURE) {
         @Override
         public AndroidManifestInfo createInstanceFromSkylark(
-            Object[] args, Environment env, Location loc) {
+            Object[] args, StarlarkThread thread, Location loc) {
           // Skylark support code puts positional inputs in the correct order and validates types.
           return of((Artifact) args[0], (String) args[1], (boolean) args[2]);
         }
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidSkylarkData.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidSkylarkData.java
index cc9ea8f..bc6e315 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidSkylarkData.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidSkylarkData.java
@@ -42,11 +42,11 @@
 import com.google.devtools.build.lib.rules.java.ProguardSpecProvider;
 import com.google.devtools.build.lib.skylarkbuildapi.android.AndroidBinaryDataSettingsApi;
 import com.google.devtools.build.lib.skylarkbuildapi.android.AndroidDataProcessingApi;
-import com.google.devtools.build.lib.syntax.Environment;
 import com.google.devtools.build.lib.syntax.EvalException;
 import com.google.devtools.build.lib.syntax.Runtime;
 import com.google.devtools.build.lib.syntax.SkylarkDict;
 import com.google.devtools.build.lib.syntax.SkylarkList;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
 import com.google.devtools.build.lib.vfs.PathFragment;
 import java.util.List;
 import java.util.Objects;
@@ -71,9 +71,9 @@
 
   @Override
   public AndroidAssetsInfo assetsFromDeps(
-      SkylarkList<AndroidAssetsInfo> deps, boolean neverlink, Environment env) {
+      SkylarkList<AndroidAssetsInfo> deps, boolean neverlink, StarlarkThread thread) {
     // We assume this is an analysis-phase thread.
-    Label label = BazelStarlarkContext.from(env).getAnalysisRuleLabel();
+    Label label = BazelStarlarkContext.from(thread).getAnalysisRuleLabel();
     return AssetDependencies.fromProviders(deps, neverlink).toInfo(label);
   }
 
@@ -85,7 +85,7 @@
       boolean neverlink,
       String customPackage,
       Location location,
-      Environment env)
+      StarlarkThread thread)
       throws InterruptedException, EvalException {
     try (SkylarkErrorReporter errorReporter =
         SkylarkErrorReporter.from(ctx.getRuleErrorConsumer(), location)) {
@@ -107,7 +107,7 @@
       Object customPackage,
       boolean exported,
       Location location,
-      Environment env)
+      StarlarkThread thread)
       throws InterruptedException, EvalException {
     String pkg = fromNoneable(customPackage, String.class);
     try (SkylarkErrorReporter errorReporter =
@@ -132,7 +132,7 @@
       SkylarkList<AndroidAssetsInfo> deps,
       boolean neverlink,
       Location location,
-      Environment env)
+      StarlarkThread thread)
       throws EvalException, InterruptedException {
     SkylarkErrorReporter errorReporter =
         SkylarkErrorReporter.from(ctx.getRuleErrorConsumer(), location);
@@ -160,7 +160,7 @@
       boolean neverlink,
       boolean enableDataBinding,
       Location location,
-      Environment env)
+      StarlarkThread thread)
       throws EvalException, InterruptedException {
     SkylarkErrorReporter errorReporter =
         SkylarkErrorReporter.from(ctx.getRuleErrorConsumer(), location);
@@ -187,14 +187,14 @@
       boolean neverlink,
       boolean enableDataBinding,
       Location location,
-      Environment env)
+      StarlarkThread thread)
       throws EvalException, InterruptedException {
     ValidatedAndroidResources validated =
-        mergeRes(ctx, manifest, resources, deps, neverlink, enableDataBinding, location, env);
+        mergeRes(ctx, manifest, resources, deps, neverlink, enableDataBinding, location, thread);
     JavaInfo javaInfo =
         getJavaInfoForRClassJar(validated.getClassJar(), validated.getJavaSourceJar());
     return SkylarkDict.of(
-        /* env = */ null,
+        /* thread = */ null,
         AndroidResourcesInfo.PROVIDER,
         validated.toProvider(),
         JavaInfo.PROVIDER,
@@ -315,7 +315,7 @@
       SkylarkList<ConfiguredTarget> deps,
       SkylarkList<String> noCompressExtensions,
       Location location,
-      Environment env)
+      StarlarkThread thread)
       throws InterruptedException, EvalException {
     SkylarkErrorReporter errorReporter =
         SkylarkErrorReporter.from(ctx.getRuleErrorConsumer(), location);
@@ -361,7 +361,7 @@
               resourceApk.toResourceInfo(ctx.getLabel()),
               resourceApk.toAssetsInfo(ctx.getLabel()),
               resourceApk.toManifestInfo().get()));
-      return SkylarkDict.copyOf(/* env = */ null, builder.build());
+      return SkylarkDict.copyOf(/* thread = */ null, builder.build());
     } catch (RuleErrorException e) {
       throw handleRuleException(errorReporter, e);
     }
@@ -385,7 +385,7 @@
       SkylarkList<String> noCompressExtensions,
       String aaptVersionString,
       Location location,
-      Environment env)
+      StarlarkThread thread)
       throws EvalException {
 
     SkylarkErrorReporter errorReporter =
@@ -417,7 +417,7 @@
    * com.google.devtools.build.lib.rules.android.AndroidSkylarkData.BinaryDataSettings}.
    */
   private BinaryDataSettings defaultBinaryDataSettings(
-      AndroidDataContext ctx, Location location, Environment env) throws EvalException {
+      AndroidDataContext ctx, Location location, StarlarkThread thread) throws EvalException {
     return makeBinarySettings(
         ctx,
         Runtime.NONE,
@@ -426,7 +426,7 @@
         SkylarkList.createImmutable(ImmutableList.of()),
         "auto",
         location,
-        env);
+        thread);
   }
 
   private static class BinaryDataSettings implements AndroidBinaryDataSettingsApi {
@@ -462,7 +462,7 @@
       boolean crunchPng,
       boolean dataBindingEnabled,
       Location location,
-      Environment env)
+      StarlarkThread thread)
       throws InterruptedException, EvalException {
     SkylarkErrorReporter errorReporter =
         SkylarkErrorReporter.from(ctx.getRuleErrorConsumer(), location);
@@ -472,7 +472,7 @@
           fromNoneableOrDefault(
               maybeSettings,
               BinaryDataSettings.class,
-              defaultBinaryDataSettings(ctx, location, env));
+              defaultBinaryDataSettings(ctx, location, thread));
 
       AndroidManifest rawManifest =
           AndroidManifest.from(
@@ -548,11 +548,13 @@
       SkylarkList<ConfiguredTarget> localProguardSpecs,
       SkylarkList<ConfiguredTarget> extraProguardSpecs,
       Location location,
-      Environment env)
+      StarlarkThread thread)
       throws EvalException, InterruptedException {
     BinaryDataSettings settings =
         fromNoneableOrDefault(
-            maybeSettings, BinaryDataSettings.class, defaultBinaryDataSettings(ctx, location, env));
+            maybeSettings,
+            BinaryDataSettings.class,
+            defaultBinaryDataSettings(ctx, location, thread));
 
     if (!settings.shrinkResources) {
       return binaryDataInfo;
@@ -608,7 +610,7 @@
         getJavaInfoForRClassJar(
             resourceApk.getResourceJavaClassJar(), resourceApk.getResourceJavaSrcJar()));
 
-    return SkylarkDict.copyOf(/* env = */ null, builder.build());
+    return SkylarkDict.copyOf(/* thread = */ null, builder.build());
   }
 
   /**
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 fe7fb32..566d1ca 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
@@ -25,8 +25,8 @@
 import com.google.devtools.build.lib.packages.RequiredProviders;
 import com.google.devtools.build.lib.packages.SkylarkProviderIdentifier;
 import com.google.devtools.build.lib.skylarkbuildapi.config.ConfigFeatureFlagProviderApi;
-import com.google.devtools.build.lib.syntax.Environment;
 import com.google.devtools.build.lib.syntax.EvalException;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
 import java.util.Map;
 
 /** Provider for exporting value and valid value predicate of feature flags to consuming targets. */
@@ -66,7 +66,7 @@
 
     @Override
     protected ConfigFeatureFlagProvider createInstanceFromSkylark(
-        Object[] args, Environment env, Location loc) throws EvalException {
+        Object[] args, StarlarkThread thread, Location loc) throws EvalException {
 
       @SuppressWarnings("unchecked")
       Map<String, Object> kwargs = (Map<String, Object>) args[0];
diff --git a/src/main/java/com/google/devtools/build/lib/rules/config/ConfigGlobalLibrary.java b/src/main/java/com/google/devtools/build/lib/rules/config/ConfigGlobalLibrary.java
index aaae4ec..217461f 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/config/ConfigGlobalLibrary.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/config/ConfigGlobalLibrary.java
@@ -24,10 +24,10 @@
 import com.google.devtools.build.lib.skylarkbuildapi.config.ConfigGlobalLibraryApi;
 import com.google.devtools.build.lib.skylarkbuildapi.config.ConfigurationTransitionApi;
 import com.google.devtools.build.lib.syntax.BaseFunction;
-import com.google.devtools.build.lib.syntax.Environment;
 import com.google.devtools.build.lib.syntax.EvalException;
 import com.google.devtools.build.lib.syntax.SkylarkDict;
 import com.google.devtools.build.lib.syntax.StarlarkSemantics;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
@@ -45,15 +45,15 @@
       List<String> inputs,
       List<String> outputs,
       Location location,
-      Environment env)
+      StarlarkThread thread)
       throws EvalException {
-    StarlarkSemantics semantics = env.getSemantics();
+    StarlarkSemantics semantics = thread.getSemantics();
     validateBuildSettingKeys(
         inputs, Settings.INPUTS, location, semantics.experimentalStarlarkConfigTransitions());
     validateBuildSettingKeys(
         outputs, Settings.OUTPUTS, location, semantics.experimentalStarlarkConfigTransitions());
     return StarlarkDefinedConfigTransition.newRegularTransition(
-        implementation, inputs, outputs, semantics, env);
+        implementation, inputs, outputs, semantics, thread);
   }
 
   @Override
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcCompilationOutputs.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcCompilationOutputs.java
index fd44b19..2591a3e 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcCompilationOutputs.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcCompilationOutputs.java
@@ -23,9 +23,9 @@
 import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
 import com.google.devtools.build.lib.events.Location;
 import com.google.devtools.build.lib.skylarkbuildapi.cpp.CcCompilationOutputsApi;
-import com.google.devtools.build.lib.syntax.Environment;
 import com.google.devtools.build.lib.syntax.EvalException;
 import com.google.devtools.build.lib.syntax.SkylarkList;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
 import java.util.LinkedHashSet;
 import java.util.Set;
 
@@ -104,11 +104,11 @@
 
   @Override
   public SkylarkList<Artifact> getSkylarkObjectFiles(
-      boolean usePic, Location location, Environment environment) throws EvalException {
+      boolean usePic, Location location, StarlarkThread thread) throws EvalException {
     CcCommon.checkLocationWhitelisted(
-        environment.getSemantics(),
+        thread.getSemantics(),
         location,
-        ((Label) environment.getGlobals().getLabel()).getPackageIdentifier().toString());
+        ((Label) thread.getGlobals().getLabel()).getPackageIdentifier().toString());
     return SkylarkList.createImmutable(getObjectFiles(usePic));
   }
 
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcInfo.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcInfo.java
index 75dce23..42929aa 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcInfo.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcInfo.java
@@ -22,9 +22,9 @@
 import com.google.devtools.build.lib.packages.BuiltinProvider;
 import com.google.devtools.build.lib.packages.NativeInfo;
 import com.google.devtools.build.lib.skylarkbuildapi.cpp.CcInfoApi;
-import com.google.devtools.build.lib.syntax.Environment;
 import com.google.devtools.build.lib.syntax.EvalException;
 import com.google.devtools.build.lib.syntax.Runtime;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
 import java.util.Collection;
 import javax.annotation.Nullable;
 
@@ -160,7 +160,7 @@
         Object skylarkCcCompilationContext,
         Object skylarkCcLinkingInfo,
         Location location,
-        Environment environment)
+        StarlarkThread thread)
         throws EvalException {
       CcCompilationContext ccCompilationContext =
           nullIfNone(skylarkCcCompilationContext, CcCompilationContext.class);
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLinkingContext.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLinkingContext.java
index 336c78c..c244350 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLinkingContext.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLinkingContext.java
@@ -27,9 +27,9 @@
 import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
 import com.google.devtools.build.lib.packages.SymbolGenerator;
 import com.google.devtools.build.lib.skylarkbuildapi.cpp.CcLinkingContextApi;
-import com.google.devtools.build.lib.syntax.Environment;
 import com.google.devtools.build.lib.syntax.SkylarkList;
 import com.google.devtools.build.lib.syntax.SkylarkNestedSet;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
 import com.google.devtools.build.lib.util.Fingerprint;
 import java.util.Arrays;
 import java.util.Collection;
@@ -262,8 +262,8 @@
   }
 
   @Override
-  public Object getSkylarkLibrariesToLink(Environment environment) {
-    if (environment.getSemantics().incompatibleDepsetForLibrariesToLinkGetter()) {
+  public Object getSkylarkLibrariesToLink(StarlarkThread thread) {
+    if (thread.getSemantics().incompatibleDepsetForLibrariesToLinkGetter()) {
       return SkylarkNestedSet.of(LibraryToLink.class, libraries);
     } else {
       return SkylarkList.createImmutable(libraries.toList());
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcModule.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcModule.java
index 938ee26..5964459 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcModule.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcModule.java
@@ -57,7 +57,6 @@
 import com.google.devtools.build.lib.rules.cpp.Link.LinkingMode;
 import com.google.devtools.build.lib.skylarkbuildapi.cpp.CcInfoApi;
 import com.google.devtools.build.lib.skylarkbuildapi.cpp.CcModuleApi;
-import com.google.devtools.build.lib.syntax.Environment;
 import com.google.devtools.build.lib.syntax.EvalException;
 import com.google.devtools.build.lib.syntax.EvalUtils;
 import com.google.devtools.build.lib.syntax.Runtime;
@@ -67,6 +66,7 @@
 import com.google.devtools.build.lib.syntax.SkylarkList.Tuple;
 import com.google.devtools.build.lib.syntax.SkylarkNestedSet;
 import com.google.devtools.build.lib.syntax.SkylarkType;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
 import com.google.devtools.build.lib.util.FileTypeSet;
 import com.google.devtools.build.lib.util.Pair;
 import com.google.devtools.build.lib.util.StringUtil;
@@ -373,7 +373,7 @@
       Object interfaceLibraryObject,
       boolean alwayslink,
       Location location,
-      Environment environment)
+      StarlarkThread thread)
       throws EvalException, InterruptedException {
     SkylarkActionFactory skylarkActionFactory =
         nullIfNone(actionsObject, SkylarkActionFactory.class);
@@ -579,7 +579,7 @@
       Object userLinkFlagsObject,
       SkylarkList<Artifact> nonCodeInputs,
       Location location,
-      Environment env)
+      StarlarkThread thread)
       throws EvalException {
     @SuppressWarnings("unchecked")
     SkylarkList<LibraryToLink> librariesToLink =
@@ -600,7 +600,7 @@
                 ImmutableList.of(
                     CcLinkingContext.LinkOptions.of(
                         userLinkFlags.getImmutableList(),
-                        BazelStarlarkContext.from(env).getSymbolGenerator()))));
+                        BazelStarlarkContext.from(thread).getSymbolGenerator()))));
       }
       ccLinkingContextBuilder.addNonCodeInputs(
           NestedSetBuilder.wrap(Order.LINK_ORDER, nonCodeInputs));
@@ -1399,7 +1399,7 @@
       boolean disallowDynamicLibraries,
       Object grepIncludes,
       Location location,
-      Environment env)
+      StarlarkThread thread)
       throws InterruptedException, EvalException {
     validateLanguage(location, language);
     SkylarkActionFactory actions = skylarkActionFactoryApi;
@@ -1432,7 +1432,7 @@
                     .getActionConstructionContext()
                     .getConfiguration()
                     .getFragment(CppConfiguration.class),
-                BazelStarlarkContext.from(env).getSymbolGenerator(),
+                BazelStarlarkContext.from(thread).getSymbolGenerator(),
                 TargetUtils.getExecutionInfo(
                     actions.getRuleContext().getRule(),
                     actions.getRuleContext().isAllowTagsPropagation()))
@@ -1529,7 +1529,7 @@
       Artifact grepIncludes,
       SkylarkList<Artifact> headersForClifDoNotUseThisParam,
       Location location,
-      @Nullable Environment environment)
+      @Nullable StarlarkThread thread)
       throws EvalException, InterruptedException {
     SkylarkActionFactory actions = skylarkActionFactoryApi;
     CcToolchainProvider ccToolchainProvider = convertFromNoneable(skylarkCcToolchainProvider, null);
@@ -1628,7 +1628,7 @@
       SkylarkList<Artifact> additionalInputs,
       Object grepIncludes,
       Location location,
-      Environment env)
+      StarlarkThread thread)
       throws InterruptedException, EvalException {
     validateLanguage(location, language);
     validateOutputType(location, outputType);
@@ -1673,7 +1673,7 @@
                 fdoContext,
                 actions.getActionConstructionContext().getConfiguration(),
                 cppConfiguration,
-                BazelStarlarkContext.from(env).getSymbolGenerator(),
+                BazelStarlarkContext.from(thread).getSymbolGenerator(),
                 TargetUtils.getExecutionInfo(
                     actions.getRuleContext().getRule(),
                     actions.getRuleContext().isAllowTagsPropagation()))
diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaInfo.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaInfo.java
index 53d83a7..01d3d3a 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaInfo.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaInfo.java
@@ -38,11 +38,11 @@
 import com.google.devtools.build.lib.skylarkbuildapi.FileApi;
 import com.google.devtools.build.lib.skylarkbuildapi.java.JavaInfoApi;
 import com.google.devtools.build.lib.skylarkinterface.SkylarkValue;
-import com.google.devtools.build.lib.syntax.Environment;
 import com.google.devtools.build.lib.syntax.EvalException;
 import com.google.devtools.build.lib.syntax.Runtime;
 import com.google.devtools.build.lib.syntax.SkylarkList;
 import com.google.devtools.build.lib.syntax.SkylarkNestedSet;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Objects;
@@ -410,7 +410,7 @@
         SkylarkList<?> exports,
         Object jdepsApi,
         Location loc,
-        Environment env)
+        StarlarkThread thread)
         throws EvalException {
       Artifact outputJar = (Artifact) outputJarApi;
       @Nullable Artifact compileJar = nullIfNone(compileJarApi, Artifact.class);
diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaInfoBuildHelper.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaInfoBuildHelper.java
index 30e377e..c8f2c93 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaInfoBuildHelper.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaInfoBuildHelper.java
@@ -39,10 +39,10 @@
 import com.google.devtools.build.lib.events.Location;
 import com.google.devtools.build.lib.rules.java.JavaCompilationArgsProvider.ClasspathType;
 import com.google.devtools.build.lib.shell.ShellUtils;
-import com.google.devtools.build.lib.syntax.Environment;
 import com.google.devtools.build.lib.syntax.EvalException;
 import com.google.devtools.build.lib.syntax.SkylarkList;
 import com.google.devtools.build.lib.syntax.StarlarkSemantics;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
 import com.google.devtools.build.lib.vfs.FileSystemUtils;
 import java.util.ArrayList;
 import java.util.List;
@@ -291,7 +291,7 @@
       Boolean neverlink,
       JavaSemantics javaSemantics,
       Location location,
-      Environment environment)
+      StarlarkThread thread)
       throws EvalException, InterruptedException {
 
     if (sourceJars.isEmpty()
diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaSkylarkCommon.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaSkylarkCommon.java
index f0516d1..893577a 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaSkylarkCommon.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaSkylarkCommon.java
@@ -26,11 +26,11 @@
 import com.google.devtools.build.lib.skylarkbuildapi.ProviderApi;
 import com.google.devtools.build.lib.skylarkbuildapi.java.JavaCommonApi;
 import com.google.devtools.build.lib.skylarkbuildapi.java.JavaToolchainSkylarkApiProviderApi;
-import com.google.devtools.build.lib.syntax.Environment;
 import com.google.devtools.build.lib.syntax.EvalException;
 import com.google.devtools.build.lib.syntax.Runtime;
 import com.google.devtools.build.lib.syntax.SkylarkList;
 import com.google.devtools.build.lib.syntax.StarlarkSemantics;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
 
 /** A module that contains Skylark utilities for Java support. */
 public class JavaSkylarkCommon
@@ -73,7 +73,7 @@
       SkylarkList<Artifact> resources,
       Boolean neverlink,
       Location location,
-      Environment environment)
+      StarlarkThread thread)
       throws EvalException, InterruptedException {
 
     return JavaInfoBuildHelper.getInstance()
@@ -98,7 +98,7 @@
             neverlink,
             javaSemantics,
             location,
-            environment);
+            thread);
   }
 
   @Override
diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/MessageBundleInfo.java b/src/main/java/com/google/devtools/build/lib/rules/java/MessageBundleInfo.java
index 49f4f0c..25e4206 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/java/MessageBundleInfo.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/java/MessageBundleInfo.java
@@ -23,10 +23,10 @@
 import com.google.devtools.build.lib.packages.NativeProvider;
 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.Environment;
 import com.google.devtools.build.lib.syntax.FunctionSignature;
 import com.google.devtools.build.lib.syntax.SkylarkList;
 import com.google.devtools.build.lib.syntax.SkylarkType;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
 import javax.annotation.Nullable;
 
 /** Marks configured targets that are able to supply message bundles to their dependents. */
@@ -50,7 +50,7 @@
         @Override
         @SuppressWarnings("unchecked")
         protected MessageBundleInfo createInstanceFromSkylark(
-            Object[] args, Environment env, Location loc) {
+            Object[] args, StarlarkThread thread, Location loc) {
           return new MessageBundleInfo(ImmutableList.copyOf((SkylarkList<Artifact>) args[0]), loc);
         }
       };
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/AppleSkylarkCommon.java b/src/main/java/com/google/devtools/build/lib/rules/objc/AppleSkylarkCommon.java
index f25fdb3..9a1b874 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/objc/AppleSkylarkCommon.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/AppleSkylarkCommon.java
@@ -46,12 +46,12 @@
 import com.google.devtools.build.lib.skylarkbuildapi.SplitTransitionProviderApi;
 import com.google.devtools.build.lib.skylarkbuildapi.apple.AppleCommonApi;
 import com.google.devtools.build.lib.skylarkinterface.SkylarkValue;
-import com.google.devtools.build.lib.syntax.Environment;
 import com.google.devtools.build.lib.syntax.EvalException;
 import com.google.devtools.build.lib.syntax.Runtime;
 import com.google.devtools.build.lib.syntax.SkylarkDict;
 import com.google.devtools.build.lib.syntax.SkylarkList;
 import com.google.devtools.build.lib.syntax.SkylarkNestedSet;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
 import com.google.devtools.build.lib.vfs.PathFragment;
 import java.util.Map;
 import javax.annotation.Nullable;
@@ -182,8 +182,8 @@
   @Override
   // This method is registered statically for skylark, and never called directly.
   public ObjcProvider newObjcProvider(
-      Boolean usesSwift, SkylarkDict<?, ?> kwargs, Environment environment) throws EvalException {
-    ObjcProvider.Builder resultBuilder = new ObjcProvider.Builder(environment.getSemantics());
+      Boolean usesSwift, SkylarkDict<?, ?> kwargs, StarlarkThread thread) throws EvalException {
+    ObjcProvider.Builder resultBuilder = new ObjcProvider.Builder(thread.getSemantics());
     if (usesSwift) {
       resultBuilder.add(ObjcProvider.FLAG, ObjcProvider.Flag.USES_SWIFT);
     }
@@ -234,7 +234,7 @@
       SkylarkRuleContextApi skylarkRuleContextApi,
       SkylarkList<String> extraLinkopts,
       SkylarkList<? extends FileApi> extraLinkInputs,
-      Environment environment)
+      StarlarkThread thread)
       throws EvalException, InterruptedException {
     SkylarkRuleContext skylarkRuleContext = (SkylarkRuleContext) skylarkRuleContextApi;
     try {
@@ -244,7 +244,7 @@
               ruleContext,
               extraLinkopts.getImmutableList(),
               SkylarkList.castList(extraLinkInputs, Artifact.class, "extra_link_inputs"));
-      return createAppleBinaryOutputSkylarkStruct(appleBinaryOutput, environment);
+      return createAppleBinaryOutputSkylarkStruct(appleBinaryOutput, thread);
     } catch (RuleErrorException | ActionConflictException exception) {
       throw new EvalException(null, exception);
     }
@@ -269,7 +269,7 @@
    * function.
    */
   private StructImpl createAppleBinaryOutputSkylarkStruct(
-      AppleBinaryOutput output, Environment environment) {
+      AppleBinaryOutput output, StarlarkThread thread) {
     Provider constructor =
         new NativeProvider<StructImpl>(StructImpl.class, "apple_binary_output") {};
     // We have to transform the output group dictionary into one that contains SkylarkValues instead
@@ -282,7 +282,7 @@
         ImmutableMap.of(
             "binary_provider", output.getBinaryInfoProvider(),
             "debug_outputs_provider", output.getDebugOutputsProvider(),
-            "output_groups", SkylarkDict.copyOf(environment, outputGroups));
+            "output_groups", SkylarkDict.copyOf(thread, outputGroups));
     return SkylarkInfo.createSchemaless(constructor, fields, Location.BUILTIN);
   }
 }
diff --git a/src/main/java/com/google/devtools/build/lib/rules/repository/ResolvedFileFunction.java b/src/main/java/com/google/devtools/build/lib/rules/repository/ResolvedFileFunction.java
index 56a2baa..f2e2f8f 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/repository/ResolvedFileFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/repository/ResolvedFileFunction.java
@@ -27,6 +27,7 @@
 import com.google.devtools.build.lib.syntax.Mutability;
 import com.google.devtools.build.lib.syntax.ParserInput;
 import com.google.devtools.build.lib.syntax.StarlarkSemantics;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
 import com.google.devtools.build.lib.vfs.FileSystemUtils;
 import com.google.devtools.build.skyframe.SkyFunction;
 import com.google.devtools.build.skyframe.SkyFunctionException;
@@ -71,21 +72,21 @@
                   LabelConstants.EXTERNAL_PACKAGE_IDENTIFIER,
                   "Failed to parse file resolved file " + key.getPath()));
         }
-        com.google.devtools.build.lib.syntax.Environment resolvedEnvironment;
+        StarlarkThread resolvedThread;
         try (Mutability mutability = Mutability.create("resolved file %s", key.getPath())) {
-          resolvedEnvironment =
-              com.google.devtools.build.lib.syntax.Environment.builder(mutability)
+          resolvedThread =
+              StarlarkThread.builder(mutability)
                   .setSemantics(starlarkSemantics)
                   .setGlobals(BazelLibrary.GLOBALS)
                   .build();
-          if (!ast.exec(resolvedEnvironment, env.getListener())) {
+          if (!ast.exec(resolvedThread, env.getListener())) {
             throw new ResolvedFileFunctionException(
                 new BuildFileContainsErrorsException(
                     LabelConstants.EXTERNAL_PACKAGE_IDENTIFIER,
                     "Failed to evaluate resolved file " + key.getPath()));
           }
         }
-        Object resolved = resolvedEnvironment.moduleLookup("resolved");
+        Object resolved = resolvedThread.moduleLookup("resolved");
         if (resolved == null) {
           throw new ResolvedFileFunctionException(
               new BuildFileContainsErrorsException(
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/ASTFileLookupFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/ASTFileLookupFunction.java
index 0197b90..d065bfd 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/ASTFileLookupFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/ASTFileLookupFunction.java
@@ -24,6 +24,7 @@
 import com.google.devtools.build.lib.syntax.Mutability;
 import com.google.devtools.build.lib.syntax.ParserInput;
 import com.google.devtools.build.lib.syntax.StarlarkSemantics;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
 import com.google.devtools.build.lib.vfs.FileSystemUtils;
 import com.google.devtools.build.lib.vfs.Path;
 import com.google.devtools.build.lib.vfs.PathFragment;
@@ -114,8 +115,8 @@
     try {
       long astFileSize = fileValue.getSize();
       try (Mutability mutability = Mutability.create("validate")) {
-        com.google.devtools.build.lib.syntax.Environment validationEnv =
-            ruleClassProvider.createSkylarkRuleClassEnvironment(
+        StarlarkThread thread =
+            ruleClassProvider.createRuleClassStarlarkThread(
                 fileLabel,
                 mutability,
                 starlarkSemantics,
@@ -127,7 +128,7 @@
         byte[] bytes = FileSystemUtils.readWithKnownFileSize(path, astFileSize);
         ParserInput input = ParserInput.create(bytes, path.asFragment());
         file = BuildFileAST.parseWithDigest(input, path.getDigest(), env.getListener());
-        file = file.validate(validationEnv, /*isBuildFile=*/ false, env.getListener());
+        file = file.validate(thread, /*isBuildFile=*/ false, env.getListener());
       }
     } catch (IOException e) {
       throw new ASTLookupFunctionException(new ErrorReadingSkylarkExtensionException(e),
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/PackageFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/PackageFunction.java
index 3945ae8..dbbbf39 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/PackageFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/PackageFunction.java
@@ -57,10 +57,10 @@
 import com.google.devtools.build.lib.skyframe.SkylarkImportLookupFunction.SkylarkImportFailedException;
 import com.google.devtools.build.lib.skyframe.SkylarkImportLookupValue.SkylarkImportLookupKey;
 import com.google.devtools.build.lib.syntax.BuildFileAST;
-import com.google.devtools.build.lib.syntax.Environment.Extension;
 import com.google.devtools.build.lib.syntax.EvalException;
 import com.google.devtools.build.lib.syntax.ParserInput;
 import com.google.devtools.build.lib.syntax.StarlarkSemantics;
+import com.google.devtools.build.lib.syntax.StarlarkThread.Extension;
 import com.google.devtools.build.lib.syntax.Statement;
 import com.google.devtools.build.lib.vfs.FileSystemUtils;
 import com.google.devtools.build.lib.vfs.Path;
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/SkylarkAspectFactory.java b/src/main/java/com/google/devtools/build/lib/skyframe/SkylarkAspectFactory.java
index 7d5fe13..0b4734e 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/SkylarkAspectFactory.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/SkylarkAspectFactory.java
@@ -34,12 +34,12 @@
 import com.google.devtools.build.lib.packages.StructProvider;
 import com.google.devtools.build.lib.packages.Target;
 import com.google.devtools.build.lib.skylarkinterface.SkylarkValue;
-import com.google.devtools.build.lib.syntax.Environment;
 import com.google.devtools.build.lib.syntax.EvalException;
 import com.google.devtools.build.lib.syntax.EvalExceptionWithStackTrace;
 import com.google.devtools.build.lib.syntax.EvalUtils;
 import com.google.devtools.build.lib.syntax.Mutability;
 import com.google.devtools.build.lib.syntax.SkylarkType;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
 import java.util.Map;
 
 /** A factory for aspects that are defined in Skylark. */
@@ -71,8 +71,8 @@
         ruleContext.ruleError(e.getMessage());
         return null;
       }
-      Environment env =
-          Environment.builder(mutability)
+      StarlarkThread thread =
+          StarlarkThread.builder(mutability)
               .setSemantics(analysisEnv.getSkylarkSemantics())
               .setEventHandler(analysisEnv.getEventHandler())
               .build();
@@ -85,7 +85,7 @@
               ruleContext.getRule().getPackage().getRepositoryMapping(),
               ruleContext.getSymbolGenerator(),
               ruleContext.getLabel())
-          .storeInThread(env);
+          .storeInThread(thread);
 
       Object aspectSkylarkObject;
       try {
@@ -96,7 +96,7 @@
                     /*args=*/ ImmutableList.of(ctadBase.getConfiguredTarget(), skylarkRuleContext),
                     /* kwargs= */ ImmutableMap.of(),
                     /*ast=*/ null,
-                    env);
+                    thread);
 
         // If allowing analysis failures, targets should be created somewhat normally, and errors
         // will be propagated via a hook elsewhere as AnalysisFailureInfo.
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/SkylarkImportLookupFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/SkylarkImportLookupFunction.java
index f726ccc..db9176f 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/SkylarkImportLookupFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/SkylarkImportLookupFunction.java
@@ -45,12 +45,13 @@
 import com.google.devtools.build.lib.skyframe.SkylarkImportLookupValue.SkylarkImportLookupKey;
 import com.google.devtools.build.lib.syntax.AssignmentStatement;
 import com.google.devtools.build.lib.syntax.BuildFileAST;
-import com.google.devtools.build.lib.syntax.Environment.Extension;
 import com.google.devtools.build.lib.syntax.EvalException;
 import com.google.devtools.build.lib.syntax.Identifier;
 import com.google.devtools.build.lib.syntax.LoadStatement;
 import com.google.devtools.build.lib.syntax.Mutability;
 import com.google.devtools.build.lib.syntax.StarlarkSemantics;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
+import com.google.devtools.build.lib.syntax.StarlarkThread.Extension;
 import com.google.devtools.build.lib.syntax.Statement;
 import com.google.devtools.build.lib.vfs.PathFragment;
 import com.google.devtools.build.lib.vfs.RootedPath;
@@ -591,8 +592,8 @@
     // the transitive closure of the accessible AST nodes.
     PathFragment extensionFile = extensionLabel.toPathFragment();
     try (Mutability mutability = Mutability.create("importing %s", extensionFile)) {
-      com.google.devtools.build.lib.syntax.Environment extensionEnv =
-          ruleClassProvider.createSkylarkRuleClassEnvironment(
+      StarlarkThread extensionThread =
+          ruleClassProvider.createRuleClassStarlarkThread(
               extensionLabel,
               mutability,
               starlarkSemantics,
@@ -600,8 +601,8 @@
               ast.getContentHashCode(),
               importMap,
               repositoryMapping);
-      extensionEnv.setupOverride("native", packageFactory.getNativeModule(inWorkspace));
-      execAndExport(ast, extensionLabel, eventHandler, extensionEnv);
+      extensionThread.setupOverride("native", packageFactory.getNativeModule(inWorkspace));
+      execAndExport(ast, extensionLabel, eventHandler, extensionThread);
 
       Event.replayEventsOn(env.getListener(), eventHandler.getEvents());
       for (Postable post : eventHandler.getPosts()) {
@@ -610,24 +611,29 @@
       if (eventHandler.hasErrors()) {
         throw SkylarkImportFailedException.errors(extensionFile);
       }
-      return new Extension(extensionEnv);
+      return new Extension(extensionThread);
     }
   }
 
-  public static void execAndExport(BuildFileAST ast, Label extensionLabel,
+  public static void execAndExport(
+      BuildFileAST ast,
+      Label extensionLabel,
       EventHandler eventHandler,
-      com.google.devtools.build.lib.syntax.Environment extensionEnv) throws InterruptedException {
-    ast.replayLexerEvents(extensionEnv, eventHandler);
+      StarlarkThread extensionThread)
+      throws InterruptedException {
+    ast.replayLexerEvents(extensionThread, eventHandler);
     ImmutableList<Statement> statements = ast.getStatements();
     for (Statement statement : statements) {
-      ast.execTopLevelStatement(statement, extensionEnv, eventHandler);
-      possiblyExport(statement, extensionLabel, eventHandler, extensionEnv);
+      ast.execTopLevelStatement(statement, extensionThread, eventHandler);
+      possiblyExport(statement, extensionLabel, eventHandler, extensionThread);
     }
   }
 
-  private static void possiblyExport(Statement statement, Label extensionLabel,
+  private static void possiblyExport(
+      Statement statement,
+      Label extensionLabel,
       EventHandler eventHandler,
-      com.google.devtools.build.lib.syntax.Environment extensionEnv) {
+      StarlarkThread extensionThread) {
     if (!(statement instanceof AssignmentStatement)) {
       return;
     }
@@ -635,7 +641,7 @@
     ImmutableSet<Identifier> boundIdentifiers =
         Identifier.boundIdentifiers(assignmentStatement.getLHS());
     for (Identifier ident : boundIdentifiers) {
-      Object lookup = extensionEnv.moduleLookup(ident.getName());
+      Object lookup = extensionThread.moduleLookup(ident.getName());
       if (lookup instanceof SkylarkExportable) {
         try {
           SkylarkExportable exportable = (SkylarkExportable) lookup;
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/SkylarkImportLookupValue.java b/src/main/java/com/google/devtools/build/lib/skyframe/SkylarkImportLookupValue.java
index 6ffc7e2..763d848 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/SkylarkImportLookupValue.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/SkylarkImportLookupValue.java
@@ -20,7 +20,7 @@
 import com.google.devtools.build.lib.concurrent.BlazeInterners;
 import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
 import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
-import com.google.devtools.build.lib.syntax.Environment.Extension;
+import com.google.devtools.build.lib.syntax.StarlarkThread.Extension;
 import com.google.devtools.build.lib.vfs.RootedPath;
 import com.google.devtools.build.skyframe.SkyFunctionName;
 import com.google.devtools.build.skyframe.SkyKey;
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/WorkspaceFileFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/WorkspaceFileFunction.java
index e4ffeca..74716bd 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/WorkspaceFileFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/WorkspaceFileFunction.java
@@ -26,9 +26,9 @@
 import com.google.devtools.build.lib.packages.WorkspaceFileValue;
 import com.google.devtools.build.lib.packages.WorkspaceFileValue.WorkspaceFileKey;
 import com.google.devtools.build.lib.syntax.BuildFileAST;
-import com.google.devtools.build.lib.syntax.Environment.Extension;
 import com.google.devtools.build.lib.syntax.Mutability;
 import com.google.devtools.build.lib.syntax.StarlarkSemantics;
+import com.google.devtools.build.lib.syntax.StarlarkThread.Extension;
 import com.google.devtools.build.lib.vfs.RootedPath;
 import com.google.devtools.build.skyframe.SkyFunction;
 import com.google.devtools.build.skyframe.SkyFunctionException;
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/serialization/testutils/TestUtils.java b/src/main/java/com/google/devtools/build/lib/skyframe/serialization/testutils/TestUtils.java
index 46a95bf..6bccc28 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/serialization/testutils/TestUtils.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/serialization/testutils/TestUtils.java
@@ -24,8 +24,8 @@
 import com.google.devtools.build.lib.skyframe.serialization.ObjectCodecs;
 import com.google.devtools.build.lib.skyframe.serialization.SerializationContext;
 import com.google.devtools.build.lib.skyframe.serialization.SerializationException;
-import com.google.devtools.build.lib.syntax.Environment.GlobalFrame;
 import com.google.devtools.build.lib.syntax.Mutability;
+import com.google.devtools.build.lib.syntax.StarlarkThread.GlobalFrame;
 import com.google.protobuf.ByteString;
 import com.google.protobuf.CodedInputStream;
 import com.google.protobuf.CodedOutputStream;
diff --git a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/SkylarkActionFactoryApi.java b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/SkylarkActionFactoryApi.java
index 69b2323..03c1186 100644
--- a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/SkylarkActionFactoryApi.java
+++ b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/SkylarkActionFactoryApi.java
@@ -21,12 +21,12 @@
 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.Environment;
 import com.google.devtools.build.lib.syntax.EvalException;
 import com.google.devtools.build.lib.syntax.SkylarkDict;
 import com.google.devtools.build.lib.syntax.SkylarkList;
 import com.google.devtools.build.lib.syntax.SkylarkNestedSet;
 import com.google.devtools.build.lib.syntax.StarlarkSemantics;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
 
 /** Module providing functions to create actions. */
 @SkylarkModule(
@@ -585,9 +585,8 @@
       throws EvalException;
 
   @SkylarkCallable(
-    name = "args",
-    doc = "Returns an Args object that can be used to build memory-efficient command lines.",
-    useEnvironment = true
-  )
-  public CommandLineArgsApi args(Environment env);
+      name = "args",
+      doc = "Returns an Args object that can be used to build memory-efficient command lines.",
+      useStarlarkThread = true)
+  public CommandLineArgsApi args(StarlarkThread thread);
 }
diff --git a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/SkylarkAttrApi.java b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/SkylarkAttrApi.java
index ba97cd3..9b69185 100644
--- a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/SkylarkAttrApi.java
+++ b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/SkylarkAttrApi.java
@@ -21,13 +21,13 @@
 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.Environment;
 import com.google.devtools.build.lib.syntax.EvalException;
 import com.google.devtools.build.lib.syntax.FuncallExpression;
 import com.google.devtools.build.lib.syntax.SkylarkDict;
 import com.google.devtools.build.lib.syntax.SkylarkList;
 import com.google.devtools.build.lib.syntax.StarlarkFunction;
 import com.google.devtools.build.lib.syntax.StarlarkSemantics.FlagIdentifier;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
 
 /**
  * The "attr" module of the Build API.
@@ -181,14 +181,14 @@
             positional = false)
       },
       useAst = true,
-      useEnvironment = true)
+      useStarlarkThread = true)
   Descriptor intAttribute(
       Integer defaultInt,
       String doc,
       Boolean mandatory,
       SkylarkList<?> values,
       FuncallExpression ast,
-      Environment env)
+      StarlarkThread thread)
       throws EvalException;
 
   @SkylarkCallable(
@@ -228,14 +228,14 @@
             positional = false)
       },
       useAst = true,
-      useEnvironment = true)
+      useStarlarkThread = true)
   public Descriptor stringAttribute(
       String defaultString,
       String doc,
       Boolean mandatory,
       SkylarkList<?> values,
       FuncallExpression ast,
-      Environment env)
+      StarlarkThread thread)
       throws EvalException;
 
   @SkylarkCallable(
@@ -360,7 +360,7 @@
             doc = ASPECTS_ARG_DOC),
       },
       useAst = true,
-      useEnvironment = true)
+      useStarlarkThread = true)
   public Descriptor labelAttribute(
       Object defaultO,
       String doc,
@@ -374,7 +374,7 @@
       Object cfg,
       SkylarkList<?> aspects,
       FuncallExpression ast,
-      Environment env)
+      StarlarkThread thread)
       throws EvalException;
 
   @SkylarkCallable(
@@ -418,7 +418,7 @@
             positional = false)
       },
       useAst = true,
-      useEnvironment = true)
+      useStarlarkThread = true)
   public Descriptor stringListAttribute(
       Boolean mandatory,
       Boolean nonEmpty,
@@ -426,7 +426,7 @@
       SkylarkList<?> defaultList,
       String doc,
       FuncallExpression ast,
-      Environment env)
+      StarlarkThread thread)
       throws EvalException;
 
   @SkylarkCallable(
@@ -470,7 +470,7 @@
             positional = false)
       },
       useAst = true,
-      useEnvironment = true)
+      useStarlarkThread = true)
   public Descriptor intListAttribute(
       Boolean mandatory,
       Boolean nonEmpty,
@@ -478,7 +478,7 @@
       SkylarkList<?> defaultList,
       String doc,
       FuncallExpression ast,
-      Environment env)
+      StarlarkThread thread)
       throws EvalException;
 
   @SkylarkCallable(
@@ -578,7 +578,7 @@
             doc = ASPECTS_ARG_DOC),
       },
       useAst = true,
-      useEnvironment = true)
+      useStarlarkThread = true)
   public Descriptor labelListAttribute(
       Boolean allowEmpty,
       Object defaultList,
@@ -592,7 +592,7 @@
       Object cfg,
       SkylarkList<?> aspects,
       FuncallExpression ast,
-      Environment env)
+      StarlarkThread thread)
       throws EvalException;
 
   @SkylarkCallable(
@@ -694,7 +694,7 @@
             doc = ASPECTS_ARG_DOC)
       },
       useAst = true,
-      useEnvironment = true)
+      useStarlarkThread = true)
   public Descriptor labelKeyedStringDictAttribute(
       Boolean allowEmpty,
       Object defaultList,
@@ -708,7 +708,7 @@
       Object cfg,
       SkylarkList<?> aspects,
       FuncallExpression ast,
-      Environment env)
+      StarlarkThread thread)
       throws EvalException;
 
   @SkylarkCallable(
@@ -741,9 +741,9 @@
             doc = MANDATORY_DOC)
       },
       useAst = true,
-      useEnvironment = true)
+      useStarlarkThread = true)
   public Descriptor boolAttribute(
-      Boolean defaultO, String doc, Boolean mandatory, FuncallExpression ast, Environment env)
+      Boolean defaultO, String doc, Boolean mandatory, FuncallExpression ast, StarlarkThread thread)
       throws EvalException;
 
   @SkylarkCallable(
@@ -779,9 +779,9 @@
             doc = MANDATORY_DOC)
       },
       useAst = true,
-      useEnvironment = true)
+      useStarlarkThread = true)
   public Descriptor outputAttribute(
-      Object defaultO, String doc, Boolean mandatory, FuncallExpression ast, Environment env)
+      Object defaultO, String doc, Boolean mandatory, FuncallExpression ast, StarlarkThread thread)
       throws EvalException;
 
   @SkylarkCallable(
@@ -830,7 +830,7 @@
             doc = NON_EMPTY_DOC)
       },
       useAst = true,
-      useEnvironment = true)
+      useStarlarkThread = true)
   public Descriptor outputListAttribute(
       Boolean allowEmpty,
       Object defaultList,
@@ -838,7 +838,7 @@
       Boolean mandatory,
       Boolean nonEmpty,
       FuncallExpression ast,
-      Environment env)
+      StarlarkThread thread)
       throws EvalException;
 
   @SkylarkCallable(
@@ -886,7 +886,7 @@
             doc = NON_EMPTY_DOC)
       },
       useAst = true,
-      useEnvironment = true)
+      useStarlarkThread = true)
   public Descriptor stringDictAttribute(
       Boolean allowEmpty,
       SkylarkDict<?, ?> defaultO,
@@ -894,7 +894,7 @@
       Boolean mandatory,
       Boolean nonEmpty,
       FuncallExpression ast,
-      Environment env)
+      StarlarkThread thread)
       throws EvalException;
 
   @SkylarkCallable(
@@ -942,7 +942,7 @@
             doc = NON_EMPTY_DOC)
       },
       useAst = true,
-      useEnvironment = true)
+      useStarlarkThread = true)
   public Descriptor stringListDictAttribute(
       Boolean allowEmpty,
       SkylarkDict<?, ?> defaultO,
@@ -950,7 +950,7 @@
       Boolean mandatory,
       Boolean nonEmpty,
       FuncallExpression ast,
-      Environment env)
+      StarlarkThread thread)
       throws EvalException;
 
   @SkylarkCallable(
@@ -983,9 +983,9 @@
       },
       disableWithFlag = FlagIdentifier.INCOMPATIBLE_NO_ATTR_LICENSE,
       useAst = true,
-      useEnvironment = true)
+      useStarlarkThread = true)
   public Descriptor licenseAttribute(
-      Object defaultO, String doc, Boolean mandatory, FuncallExpression ast, Environment env)
+      Object defaultO, String doc, Boolean mandatory, FuncallExpression ast, StarlarkThread thread)
       throws EvalException;
 
   /** An attribute descriptor. */
diff --git a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/SkylarkBuildApiGlobals.java b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/SkylarkBuildApiGlobals.java
index 97f035c..68dc749 100644
--- a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/SkylarkBuildApiGlobals.java
+++ b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/SkylarkBuildApiGlobals.java
@@ -18,8 +18,8 @@
 import com.google.devtools.build.lib.skylarkinterface.Param;
 import com.google.devtools.build.lib.skylarkinterface.SkylarkCallable;
 import com.google.devtools.build.lib.skylarkinterface.SkylarkGlobalLibrary;
-import com.google.devtools.build.lib.syntax.Environment;
 import com.google.devtools.build.lib.syntax.EvalException;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
 
 /**
  * A collection of global skylark build API functions that belong in the global namespace.
@@ -56,7 +56,7 @@
             doc = "The name of the value to obtain from the configuration fragment."),
       },
       useLocation = true,
-      useEnvironment = true)
+      useStarlarkThread = true)
   public LateBoundDefaultApi configurationField(
-      String fragment, String name, Location loc, Environment env) throws EvalException;
+      String fragment, String name, Location loc, StarlarkThread thread) throws EvalException;
 }
diff --git a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/SkylarkNativeModuleApi.java b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/SkylarkNativeModuleApi.java
index 2660411..c5e6091 100644
--- a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/SkylarkNativeModuleApi.java
+++ b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/SkylarkNativeModuleApi.java
@@ -19,12 +19,12 @@
 import com.google.devtools.build.lib.skylarkinterface.SkylarkCallable;
 import com.google.devtools.build.lib.skylarkinterface.SkylarkModule;
 import com.google.devtools.build.lib.skylarkinterface.SkylarkModuleCategory;
-import com.google.devtools.build.lib.syntax.Environment;
 import com.google.devtools.build.lib.syntax.EvalException;
 import com.google.devtools.build.lib.syntax.FuncallExpression;
 import com.google.devtools.build.lib.syntax.Runtime;
 import com.google.devtools.build.lib.syntax.SkylarkDict;
 import com.google.devtools.build.lib.syntax.SkylarkList;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
 
 /**
  * Interface for a module with native rule and package helper functions.
@@ -87,14 +87,14 @@
                     + " excluded).")
       },
       useAst = true,
-      useEnvironment = true)
+      useStarlarkThread = true)
   public SkylarkList<?> glob(
       SkylarkList<?> include,
       SkylarkList<?> exclude,
       Integer excludeDirectories,
       Object allowEmpty,
       FuncallExpression ast,
-      Environment env)
+      StarlarkThread thread)
       throws EvalException, InterruptedException;
 
   @SkylarkCallable(
@@ -114,8 +114,8 @@
             doc = "The name of the target.")
       },
       useAst = true,
-      useEnvironment = true)
-  public Object existingRule(String name, FuncallExpression ast, Environment env)
+      useStarlarkThread = true)
+  public Object existingRule(String name, FuncallExpression ast, StarlarkThread thread)
       throws EvalException, InterruptedException;
 
   @SkylarkCallable(
@@ -128,26 +128,48 @@
               + "<p><i>Note: If possible, avoid using this function. It makes BUILD files brittle "
               + "and order-dependent.</i>",
       useAst = true,
-      useEnvironment = true)
+      useStarlarkThread = true)
   public SkylarkDict<String, SkylarkDict<String, Object>> existingRules(
-      FuncallExpression ast, Environment env) throws EvalException, InterruptedException;
+      FuncallExpression ast, StarlarkThread thread) throws EvalException, InterruptedException;
 
-  @SkylarkCallable(name = "package_group",
-      doc = "This function defines a set of packages and assigns a label to the group. "
-          + "The label can be referenced in <code>visibility</code> attributes.",
+  @SkylarkCallable(
+      name = "package_group",
+      doc =
+          "This function defines a set of packages and assigns a label to the group. "
+              + "The label can be referenced in <code>visibility</code> attributes.",
       parameters = {
-      @Param(name = "name", type = String.class, named = true, positional = false,
-          doc = "The unique name for this rule."),
-      @Param(name = "packages", type = SkylarkList.class, generic1 = String.class,
-          defaultValue = "[]", named = true, positional = false,
-          doc = "A complete enumeration of packages in this group."),
-      @Param(name = "includes", type = SkylarkList.class, generic1 = String.class,
-          defaultValue = "[]", named = true, positional = false,
-          doc = "Other package groups that are included in this one.")},
-      useAst = true, useEnvironment = true)
-  public Runtime.NoneType packageGroup(String name, SkylarkList<?> packages,
+        @Param(
+            name = "name",
+            type = String.class,
+            named = true,
+            positional = false,
+            doc = "The unique name for this rule."),
+        @Param(
+            name = "packages",
+            type = SkylarkList.class,
+            generic1 = String.class,
+            defaultValue = "[]",
+            named = true,
+            positional = false,
+            doc = "A complete enumeration of packages in this group."),
+        @Param(
+            name = "includes",
+            type = SkylarkList.class,
+            generic1 = String.class,
+            defaultValue = "[]",
+            named = true,
+            positional = false,
+            doc = "Other package groups that are included in this one.")
+      },
+      useAst = true,
+      useStarlarkThread = true)
+  public Runtime.NoneType packageGroup(
+      String name,
+      SkylarkList<?> packages,
       SkylarkList<?> includes,
-      FuncallExpression ast, Environment env) throws EvalException;
+      FuncallExpression ast,
+      StarlarkThread thread)
+      throws EvalException;
 
   @SkylarkCallable(
       name = "exports_files",
@@ -182,44 +204,40 @@
             doc = "Licenses to be specified.")
       },
       useAst = true,
-      useEnvironment = true)
+      useStarlarkThread = true)
   public Runtime.NoneType exportsFiles(
       SkylarkList<?> srcs,
       Object visibility,
       Object licenses,
       FuncallExpression ast,
-      Environment env)
+      StarlarkThread thread)
       throws EvalException;
 
   @SkylarkCallable(
-    name = "package_name",
-    doc =
-        "The name of the package being evaluated. "
-            + "For example, in the BUILD file <code>some/package/BUILD</code>, its value "
-            + "will be <code>some/package</code>. "
-            + "If the BUILD file calls a function defined in a .bzl file, "
-            + "<code>package_name()</code> will match the caller BUILD file package. "
-            + "This function is equivalent to the deprecated variable <code>PACKAGE_NAME</code>.",
-    parameters = {},
-    useAst = true,
-    useEnvironment = true
-  )
-  public String packageName(FuncallExpression ast, Environment env)
-      throws EvalException;
+      name = "package_name",
+      doc =
+          "The name of the package being evaluated. "
+              + "For example, in the BUILD file <code>some/package/BUILD</code>, its value "
+              + "will be <code>some/package</code>. "
+              + "If the BUILD file calls a function defined in a .bzl file, "
+              + "<code>package_name()</code> will match the caller BUILD file package. "
+              + "This function is equivalent to the deprecated variable <code>PACKAGE_NAME</code>.",
+      parameters = {},
+      useAst = true,
+      useStarlarkThread = true)
+  public String packageName(FuncallExpression ast, StarlarkThread thread) throws EvalException;
 
   @SkylarkCallable(
-    name = "repository_name",
-    doc =
-        "The name of the repository the rule or build extension is called from. "
-            + "For example, in packages that are called into existence by the WORKSPACE stanza "
-            + "<code>local_repository(name='local', path=...)</code> it will be set to "
-            + "<code>@local</code>. In packages in the main repository, it will be set to "
-            + "<code>@</code>. This function is equivalent to the deprecated variable "
-            + "<code>REPOSITORY_NAME</code>.",
-    parameters = {},
-    useLocation = true,
-    useEnvironment = true
-  )
-  public String repositoryName(Location location, Environment env)
-      throws EvalException;
+      name = "repository_name",
+      doc =
+          "The name of the repository the rule or build extension is called from. "
+              + "For example, in packages that are called into existence by the WORKSPACE stanza "
+              + "<code>local_repository(name='local', path=...)</code> it will be set to "
+              + "<code>@local</code>. In packages in the main repository, it will be set to "
+              + "<code>@</code>. This function is equivalent to the deprecated variable "
+              + "<code>REPOSITORY_NAME</code>.",
+      parameters = {},
+      useLocation = true,
+      useStarlarkThread = true)
+  public String repositoryName(Location location, StarlarkThread thread) throws EvalException;
 }
diff --git a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/SkylarkRuleContextApi.java b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/SkylarkRuleContextApi.java
index 8b2ee22..cff87a7 100644
--- a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/SkylarkRuleContextApi.java
+++ b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/SkylarkRuleContextApi.java
@@ -24,7 +24,6 @@
 import com.google.devtools.build.lib.skylarkinterface.SkylarkModuleCategory;
 import com.google.devtools.build.lib.skylarkinterface.SkylarkValue;
 import com.google.devtools.build.lib.syntax.ClassObject;
-import com.google.devtools.build.lib.syntax.Environment;
 import com.google.devtools.build.lib.syntax.EvalException;
 import com.google.devtools.build.lib.syntax.Runtime;
 import com.google.devtools.build.lib.syntax.Runtime.UnboundMarker;
@@ -34,6 +33,7 @@
 import com.google.devtools.build.lib.syntax.SkylarkList.Tuple;
 import com.google.devtools.build.lib.syntax.SkylarkNestedSet;
 import com.google.devtools.build.lib.syntax.StarlarkSemantics.FlagIdentifier;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
 import java.util.Map;
 import javax.annotation.Nullable;
 
@@ -690,7 +690,7 @@
       },
       allowReturnNones = true,
       useLocation = true,
-      useEnvironment = true)
+      useStarlarkThread = true)
   public Runtime.NoneType action(
       SkylarkList outputs,
       Object inputs,
@@ -705,155 +705,144 @@
       Object executionRequirementsUnchecked,
       Object inputManifestsUnchecked,
       Location loc,
-      Environment env)
+      StarlarkThread thread)
       throws EvalException;
 
   @SkylarkCallable(
-    name = "expand_location",
-    doc =
-        "Expands all <code>$(location ...)</code> templates in the given string by replacing "
-            + "<code>$(location //x)</code> with the path of the output file of target //x. "
-            + "Expansion only works for labels that point to direct dependencies of this rule or "
-            + "that are explicitly listed in the optional argument <code>targets</code>. "
-            + "<br/><br/>"
-            + "<code>$(location ...)</code> will cause an error if the referenced target has "
-            + "multiple outputs. In this case, please use <code>$(locations ...)</code> since it "
-            + "produces a space-separated list of output paths. It can be safely used for a "
-            + "single output file, too."
-            + "<br/><br/>"
-            + "This function is useful to let the user specify a command in a BUILD file (like "
-            + "for <code>genrule</code>). In other cases, it is often better to manipulate labels "
-            + "directly.",
-    parameters = {
-      @Param(name = "input", type = String.class, doc = "String to be expanded."),
-      @Param(
-        name = "targets",
-        type = SkylarkList.class,
-        generic1 = TransitiveInfoCollectionApi.class,
-        defaultValue = "[]",
-        named = true,
-        doc = "List of targets for additional lookup information."
-      ),
-    },
-    allowReturnNones = true,
-    useLocation = true,
-    useEnvironment = true
-  )
-  public String expandLocation(String input, SkylarkList targets, Location loc, Environment env)
-      throws EvalException;
+      name = "expand_location",
+      doc =
+          "Expands all <code>$(location ...)</code> templates in the given string by replacing "
+              + "<code>$(location //x)</code> with the path of the output file of target //x. "
+              + "Expansion only works for labels that point to direct dependencies of this rule or "
+              + "that are explicitly listed in the optional argument <code>targets</code>. "
+              + "<br/><br/>"
+              //
+              + "<code>$(location ...)</code> will cause an error if the referenced target has "
+              + "multiple outputs. In this case, please use <code>$(locations ...)</code> since it "
+              + "produces a space-separated list of output paths. It can be safely used for a "
+              + "single output file, too."
+              + "<br/><br/>"
+              //
+              + "This function is useful to let the user specify a command in a BUILD file (like"
+              + " for <code>genrule</code>). In other cases, it is often better to manipulate"
+              + " labels directly.",
+      parameters = {
+        @Param(name = "input", type = String.class, doc = "String to be expanded."),
+        @Param(
+            name = "targets",
+            type = SkylarkList.class,
+            generic1 = TransitiveInfoCollectionApi.class,
+            defaultValue = "[]",
+            named = true,
+            doc = "List of targets for additional lookup information."),
+      },
+      allowReturnNones = true,
+      useLocation = true,
+      useStarlarkThread = true)
+  public String expandLocation(
+      String input, SkylarkList targets, Location loc, StarlarkThread thread) throws EvalException;
 
   @SkylarkCallable(
-    name = "file_action",
-    doc =
-        "DEPRECATED. Use <a href =\"actions.html#write\">ctx.actions.write</a> instead. <br>"
-            + "Creates a file write action.",
-    parameters = {
-      @Param(name = "output", type = FileApi.class, named = true, doc = "The output file."),
-      @Param(
-        name = "content",
-        type = String.class,
-        named = true,
-        doc = "The contents of the file."
-      ),
-      @Param(
-        name = "executable",
-        type = Boolean.class,
-        defaultValue = "False",
-        named = true,
-        doc = "Whether the output file should be executable (default is False)."
-      )
-    },
-    allowReturnNones = true,
-    useLocation = true,
-    useEnvironment = true
-  )
+      name = "file_action",
+      doc =
+          "DEPRECATED. Use <a href =\"actions.html#write\">ctx.actions.write</a> instead. <br>"
+              + "Creates a file write action.",
+      parameters = {
+        @Param(name = "output", type = FileApi.class, named = true, doc = "The output file."),
+        @Param(
+            name = "content",
+            type = String.class,
+            named = true,
+            doc = "The contents of the file."),
+        @Param(
+            name = "executable",
+            type = Boolean.class,
+            defaultValue = "False",
+            named = true,
+            doc = "Whether the output file should be executable (default is False).")
+      },
+      allowReturnNones = true,
+      useLocation = true,
+      useStarlarkThread = true)
   public Runtime.NoneType fileAction(
-      FileApi output, String content, Boolean executable, Location loc, Environment env)
+      FileApi output, String content, Boolean executable, Location loc, StarlarkThread thread)
       throws EvalException;
 
   @SkylarkCallable(
-    name = "empty_action",
-    doc =
-        "DEPRECATED. Use <a href=\"actions.html#do_nothing\">ctx.actions.do_nothing</a> instead."
-            + " <br>"
-            + "Creates an empty action that neither executes a command nor produces any "
-            + "output, but that is useful for inserting 'extra actions'.",
-    parameters = {
-      @Param(
-        name = "mnemonic",
-        type = String.class,
-        named = true,
-        positional = false,
-        doc = "A one-word description of the action, e.g. CppCompile or GoLink."
-      ),
-      @Param(
-        name = "inputs",
-        allowedTypes = {
-          @ParamType(type = SkylarkList.class),
-          @ParamType(type = SkylarkNestedSet.class),
-        },
-        generic1 = FileApi.class,
-        named = true,
-        positional = false,
-        defaultValue = "[]",
-        doc = "List of the input files of the action."
-      ),
-    },
-    allowReturnNones = true,
-    useLocation = true,
-    useEnvironment = true
-  )
-  public Runtime.NoneType emptyAction(String mnemonic, Object inputs, Location loc, Environment env)
-      throws EvalException;
+      name = "empty_action",
+      doc =
+          "DEPRECATED. Use <a href=\"actions.html#do_nothing\">ctx.actions.do_nothing</a> instead."
+              + " <br>"
+              + "Creates an empty action that neither executes a command nor produces any "
+              + "output, but that is useful for inserting 'extra actions'.",
+      parameters = {
+        @Param(
+            name = "mnemonic",
+            type = String.class,
+            named = true,
+            positional = false,
+            doc = "A one-word description of the action, e.g. CppCompile or GoLink."),
+        @Param(
+            name = "inputs",
+            allowedTypes = {
+              @ParamType(type = SkylarkList.class),
+              @ParamType(type = SkylarkNestedSet.class),
+            },
+            generic1 = FileApi.class,
+            named = true,
+            positional = false,
+            defaultValue = "[]",
+            doc = "List of the input files of the action."),
+      },
+      allowReturnNones = true,
+      useLocation = true,
+      useStarlarkThread = true)
+  public Runtime.NoneType emptyAction(
+      String mnemonic, Object inputs, Location loc, StarlarkThread thread) throws EvalException;
 
   @SkylarkCallable(
-    name = "template_action",
-    doc =
-        "DEPRECATED. "
-            + "Use <a href=\"actions.html#expand_template\">ctx.actions.expand_template()</a> "
-            + "instead. <br>Creates a template expansion action.",
-    parameters = {
-      @Param(
-        name = "template",
-        type = FileApi.class,
-        named = true,
-        positional = false,
-        doc = "The template file, which is a UTF-8 encoded text file."
-      ),
-      @Param(
-        name = "output",
-        type = FileApi.class,
-        named = true,
-        positional = false,
-        doc = "The output file, which is a UTF-8 encoded text file."
-      ),
-      @Param(
-        name = "substitutions",
-        type = SkylarkDict.class,
-        named = true,
-        positional = false,
-        doc = "Substitutions to make when expanding the template."
-      ),
-      @Param(
-        name = "executable",
-        type = Boolean.class,
-        defaultValue = "False",
-        named = true,
-        positional = false,
-        doc = "Whether the output file should be executable (default is False)."
-      )
-    },
-    allowReturnNones = true,
-    useLocation = true,
-    useEnvironment = true
-  )
+      name = "template_action",
+      doc =
+          "DEPRECATED. "
+              + "Use <a href=\"actions.html#expand_template\">ctx.actions.expand_template()</a> "
+              + "instead. <br>Creates a template expansion action.",
+      parameters = {
+        @Param(
+            name = "template",
+            type = FileApi.class,
+            named = true,
+            positional = false,
+            doc = "The template file, which is a UTF-8 encoded text file."),
+        @Param(
+            name = "output",
+            type = FileApi.class,
+            named = true,
+            positional = false,
+            doc = "The output file, which is a UTF-8 encoded text file."),
+        @Param(
+            name = "substitutions",
+            type = SkylarkDict.class,
+            named = true,
+            positional = false,
+            doc = "Substitutions to make when expanding the template."),
+        @Param(
+            name = "executable",
+            type = Boolean.class,
+            defaultValue = "False",
+            named = true,
+            positional = false,
+            doc = "Whether the output file should be executable (default is False).")
+      },
+      allowReturnNones = true,
+      useLocation = true,
+      useStarlarkThread = true)
   public Runtime.NoneType templateAction(
       FileApi template,
       FileApi output,
       SkylarkDict<?, ?> substitutionsUnchecked,
       Boolean executable,
       Location loc,
-      Environment env)
+      StarlarkThread thread)
       throws EvalException;
 
   @SkylarkCallable(
@@ -994,7 +983,7 @@
                     + "for useful keys."),
       },
       useLocation = true,
-      useEnvironment = true)
+      useStarlarkThread = true)
   public Tuple<Object> resolveCommand(
       String command,
       Object attributeUnchecked,
@@ -1004,7 +993,7 @@
       SkylarkDict<?, ?> labelDictUnchecked,
       SkylarkDict<?, ?> executionRequirementsUnchecked,
       Location loc,
-      Environment env)
+      StarlarkThread thread)
       throws EvalException;
 
   @SkylarkCallable(
@@ -1027,6 +1016,6 @@
             doc = "List of tools (list of targets)."),
       },
       useLocation = false,
-      useEnvironment = false)
+      useStarlarkThread = false)
   public Tuple<Object> resolveTools(SkylarkList tools) throws EvalException;
 }
diff --git a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/SkylarkRuleFunctionsApi.java b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/SkylarkRuleFunctionsApi.java
index 96d4571..b2c9b5d 100644
--- a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/SkylarkRuleFunctionsApi.java
+++ b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/SkylarkRuleFunctionsApi.java
@@ -23,7 +23,6 @@
 import com.google.devtools.build.lib.skylarkinterface.SkylarkConstructor;
 import com.google.devtools.build.lib.skylarkinterface.SkylarkGlobalLibrary;
 import com.google.devtools.build.lib.syntax.BaseFunction;
-import com.google.devtools.build.lib.syntax.Environment;
 import com.google.devtools.build.lib.syntax.EvalException;
 import com.google.devtools.build.lib.syntax.FuncallExpression;
 import com.google.devtools.build.lib.syntax.Runtime.NoneType;
@@ -32,6 +31,7 @@
 import com.google.devtools.build.lib.syntax.SkylarkList;
 import com.google.devtools.build.lib.syntax.StarlarkFunction;
 import com.google.devtools.build.lib.syntax.StarlarkSemantics.FlagIdentifier;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
 
 /**
  * Interface for a global Skylark library containing rule-related helper and registration functions.
@@ -341,7 +341,7 @@
                     + "apply to its own configuration before analysis.")
       },
       useAst = true,
-      useEnvironment = true)
+      useStarlarkThread = true)
   public BaseFunction rule(
       StarlarkFunction implementation,
       Boolean test,
@@ -361,7 +361,7 @@
       Object buildSetting,
       Object cfg,
       FuncallExpression ast,
-      Environment env)
+      StarlarkThread thread)
       throws EvalException;
 
   @SkylarkCallable(
@@ -499,7 +499,7 @@
                     + "will propagate through `alpha`, `beta`, and `charlie`. If False, then the "
                     + "aspect will propagate only to `alpha`. </p><p>False by default.</p>")
       },
-      useEnvironment = true,
+      useStarlarkThread = true,
       useAst = true)
   public SkylarkAspectApi aspect(
       StarlarkFunction implementation,
@@ -513,7 +513,7 @@
       String doc,
       Boolean applyToGeneratingRules,
       FuncallExpression ast,
-      Environment env)
+      StarlarkThread thread)
       throws EvalException;
 
   @SkylarkCallable(
@@ -545,9 +545,9 @@
                     + "Label() call appears.")
       },
       useLocation = true,
-      useEnvironment = true)
+      useStarlarkThread = true)
   @SkylarkConstructor(objectType = Label.class)
   public Label label(
-      String labelString, Boolean relativeToCallerRepository, Location loc, Environment env)
+      String labelString, Boolean relativeToCallerRepository, Location loc, StarlarkThread thread)
       throws EvalException;
 }
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 e6f2456..0ea61a7 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
@@ -19,12 +19,12 @@
 import com.google.devtools.build.lib.skylarkinterface.Param;
 import com.google.devtools.build.lib.skylarkinterface.SkylarkCallable;
 import com.google.devtools.build.lib.skylarkinterface.SkylarkGlobalLibrary;
-import com.google.devtools.build.lib.syntax.Environment;
 import com.google.devtools.build.lib.syntax.EvalException;
 import com.google.devtools.build.lib.syntax.FuncallExpression;
 import com.google.devtools.build.lib.syntax.Runtime.NoneType;
 import com.google.devtools.build.lib.syntax.SkylarkDict;
 import com.google.devtools.build.lib.syntax.SkylarkList;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
 
 /** A collection of global skylark build API functions that apply to WORKSPACE files. */
 @SkylarkGlobalLibrary
@@ -80,12 +80,12 @@
                     + " them (or their parent directories) in the .bazelignore file."),
       },
       useAst = true,
-      useEnvironment = true)
+      useStarlarkThread = true)
   NoneType workspace(
       String name,
       SkylarkDict<String, Object> managedDirectories,
       FuncallExpression ast,
-      Environment env)
+      StarlarkThread thread)
       throws EvalException, InterruptedException;
 
   @SkylarkCallable(
@@ -99,9 +99,9 @@
               generic1 = String.class,
               doc = "The labels of the platforms to register."),
       useLocation = true,
-      useEnvironment = true)
+      useStarlarkThread = true)
   NoneType registerExecutionPlatforms(
-      SkylarkList<?> platformLabels, Location location, Environment env)
+      SkylarkList<?> platformLabels, Location location, StarlarkThread thread)
       throws EvalException, InterruptedException;
 
   @SkylarkCallable(
@@ -117,8 +117,9 @@
               generic1 = String.class,
               doc = "The labels of the toolchains to register."),
       useLocation = true,
-      useEnvironment = true)
-  NoneType registerToolchains(SkylarkList<?> toolchainLabels, Location location, Environment env)
+      useStarlarkThread = true)
+  NoneType registerToolchains(
+      SkylarkList<?> toolchainLabels, Location location, StarlarkThread thread)
       throws EvalException, InterruptedException;
 
   @SkylarkCallable(
@@ -146,7 +147,7 @@
             doc = "The real label to be aliased")
       },
       useAst = true,
-      useEnvironment = true)
-  NoneType bind(String name, Object actual, FuncallExpression ast, Environment env)
+      useStarlarkThread = true)
+  NoneType bind(String name, Object actual, FuncallExpression ast, StarlarkThread thread)
       throws EvalException, InterruptedException;
 }
diff --git a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/android/AndroidDataProcessingApi.java b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/android/AndroidDataProcessingApi.java
index 3d67e3d..392c9ed 100644
--- a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/android/AndroidDataProcessingApi.java
+++ b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/android/AndroidDataProcessingApi.java
@@ -22,11 +22,11 @@
 import com.google.devtools.build.lib.skylarkinterface.Param;
 import com.google.devtools.build.lib.skylarkinterface.SkylarkCallable;
 import com.google.devtools.build.lib.skylarkinterface.SkylarkModule;
-import com.google.devtools.build.lib.syntax.Environment;
 import com.google.devtools.build.lib.syntax.EvalException;
 import com.google.devtools.build.lib.syntax.SkylarkDict;
 import com.google.devtools.build.lib.syntax.SkylarkList;
 import com.google.devtools.build.lib.syntax.StarlarkSemantics.FlagIdentifier;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
 
 /** Skylark-visible methods for working with Android data (manifests, resources, and assets). */
 @SkylarkModule(
@@ -70,14 +70,14 @@
                 "Defaults to False. If true, assets will not be exposed to targets that depend on"
                     + " them.")
       },
-      useEnvironment = true,
+      useStarlarkThread = true,
       doc =
           "Creates an AndroidAssetsInfoApi from this target's asset dependencies, ignoring local"
               + " assets. No processing will be done. This method is deprecated and exposed only"
               + " for backwards-compatibility with existing behavior.",
       documented = false)
   AndroidAssetsInfoT assetsFromDeps(
-      SkylarkList<AndroidAssetsInfoT> deps, boolean neverlink, Environment env);
+      SkylarkList<AndroidAssetsInfoT> deps, boolean neverlink, StarlarkThread thread);
 
   @SkylarkCallable(
       name = "resources_from_deps",
@@ -122,7 +122,7 @@
             doc = "The Android application package to stamp the manifest with."),
       },
       useLocation = true,
-      useEnvironment = true,
+      useStarlarkThread = true,
       doc =
           "Creates an AndroidResourcesInfoApi from this target's resource dependencies, ignoring"
               + " local resources. Only processing of deps will be done. This method is deprecated"
@@ -137,7 +137,7 @@
       boolean neverlink,
       String customPackage,
       Location location,
-      Environment env)
+      StarlarkThread thread)
       throws InterruptedException, EvalException;
 
   @SkylarkCallable(
@@ -181,7 +181,7 @@
                     + " inherited."),
       },
       useLocation = true,
-      useEnvironment = true,
+      useStarlarkThread = true,
       doc = "Stamps a manifest with package information.",
       documented = false)
   AndroidManifestInfoT stampAndroidManifest(
@@ -190,7 +190,7 @@
       Object customPackage,
       boolean exported,
       Location location,
-      Environment env)
+      StarlarkThread thread)
       throws InterruptedException, EvalException;
 
   @SkylarkCallable(
@@ -244,7 +244,7 @@
                     + " targets that depend on this one.")
       },
       useLocation = true,
-      useEnvironment = true,
+      useStarlarkThread = true,
       doc =
           "Merges this target's assets together with assets inherited from dependencies. Note that,"
               + " by default, actions for validating the merge are created but may not be called."
@@ -258,7 +258,7 @@
       SkylarkList<AndroidAssetsInfoT> deps,
       boolean neverlink,
       Location location,
-      Environment env)
+      StarlarkThread thread)
       throws EvalException, InterruptedException;
 
   @SkylarkCallable(
@@ -316,7 +316,7 @@
                     + " resources."),
       },
       useLocation = true,
-      useEnvironment = true,
+      useStarlarkThread = true,
       doc =
           "Merges this target's resources together with resources inherited from dependencies."
               + " Returns a dict of provider type to actual info, with elements for"
@@ -336,7 +336,7 @@
       boolean neverlink,
       boolean enableDataBinding,
       Location location,
-      Environment env)
+      StarlarkThread thread)
       throws EvalException, InterruptedException;
 
   @SkylarkCallable(
@@ -394,7 +394,7 @@
                     + " resources."),
       },
       useLocation = true,
-      useEnvironment = true,
+      useStarlarkThread = true,
       doc =
           "Merges this target's resources together with resources inherited from dependencies."
               + " Returns a dict of provider type to actual info, with elements for"
@@ -413,7 +413,7 @@
       boolean neverlink,
       boolean enableDataBinding,
       Location location,
-      Environment env)
+      StarlarkThread thread)
       throws EvalException, InterruptedException;
 
   @SkylarkCallable(
@@ -635,7 +635,7 @@
             doc = "A list of file extensions to leave uncompressed in the resource apk.")
       },
       useLocation = true,
-      useEnvironment = true,
+      useStarlarkThread = true,
       doc =
           "Processes resources, assets, and manifests for android_local_test and returns a dict"
               + " from provider type to the appropriate provider.",
@@ -652,7 +652,7 @@
       SkylarkList<TransitiveInfoCollectionT> deps,
       SkylarkList<String> noCompressExtensions,
       Location location,
-      Environment env)
+      StarlarkThread thread)
       throws InterruptedException, EvalException;
 
   @SkylarkCallable(
@@ -716,7 +716,7 @@
                     + " supported."),
       },
       useLocation = true,
-      useEnvironment = true,
+      useStarlarkThread = true,
       doc =
           "Returns a wrapper object containing various settings shared across multiple methods for"
               + " processing binary data.",
@@ -729,7 +729,7 @@
       SkylarkList<String> noCompressExtensions,
       String aaptVersionString,
       Location location,
-      Environment env)
+      StarlarkThread thread)
       throws EvalException;
 
   @SkylarkCallable(
@@ -849,7 +849,7 @@
                     + " resources."),
       },
       useLocation = true,
-      useEnvironment = true,
+      useStarlarkThread = true,
       doc =
           "Processes resources, assets, and manifests for android_binary and returns the"
               + " appropriate providers.",
@@ -868,7 +868,7 @@
       boolean crunchPng,
       boolean dataBindingEnabled,
       Location location,
-      Environment env)
+      StarlarkThread thread)
       throws InterruptedException, EvalException;
 
   @SkylarkCallable(
@@ -940,7 +940,7 @@
                     + " is controlled by Java configuration.")
       },
       useLocation = true,
-      useEnvironment = true,
+      useStarlarkThread = true,
       doc =
           "Possibly shrinks the data APK by removing resources that were marked as unused during"
               + " proguarding.",
@@ -955,7 +955,7 @@
       SkylarkList<TransitiveInfoCollectionT> localProguardSpecs,
       SkylarkList<TransitiveInfoCollectionT> extraProguardSpecs,
       Location location,
-      Environment env)
+      StarlarkThread thread)
       throws EvalException, InterruptedException;
 
   @SkylarkCallable(
diff --git a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/apple/AppleCommonApi.java b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/apple/AppleCommonApi.java
index b5d9a23..b84d8dd 100644
--- a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/apple/AppleCommonApi.java
+++ b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/apple/AppleCommonApi.java
@@ -25,11 +25,11 @@
 import com.google.devtools.build.lib.skylarkinterface.Param;
 import com.google.devtools.build.lib.skylarkinterface.SkylarkCallable;
 import com.google.devtools.build.lib.skylarkinterface.SkylarkModule;
-import com.google.devtools.build.lib.syntax.Environment;
 import com.google.devtools.build.lib.syntax.EvalException;
 import com.google.devtools.build.lib.syntax.SkylarkDict;
 import com.google.devtools.build.lib.syntax.SkylarkList;
 import com.google.devtools.build.lib.syntax.SkylarkNestedSet;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
 
 /** Interface for a module with useful functions for creating apple-related rule implementations. */
 @SkylarkModule(
@@ -296,10 +296,10 @@
               type = SkylarkDict.class,
               defaultValue = "{}",
               doc = "Dictionary of arguments."),
-      useEnvironment = true)
+      useStarlarkThread = true)
   // This method is registered statically for skylark, and never called directly.
   public ObjcProviderApi<?> newObjcProvider(
-      Boolean usesSwift, SkylarkDict<?, ?> kwargs, Environment environment) throws EvalException;
+      Boolean usesSwift, SkylarkDict<?, ?> kwargs, StarlarkThread thread) throws EvalException;
 
   @SkylarkCallable(
     name = "new_dynamic_framework_provider",
@@ -388,13 +388,13 @@
             defaultValue = "[]",
             doc = "Extra files to pass to the linker action."),
       },
-      useEnvironment = true)
+      useStarlarkThread = true)
   // TODO(b/70937317): Iterate on, improve, and solidify this API.
   public StructApi linkMultiArchBinary(
       SkylarkRuleContextApi skylarkRuleContext,
       SkylarkList<String> extraLinkopts,
       SkylarkList<? extends FileApi> extraLinkInputs,
-      Environment environment)
+      StarlarkThread thread)
       throws EvalException, InterruptedException;
 
   @SkylarkCallable(
diff --git a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/config/ConfigGlobalLibraryApi.java b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/config/ConfigGlobalLibraryApi.java
index 990839b..b863227 100644
--- a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/config/ConfigGlobalLibraryApi.java
+++ b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/config/ConfigGlobalLibraryApi.java
@@ -20,11 +20,11 @@
 import com.google.devtools.build.lib.skylarkinterface.SkylarkConstructor;
 import com.google.devtools.build.lib.skylarkinterface.SkylarkGlobalLibrary;
 import com.google.devtools.build.lib.syntax.BaseFunction;
-import com.google.devtools.build.lib.syntax.Environment;
 import com.google.devtools.build.lib.syntax.EvalException;
 import com.google.devtools.build.lib.syntax.SkylarkDict;
 import com.google.devtools.build.lib.syntax.SkylarkList;
 import com.google.devtools.build.lib.syntax.StarlarkSemantics;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
 import java.util.List;
 
 /**
@@ -87,14 +87,14 @@
                     + "a superset of the key set of the dictionary returned by this transition."),
       },
       useLocation = true,
-      useEnvironment = true)
+      useStarlarkThread = true)
   @SkylarkConstructor(objectType = ConfigurationTransitionApi.class)
   ConfigurationTransitionApi transition(
       BaseFunction implementation,
       List<String> inputs,
       List<String> outputs,
       Location location,
-      Environment env)
+      StarlarkThread thread)
       throws EvalException;
 
   @SkylarkCallable(
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 8a2df2d..04d4149 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
@@ -22,12 +22,12 @@
 import com.google.devtools.build.lib.skylarkinterface.ParamType;
 import com.google.devtools.build.lib.skylarkinterface.SkylarkCallable;
 import com.google.devtools.build.lib.skylarkinterface.SkylarkModule;
-import com.google.devtools.build.lib.syntax.Environment;
 import com.google.devtools.build.lib.syntax.EvalException;
 import com.google.devtools.build.lib.syntax.Runtime.NoneType;
 import com.google.devtools.build.lib.syntax.SkylarkList;
 import com.google.devtools.build.lib.syntax.SkylarkList.Tuple;
 import com.google.devtools.build.lib.syntax.SkylarkNestedSet;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
 
 /** Utilites related to C++ support. */
 @SkylarkModule(
@@ -62,7 +62,7 @@
   @SkylarkCallable(
       name = "compile",
       doc = "Should be used for C++ compilation.",
-      useEnvironment = true,
+      useStarlarkThread = true,
       useLocation = true,
       parameters = {
         @Param(
@@ -228,13 +228,13 @@
       boolean disallowPicOutputs,
       boolean disallowNopicOutputs,
       Location location,
-      Environment environment)
+      StarlarkThread thread)
       throws EvalException, InterruptedException;
 
   @SkylarkCallable(
       name = "link",
       doc = "Should be used for C++ transitive linking.",
-      useEnvironment = true,
+      useStarlarkThread = true,
       useLocation = true,
       parameters = {
         @Param(
@@ -337,7 +337,7 @@
       boolean linkDepsStatically,
       SkylarkList<FileT> additionalInputs,
       Location location,
-      Environment env)
+      StarlarkThread thread)
       throws InterruptedException, EvalException;
 
   @SkylarkCallable(
diff --git a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/cpp/CcCompilationOutputsApi.java b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/cpp/CcCompilationOutputsApi.java
index 69cdab2..508980d 100644
--- a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/cpp/CcCompilationOutputsApi.java
+++ b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/cpp/CcCompilationOutputsApi.java
@@ -20,9 +20,9 @@
 import com.google.devtools.build.lib.skylarkinterface.SkylarkCallable;
 import com.google.devtools.build.lib.skylarkinterface.SkylarkModule;
 import com.google.devtools.build.lib.skylarkinterface.SkylarkModuleCategory;
-import com.google.devtools.build.lib.syntax.Environment;
 import com.google.devtools.build.lib.syntax.EvalException;
 import com.google.devtools.build.lib.syntax.SkylarkList;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
 
 /** Interface for a structured representation of the compilation outputs of a C++ rule. */
 @SkylarkModule(
@@ -36,14 +36,14 @@
   @SkylarkCallable(
       name = "object_files",
       doc = "Do not use. Use eiher 'objects' or 'pic_objects'.",
-      useEnvironment = true,
+      useStarlarkThread = true,
       useLocation = true,
       parameters = {
         @Param(name = "use_pic", doc = "use_pic", positional = false, named = true),
       })
   @Deprecated
-  SkylarkList<FileT> getSkylarkObjectFiles(
-      boolean usePic, Location location, Environment environment) throws EvalException;
+  SkylarkList<FileT> getSkylarkObjectFiles(boolean usePic, Location location, StarlarkThread thread)
+      throws EvalException;
 
   @SkylarkCallable(name = "objects", documented = false, useLocation = true, structField = true)
   SkylarkList<FileT> getSkylarkObjects(Location location) throws EvalException;
diff --git a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/cpp/CcInfoApi.java b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/cpp/CcInfoApi.java
index ea001ca..17c1180 100644
--- a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/cpp/CcInfoApi.java
+++ b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/cpp/CcInfoApi.java
@@ -23,9 +23,9 @@
 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.syntax.Environment;
 import com.google.devtools.build.lib.syntax.EvalException;
 import com.google.devtools.build.lib.syntax.Runtime.NoneType;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
 
 /** Wrapper for every C++ compilation and linking provider. */
 @SkylarkModule(
@@ -64,7 +64,7 @@
         name = NAME,
         doc = "The <code>CcInfo</code> constructor.",
         useLocation = true,
-        useEnvironment = true,
+        useStarlarkThread = true,
         parameters = {
           @Param(
               name = "compilation_context",
@@ -92,10 +92,7 @@
         selfCall = true)
     @SkylarkConstructor(objectType = CcInfoApi.class, receiverNameForDoc = NAME)
     CcInfoApi createInfo(
-        Object ccCompilationContext,
-        Object ccLinkingInfo,
-        Location location,
-        Environment environment)
+        Object ccCompilationContext, Object ccLinkingInfo, Location location, StarlarkThread thread)
         throws EvalException;
   }
 }
diff --git a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/cpp/CcLinkingContextApi.java b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/cpp/CcLinkingContextApi.java
index 34671f4..0973a49 100644
--- a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/cpp/CcLinkingContextApi.java
+++ b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/cpp/CcLinkingContextApi.java
@@ -18,9 +18,9 @@
 import com.google.devtools.build.lib.skylarkinterface.SkylarkCallable;
 import com.google.devtools.build.lib.skylarkinterface.SkylarkModule;
 import com.google.devtools.build.lib.skylarkinterface.SkylarkModuleCategory;
-import com.google.devtools.build.lib.syntax.Environment;
 import com.google.devtools.build.lib.syntax.SkylarkList;
 import com.google.devtools.build.lib.syntax.SkylarkNestedSet;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
 
 /** Wrapper for every C++ linking provider. */
 @SkylarkModule(
@@ -42,8 +42,8 @@
           "Returns the depset of <code>LibraryToLink</code>. May return a list but this is"
               + "deprecated. See #8118.",
       structField = true,
-      useEnvironment = true)
-  Object getSkylarkLibrariesToLink(Environment environment);
+      useStarlarkThread = true)
+  Object getSkylarkLibrariesToLink(StarlarkThread thread);
 
   @SkylarkCallable(
       name = "additional_inputs",
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 ffd1ca4..af29935 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
@@ -23,13 +23,13 @@
 import com.google.devtools.build.lib.skylarkinterface.ParamType;
 import com.google.devtools.build.lib.skylarkinterface.SkylarkCallable;
 import com.google.devtools.build.lib.skylarkinterface.SkylarkModule;
-import com.google.devtools.build.lib.syntax.Environment;
 import com.google.devtools.build.lib.syntax.EvalException;
 import com.google.devtools.build.lib.syntax.Runtime.NoneType;
 import com.google.devtools.build.lib.syntax.SkylarkDict;
 import com.google.devtools.build.lib.syntax.SkylarkList;
 import com.google.devtools.build.lib.syntax.SkylarkList.Tuple;
 import com.google.devtools.build.lib.syntax.SkylarkNestedSet;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
 
 /** Utilites related to C++ support. */
 @SkylarkModule(
@@ -525,7 +525,7 @@
       name = "create_library_to_link",
       doc = "Creates <code>LibraryToLink</code>",
       useLocation = true,
-      useEnvironment = true,
+      useStarlarkThread = true,
       parameters = {
         @Param(
             name = "actions",
@@ -596,14 +596,14 @@
       Object interfaceLibrary,
       boolean alwayslink,
       Location location,
-      Environment environment)
+      StarlarkThread thread)
       throws EvalException, InterruptedException;
 
   @SkylarkCallable(
       name = "create_linking_context",
       doc = "Creates a <code>LinkingContext</code>.",
       useLocation = true,
-      useEnvironment = true,
+      useStarlarkThread = true,
       parameters = {
         @Param(
             name = "libraries_to_link",
@@ -634,7 +634,7 @@
       Object userLinkFlagsObject,
       SkylarkList<FileT> nonCodeInputs,
       Location location,
-      Environment env)
+      StarlarkThread thread)
       throws EvalException, InterruptedException;
 
   @SkylarkCallable(
@@ -925,7 +925,7 @@
               + " order to be linked later by a top level rule that does transitive linking to"
               + " create an executable or dynamic library.",
       useLocation = true,
-      useEnvironment = true,
+      useStarlarkThread = true,
       parameters = {
         @Param(
             name = "actions",
@@ -1037,6 +1037,6 @@
       boolean disallowDynamicLibraries,
       Object grepIncludes,
       Location location,
-      Environment env)
+      StarlarkThread thread)
       throws InterruptedException, EvalException;
 }
diff --git a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/java/JavaCommonApi.java b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/java/JavaCommonApi.java
index 046c2b6..ed96f50 100644
--- a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/java/JavaCommonApi.java
+++ b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/java/JavaCommonApi.java
@@ -26,11 +26,11 @@
 import com.google.devtools.build.lib.skylarkinterface.ParamType;
 import com.google.devtools.build.lib.skylarkinterface.SkylarkCallable;
 import com.google.devtools.build.lib.skylarkinterface.SkylarkModule;
-import com.google.devtools.build.lib.syntax.Environment;
 import com.google.devtools.build.lib.syntax.EvalException;
 import com.google.devtools.build.lib.syntax.SkylarkList;
 import com.google.devtools.build.lib.syntax.StarlarkSemantics;
 import com.google.devtools.build.lib.syntax.StarlarkSemantics.FlagIdentifier;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
 
 /** Utilities for Java compilation support in Skylark. */
 @SkylarkModule(name = "java_common", doc = "Utilities for Java compilation support in Starlark.")
@@ -200,7 +200,7 @@
             defaultValue = "False")
       },
       useLocation = true,
-      useEnvironment = true)
+      useStarlarkThread = true)
   public JavaInfoT createJavaCompileAction(
       SkylarkRuleContextT skylarkRuleContext,
       SkylarkList<FileT> sourceJars,
@@ -221,7 +221,7 @@
       SkylarkList<FileT> resources,
       Boolean neverlink,
       Location loc,
-      Environment environment)
+      StarlarkThread thread)
       throws EvalException, InterruptedException;
 
   @SkylarkCallable(
diff --git a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/java/JavaInfoApi.java b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/java/JavaInfoApi.java
index c874007..fb19f44 100644
--- a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/java/JavaInfoApi.java
+++ b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/java/JavaInfoApi.java
@@ -25,10 +25,10 @@
 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.syntax.Environment;
 import com.google.devtools.build.lib.syntax.EvalException;
 import com.google.devtools.build.lib.syntax.SkylarkList;
 import com.google.devtools.build.lib.syntax.SkylarkNestedSet;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
 
 /** Info object encapsulating all information by java rules. */
 @SkylarkModule(
@@ -160,85 +160,86 @@
   public interface JavaInfoProviderApi extends ProviderApi {
 
     @SkylarkCallable(
-      name = "JavaInfo",
-      doc = "The <code>JavaInfo</code> constructor.",
-      parameters = {
-        @Param(
-            name = "output_jar",
-            type = FileApi.class,
-            named = true,
-            doc =
-                "The jar that was created as a result of a compilation "
-                    + "(e.g. javac, scalac, etc)."),
-        @Param(
-            name = "compile_jar",
-            type = FileApi.class,
-            named = true,
-            noneable = true,
-            defaultValue = "None",
-            doc =
-                "A jar that is added as the compile-time dependency in lieu of "
-                    + "<code>output_jar</code>. Typically this is the ijar produced by "
-                    + "<code><a class=\"anchor\" href=\"java_common.html#run_ijar\">"
-                    + "run_ijar</a></code>. "
-                    + "If you cannot use ijar, consider instead using the output of "
-                    + "<code><a class=\"anchor\" href=\"java_common.html#stamp_jar\">"
-                    + "stamp_ijar</a></code>. If you do not wish to use either, "
-                    + "you can simply pass <code>output_jar</code>."),
-        @Param(
-            name = "source_jar",
-            type = FileApi.class,
-            named = true,
-            noneable = true,
-            defaultValue = "None",
-            doc =
-                "The source jar that was used to create the output jar. "
-                    + "Use <code><a class=\"anchor\" href=\"java_common.html#pack_sources\">"
-                    + "pack_sources</a></code> to produce this source jar."),
-        @Param(
-            name = "neverlink",
-            type = Boolean.class,
-            named = true,
-            defaultValue = "False",
-            doc = "If true only use this library for compilation and not at runtime."),
-        @Param(
-            name = "deps",
-            type = SkylarkList.class,
-            generic1 = JavaInfoApi.class,
-            named = true,
-            defaultValue = "[]",
-            doc = "Compile time dependencies that were used to create the output jar."),
-        @Param(
-            name = "runtime_deps",
-            type = SkylarkList.class,
-            generic1 = JavaInfoApi.class,
-            named = true,
-            defaultValue = "[]",
-            doc = "Runtime dependencies that are needed for this library."),
-        @Param(
-            name = "exports",
-            type = SkylarkList.class,
-            generic1 = JavaInfoApi.class,
-            named = true,
-            defaultValue = "[]",
-            doc =
-                "Libraries to make available for users of this library. See also "
-                    + "<a class=\"anchor\" href=\"https://docs.bazel.build/versions/"
-                    + "master/be/java.html#java_library.exports\">java_library.exports</a>."),
-        @Param(
-            name = "jdeps",
-            type = FileApi.class,
-            named = true,
-            defaultValue = "None",
-            noneable = true,
-            doc = "jdeps information for the rule output (if available). This should be a "
-                + "binary proto encoded using the deps.proto protobuf included with Bazel.  "
-                + "If available this file is typically produced by a compiler. IDEs and other "
-                + "tools can use this information for more efficient processing."),
-      },
-      selfCall = true,
-      useLocation = true,
-      useEnvironment = true)
+        name = "JavaInfo",
+        doc = "The <code>JavaInfo</code> constructor.",
+        parameters = {
+          @Param(
+              name = "output_jar",
+              type = FileApi.class,
+              named = true,
+              doc =
+                  "The jar that was created as a result of a compilation "
+                      + "(e.g. javac, scalac, etc)."),
+          @Param(
+              name = "compile_jar",
+              type = FileApi.class,
+              named = true,
+              noneable = true,
+              defaultValue = "None",
+              doc =
+                  "A jar that is added as the compile-time dependency in lieu of "
+                      + "<code>output_jar</code>. Typically this is the ijar produced by "
+                      + "<code><a class=\"anchor\" href=\"java_common.html#run_ijar\">"
+                      + "run_ijar</a></code>. "
+                      + "If you cannot use ijar, consider instead using the output of "
+                      + "<code><a class=\"anchor\" href=\"java_common.html#stamp_jar\">"
+                      + "stamp_ijar</a></code>. If you do not wish to use either, "
+                      + "you can simply pass <code>output_jar</code>."),
+          @Param(
+              name = "source_jar",
+              type = FileApi.class,
+              named = true,
+              noneable = true,
+              defaultValue = "None",
+              doc =
+                  "The source jar that was used to create the output jar. "
+                      + "Use <code><a class=\"anchor\" href=\"java_common.html#pack_sources\">"
+                      + "pack_sources</a></code> to produce this source jar."),
+          @Param(
+              name = "neverlink",
+              type = Boolean.class,
+              named = true,
+              defaultValue = "False",
+              doc = "If true only use this library for compilation and not at runtime."),
+          @Param(
+              name = "deps",
+              type = SkylarkList.class,
+              generic1 = JavaInfoApi.class,
+              named = true,
+              defaultValue = "[]",
+              doc = "Compile time dependencies that were used to create the output jar."),
+          @Param(
+              name = "runtime_deps",
+              type = SkylarkList.class,
+              generic1 = JavaInfoApi.class,
+              named = true,
+              defaultValue = "[]",
+              doc = "Runtime dependencies that are needed for this library."),
+          @Param(
+              name = "exports",
+              type = SkylarkList.class,
+              generic1 = JavaInfoApi.class,
+              named = true,
+              defaultValue = "[]",
+              doc =
+                  "Libraries to make available for users of this library. See also "
+                      + "<a class=\"anchor\" href=\"https://docs.bazel.build/versions/"
+                      + "master/be/java.html#java_library.exports\">java_library.exports</a>."),
+          @Param(
+              name = "jdeps",
+              type = FileApi.class,
+              named = true,
+              defaultValue = "None",
+              noneable = true,
+              doc =
+                  "jdeps information for the rule output (if available). This should be a binary"
+                      + " proto encoded using the deps.proto protobuf included with Bazel.  If"
+                      + " available this file is typically produced by a compiler. IDEs and other"
+                      + " tools can use this information for more efficient processing."),
+        },
+        selfCall = true,
+        useLocation = true,
+        useStarlarkThread = true)
     @SkylarkConstructor(objectType = JavaInfoApi.class, receiverNameForDoc = "JavaInfo")
     public JavaInfoApi<?> javaInfo(
         FileApi outputJarApi,
@@ -250,7 +251,7 @@
         SkylarkList<?> exports,
         Object jdepsApi,
         Location loc,
-        Environment env)
+        StarlarkThread thread)
         throws EvalException;
   }
 }
diff --git a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/repository/RepositoryModuleApi.java b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/repository/RepositoryModuleApi.java
index bdf7dd7..7e72dc4 100644
--- a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/repository/RepositoryModuleApi.java
+++ b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/repository/RepositoryModuleApi.java
@@ -18,11 +18,11 @@
 import com.google.devtools.build.lib.skylarkinterface.SkylarkCallable;
 import com.google.devtools.build.lib.skylarkinterface.SkylarkGlobalLibrary;
 import com.google.devtools.build.lib.syntax.BaseFunction;
-import com.google.devtools.build.lib.syntax.Environment;
 import com.google.devtools.build.lib.syntax.EvalException;
 import com.google.devtools.build.lib.syntax.FuncallExpression;
 import com.google.devtools.build.lib.syntax.SkylarkDict;
 import com.google.devtools.build.lib.syntax.SkylarkList;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
 
 /**
  * The Skylark module containing the definition of {@code repository_rule} function to define a
@@ -97,7 +97,7 @@
             positional = false)
       },
       useAst = true,
-      useEnvironment = true)
+      useStarlarkThread = true)
   public BaseFunction repositoryRule(
       BaseFunction implementation,
       Object attrs,
@@ -106,6 +106,6 @@
       Boolean configure,
       String doc,
       FuncallExpression ast,
-      Environment env)
+      StarlarkThread thread)
       throws EvalException;
 }
diff --git a/src/main/java/com/google/devtools/build/lib/skylarkdebug/server/DebugEventHelper.java b/src/main/java/com/google/devtools/build/lib/skylarkdebug/server/DebugEventHelper.java
index 9b48a31..e7edd09 100644
--- a/src/main/java/com/google/devtools/build/lib/skylarkdebug/server/DebugEventHelper.java
+++ b/src/main/java/com/google/devtools/build/lib/skylarkdebug/server/DebugEventHelper.java
@@ -34,7 +34,7 @@
 import com.google.devtools.build.lib.skylarkdebugging.SkylarkDebuggingProtos.ThreadPausedEvent;
 import com.google.devtools.build.lib.skylarkdebugging.SkylarkDebuggingProtos.Value;
 import com.google.devtools.build.lib.syntax.DebugFrame;
-import com.google.devtools.build.lib.syntax.Environment;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
 import java.util.Collection;
 import java.util.LinkedHashMap;
 import java.util.Map;
@@ -170,16 +170,16 @@
     return builder.build();
   }
 
-  static Environment.Stepping convertSteppingEnum(SkylarkDebuggingProtos.Stepping stepping) {
+  static StarlarkThread.Stepping convertSteppingEnum(SkylarkDebuggingProtos.Stepping stepping) {
     switch (stepping) {
       case INTO:
-        return Environment.Stepping.INTO;
+        return StarlarkThread.Stepping.INTO;
       case OUT:
-        return Environment.Stepping.OUT;
+        return StarlarkThread.Stepping.OUT;
       case OVER:
-        return Environment.Stepping.OVER;
+        return StarlarkThread.Stepping.OVER;
       case NONE:
-        return Environment.Stepping.NONE;
+        return StarlarkThread.Stepping.NONE;
       case UNRECOGNIZED:
         // fall through to exception
     }
diff --git a/src/main/java/com/google/devtools/build/lib/skylarkdebug/server/SkylarkDebugServer.java b/src/main/java/com/google/devtools/build/lib/skylarkdebug/server/SkylarkDebugServer.java
index addd243..4540fd2 100644
--- a/src/main/java/com/google/devtools/build/lib/skylarkdebug/server/SkylarkDebugServer.java
+++ b/src/main/java/com/google/devtools/build/lib/skylarkdebug/server/SkylarkDebugServer.java
@@ -22,7 +22,7 @@
 import com.google.devtools.build.lib.events.Location;
 import com.google.devtools.build.lib.skylarkdebugging.SkylarkDebuggingProtos;
 import com.google.devtools.build.lib.syntax.Debugger;
-import com.google.devtools.build.lib.syntax.Environment;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
 import java.io.IOException;
 import java.net.ServerSocket;
 import java.util.List;
@@ -143,9 +143,9 @@
    * @param location the location of the statement or expression currently being executed
    */
   @Override
-  public void before(Environment env, Location location) {
+  public void before(StarlarkThread thread, Location location) {
     if (!transport.isClosed()) {
-      threadHandler.pauseIfNecessary(env, location, transport);
+      threadHandler.pauseIfNecessary(thread, location, transport);
     }
   }
 
diff --git a/src/main/java/com/google/devtools/build/lib/skylarkdebug/server/ThreadHandler.java b/src/main/java/com/google/devtools/build/lib/skylarkdebug/server/ThreadHandler.java
index 378a16a..8ba96a8 100644
--- a/src/main/java/com/google/devtools/build/lib/skylarkdebug/server/ThreadHandler.java
+++ b/src/main/java/com/google/devtools/build/lib/skylarkdebug/server/ThreadHandler.java
@@ -26,12 +26,12 @@
 import com.google.devtools.build.lib.skylarkdebugging.SkylarkDebuggingProtos.Error;
 import com.google.devtools.build.lib.skylarkdebugging.SkylarkDebuggingProtos.PauseReason;
 import com.google.devtools.build.lib.skylarkdebugging.SkylarkDebuggingProtos.Value;
-import com.google.devtools.build.lib.syntax.Environment;
 import com.google.devtools.build.lib.syntax.EvalException;
 import com.google.devtools.build.lib.syntax.EvalUtils;
 import com.google.devtools.build.lib.syntax.Expression;
 import com.google.devtools.build.lib.syntax.ParserInput;
 import com.google.devtools.build.lib.syntax.Runtime;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
 import com.google.devtools.build.lib.vfs.PathFragment;
 import java.util.Collection;
 import java.util.HashMap;
@@ -49,7 +49,7 @@
   private static class PausedThreadState {
     final long id;
     final String name;
-    final Environment env;
+    final StarlarkThread thread;
     /** The {@link Location} where execution is currently paused. */
     final Location location;
     /** Used to block execution of threads */
@@ -57,10 +57,10 @@
 
     final ThreadObjectMap objectMap;
 
-    PausedThreadState(long id, String name, Environment env, Location location) {
+    PausedThreadState(long id, String name, StarlarkThread thread, Location location) {
       this.id = id;
       this.name = name;
-      this.env = env;
+      this.thread = thread;
       this.location = location;
       this.semaphore = new Semaphore(0);
       this.objectMap = new ThreadObjectMap();
@@ -74,9 +74,9 @@
    */
   private static class SteppingThreadState {
     /** Determines when execution should next be paused. */
-    final Environment.ReadyToPause readyToPause;
+    final StarlarkThread.ReadyToPause readyToPause;
 
-    SteppingThreadState(Environment.ReadyToPause readyToPause) {
+    SteppingThreadState(StarlarkThread.ReadyToPause readyToPause) {
       this.readyToPause = readyToPause;
     }
   }
@@ -196,22 +196,22 @@
   private void resumePausedThread(
       PausedThreadState thread, SkylarkDebuggingProtos.Stepping stepping) {
     pausedThreads.remove(thread.id);
-    Environment.ReadyToPause readyToPause =
-        thread.env.stepControl(DebugEventHelper.convertSteppingEnum(stepping));
+    StarlarkThread.ReadyToPause readyToPause =
+        thread.thread.stepControl(DebugEventHelper.convertSteppingEnum(stepping));
     if (readyToPause != null) {
       steppingThreads.put(thread.id, new SteppingThreadState(readyToPause));
     }
     thread.semaphore.release();
   }
 
-  void pauseIfNecessary(Environment env, Location location, DebugServerTransport transport) {
+  void pauseIfNecessary(StarlarkThread thread, Location location, DebugServerTransport transport) {
     if (servicingEvalRequest.get()) {
       return;
     }
     PauseReason pauseReason;
     Error error = null;
     try {
-      pauseReason = shouldPauseCurrentThread(env, location);
+      pauseReason = shouldPauseCurrentThread(thread, location);
     } catch (ConditionalBreakpointException e) {
       pauseReason = PauseReason.CONDITIONAL_BREAKPOINT_ERROR;
       error = Error.newBuilder().setMessage(e.getMessage()).build();
@@ -224,7 +224,7 @@
     synchronized (this) {
       steppingThreads.remove(threadId);
     }
-    pauseCurrentThread(env, location, transport, pauseReason, error);
+    pauseCurrentThread(thread, location, transport, pauseReason, error);
   }
 
   /** Handles a {@code ListFramesRequest} and returns its response. */
@@ -236,7 +236,7 @@
         throw new DebugRequestException(
             String.format("Thread %s is not paused or does not exist.", threadId));
       }
-      return thread.env.listFrames(thread.location).stream()
+      return thread.thread.listFrames(thread.location).stream()
           .map(frame -> DebugEventHelper.getFrameProto(thread.objectMap, frame))
           .collect(toImmutableList());
     }
@@ -262,23 +262,23 @@
 
   SkylarkDebuggingProtos.Value evaluate(long threadId, String statement)
       throws DebugRequestException {
-    Environment env;
+    StarlarkThread thread;
     ThreadObjectMap objectMap;
     synchronized (this) {
-      PausedThreadState thread = pausedThreads.get(threadId);
-      if (thread == null) {
+      PausedThreadState threadState = pausedThreads.get(threadId);
+      if (threadState == null) {
         throw new DebugRequestException(
             String.format("Thread %s is not paused or does not exist.", threadId));
       }
-      env = thread.env;
-      objectMap = thread.objectMap;
+      thread = threadState.thread;
+      objectMap = threadState.objectMap;
     }
-    // no need to evaluate within the synchronize block: for paused threads, the env and
+    // no need to evaluate within the synchronize block: for paused threads, the thread and
     // object map are only accessed in response to a client request, and requests are handled
     // serially
     // TODO(bazel-team): support asynchronous replies, and use finer-grained locks
     try {
-      Object result = doEvaluate(env, statement);
+      Object result = doEvaluate(thread, statement);
       return DebuggerSerialization.getValueProto(objectMap, "Evaluation result", result);
     } catch (EvalException | InterruptedException e) {
       throw new DebugRequestException(e.getMessage());
@@ -286,14 +286,14 @@
   }
 
   /**
-   * Evaluate the given expression in the environment defined by the provided {@link Environment}.
-   * The "expression" may be a sequence of statements, in which case it is executed for its side
-   * effects, such as assignments.
+   * Evaluate the given expression in the environment defined by the provided {@link
+   * StarlarkThread}. The "expression" may be a sequence of statements, in which case it is executed
+   * for its side effects, such as assignments.
    *
    * <p>The caller is responsible for ensuring that the associated skylark thread isn't currently
    * running.
    */
-  private Object doEvaluate(Environment env, String content)
+  private Object doEvaluate(StarlarkThread thread, String content)
       throws EvalException, InterruptedException {
     try {
       servicingEvalRequest.set(true);
@@ -313,10 +313,10 @@
       Expression.parse(input, sensor); // discard result
       if (!sensor.wasTriggered()) {
         // It's a valid expression; evaluate (and parse again).
-        return env.debugEval(input);
+        return thread.debugEval(input);
       } else {
         // Assume it is a file and execute it.
-        env.debugExec(input);
+        thread.debugExec(input);
         return Runtime.NONE;
       }
     } finally {
@@ -329,7 +329,7 @@
    * ContinueExecutionRequest.
    */
   private void pauseCurrentThread(
-      Environment env,
+      StarlarkThread thread,
       Location location,
       DebugServerTransport transport,
       PauseReason pauseReason,
@@ -337,7 +337,7 @@
     long threadId = Thread.currentThread().getId();
 
     PausedThreadState pausedState =
-        new PausedThreadState(threadId, Thread.currentThread().getName(), env, location);
+        new PausedThreadState(threadId, Thread.currentThread().getName(), thread, location);
     synchronized (this) {
       pausedThreads.put(threadId, pausedState);
     }
@@ -349,7 +349,7 @@
   }
 
   @Nullable
-  private PauseReason shouldPauseCurrentThread(Environment env, Location location)
+  private PauseReason shouldPauseCurrentThread(StarlarkThread thread, Location location)
       throws ConditionalBreakpointException {
     long threadId = Thread.currentThread().getId();
     DebuggerState state = debuggerState;
@@ -362,7 +362,7 @@
     if (threadsToPause.contains(threadId)) {
       return PauseReason.PAUSE_THREAD_REQUEST;
     }
-    if (hasBreakpointMatchedAtLocation(env, location)) {
+    if (hasBreakpointMatchedAtLocation(thread, location)) {
       return PauseReason.HIT_BREAKPOINT;
     }
 
@@ -370,7 +370,7 @@
     // concurrent map, and synchronizing on individual entries
     synchronized (this) {
       SteppingThreadState steppingState = steppingThreads.get(threadId);
-      if (steppingState != null && steppingState.readyToPause.test(env)) {
+      if (steppingState != null && steppingState.readyToPause.test(thread)) {
         return PauseReason.STEPPING;
       }
     }
@@ -381,7 +381,7 @@
    * Returns true if there's a breakpoint at the current location, with a satisfied condition if
    * relevant.
    */
-  private boolean hasBreakpointMatchedAtLocation(Environment env, Location location)
+  private boolean hasBreakpointMatchedAtLocation(StarlarkThread thread, Location location)
       throws ConditionalBreakpointException {
     // breakpoints is volatile, so taking a local copy
     ImmutableMap<SkylarkDebuggingProtos.Location, SkylarkDebuggingProtos.Breakpoint> breakpoints =
@@ -403,7 +403,7 @@
       return true;
     }
     try {
-      return EvalUtils.toBoolean(doEvaluate(env, condition));
+      return EvalUtils.toBoolean(doEvaluate(thread, condition));
     } catch (EvalException | InterruptedException e) {
       throw new ConditionalBreakpointException(e.getMessage());
     }
diff --git a/src/main/java/com/google/devtools/build/lib/skylarkinterface/SkylarkCallable.java b/src/main/java/com/google/devtools/build/lib/skylarkinterface/SkylarkCallable.java
index 8ea3602..3ab849a 100644
--- a/src/main/java/com/google/devtools/build/lib/skylarkinterface/SkylarkCallable.java
+++ b/src/main/java/com/google/devtools/build/lib/skylarkinterface/SkylarkCallable.java
@@ -46,11 +46,12 @@
  *   <li>If structField=true, there must be zero user-supplied parameters.
  *   <li>The underlying java method's parameters must be supplied in the following order:
  *       <pre>method([positionals]*[named args]*(extra positionals list)(extra kwargs)
- *       (Location)(FuncallExpression)(Envrionment)(StarlarkSemantics))</pre>
+ *       (Location)(FuncallExpression)(StarlarkThread)(StarlarkSemantics))</pre>
  *       where (extra positionals list) is a SkylarkList if extraPositionals is defined, (extra
  *       kwargs) is a SkylarkDict if extraKeywords is defined, and Location, FuncallExpression,
- *       Environment, and StarlarkSemantics are supplied by the interpreter if and only if
- *       useLocation, useAst, useEnvironment, and useStarlarkSemantics are specified, respectively.
+ *       StarlarkThread, and StarlarkSemantics are supplied by the interpreter if and only if
+ *       useLocation, useAst, useStarlarkThread, and useStarlarkSemantics are specified,
+ *       respectively.
  *   <li>The number of method parameters much match the number of annotation-declared parameters
  *       plus the number of interpreter-supplied parameters.
  * </ul>
@@ -154,13 +155,13 @@
   boolean useAst() default false;
 
   /**
-   * If true, the Starlark Environment will be passed as an argument of the annotated function.
-   * (Thus, the annotated method signature must contain Environment as a parameter. See the
-   * interface-level javadoc for details.)
+   * If true, the StarlarkThread will be passed as an argument of the annotated function. (Thus, the
+   * annotated method signature must contain StarlarkThread as a parameter. See the interface-level
+   * javadoc for details.)
    *
    * <p>This is incompatible with structField=true. If structField is true, this must be false.
    */
-  boolean useEnvironment() default false;
+  boolean useStarlarkThread() default false;
 
   /**
    * If true, the Starlark semantics will be passed as an argument of the annotated function. (Thus,
diff --git a/src/main/java/com/google/devtools/build/lib/skylarkinterface/SkylarkSignature.java b/src/main/java/com/google/devtools/build/lib/skylarkinterface/SkylarkSignature.java
index 02ed5fe5..e0fbeaa2 100644
--- a/src/main/java/com/google/devtools/build/lib/skylarkinterface/SkylarkSignature.java
+++ b/src/main/java/com/google/devtools/build/lib/skylarkinterface/SkylarkSignature.java
@@ -29,8 +29,8 @@
  * <ul>
  *   <li>{@link com.google.devtools.build.lib.events.Location} if {@link #useLocation()} is true.
  *   <li>{@link com.google.devtools.build.lib.syntax.Node} if {@link #useAst()} is true.
- *   <li>{@link com.google.devtools.build.lib.syntax.Environment} if {@link #useEnvironment()} )} is
- *       true.
+ *   <li>{@link com.google.devtools.build.lib.syntax.StarlarkThread} if {@link #useStarlarkThread()}
+ *       )} is true.
  * </ul>
  */
 @Target({ElementType.FIELD})
@@ -113,9 +113,8 @@
   boolean useAst() default false;
 
   /**
-   * If true the AST of the Skylark Environment
-   * ({@link com.google.devtools.build.lib.syntax.Environment}) will be passed as an argument of the
-   * annotated function.
+   * If true the ({@link com.google.devtools.build.lib.syntax.StarlarkThread}) will be passed as an
+   * argument of the annotated function.
    */
-  boolean useEnvironment() default false;
+  boolean useStarlarkThread() default false;
 }
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 b0904a0..98bc662 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
@@ -49,7 +49,7 @@
  *       <pre>method([positionals]*[other user-args](Location)(FuncallExpression)(Environment))
  *       </pre>
  *       where Location, FuncallExpression, and Environment are supplied by the interpreter if and
- *       only if useLocation, useAst, and useEnvironment are specified, respectively.
+ *       only if useLocation, useAst, and useStarlarkThread are specified, respectively.
  *   <li>The number of method parameters must match the number of annotation-declared parameters
  *       plus the number of interpreter-supplied parameters.
  *   <li>Each parameter, if explicitly typed, may only use either 'type' or 'allowedTypes', not
@@ -82,7 +82,7 @@
       "com.google.devtools.build.lib.syntax.SkylarkDict<?,?>";
   private static final String LOCATION = "com.google.devtools.build.lib.events.Location";
   private static final String AST = "com.google.devtools.build.lib.syntax.FuncallExpression";
-  private static final String ENVIRONMENT = "com.google.devtools.build.lib.syntax.Environment";
+  private static final String ENVIRONMENT = "com.google.devtools.build.lib.syntax.StarlarkThread";
   private static final String STARLARK_SEMANTICS =
       "com.google.devtools.build.lib.syntax.StarlarkSemantics";
 
@@ -424,12 +424,12 @@
       }
       currentIndex++;
     }
-    if (annotation.useEnvironment()) {
+    if (annotation.useStarlarkThread()) {
       if (!ENVIRONMENT.equals(methodSignatureParams.get(currentIndex).asType().toString())) {
         throw new SkylarkCallableProcessorException(
             methodElement,
             String.format(
-                "Expected parameter index %d to be the %s type, matching useEnvironment, "
+                "Expected parameter index %d to be the %s type, matching useStarlarkThread, "
                     + "but was %s",
                 currentIndex,
                 ENVIRONMENT,
@@ -458,7 +458,7 @@
     numExtraInterpreterParams += annotation.extraKeywords().name().isEmpty() ? 0 : 1;
     numExtraInterpreterParams += annotation.useLocation() ? 1 : 0;
     numExtraInterpreterParams += annotation.useAst() ? 1 : 0;
-    numExtraInterpreterParams += annotation.useEnvironment() ? 1 : 0;
+    numExtraInterpreterParams += annotation.useStarlarkThread() ? 1 : 0;
     numExtraInterpreterParams += annotation.useStarlarkSemantics() ? 1 : 0;
     return numExtraInterpreterParams;
   }
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 6866b97..f67419a 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
@@ -179,9 +179,11 @@
   /**
    * Process the caller-provided arguments into an array suitable for the callee (this function).
    */
-  public Object[] processArguments(List<Object> args,
+  public Object[] processArguments(
+      List<Object> args,
       @Nullable Map<String, Object> kwargs,
-      @Nullable Location loc, @Nullable Environment env)
+      @Nullable Location loc,
+      @Nullable StarlarkThread thread)
       throws EvalException {
 
     Object[] arguments = new Object[getArgArraySize()];
@@ -256,7 +258,7 @@
       // If there's a kwParam, it's empty.
       if (hasKwParam) {
         // TODO(bazel-team): create a fresh mutable dict, like Python does
-        arguments[kwParamIndex] = SkylarkDict.of(env);
+        arguments[kwParamIndex] = SkylarkDict.of(thread);
       }
     } else if (hasKwParam && numNamedParams == 0) {
       // Easy case (2b): there are no named parameters, but there is a **kwParam.
@@ -265,10 +267,10 @@
       // Also note that no named parameters means no mandatory parameters that weren't passed,
       // and no missing optional parameters for which to use a default. Thus, no loops.
       // NB: not 2a means kwarg isn't null
-      arguments[kwParamIndex] = SkylarkDict.copyOf(env, kwargs);
+      arguments[kwParamIndex] = SkylarkDict.copyOf(thread, kwargs);
     } else {
       // Hard general case (2c): some keyword arguments may correspond to named parameters
-      SkylarkDict<String, Object> kwArg = hasKwParam ? SkylarkDict.of(env) : SkylarkDict.empty();
+      SkylarkDict<String, Object> kwArg = hasKwParam ? SkylarkDict.of(thread) : SkylarkDict.empty();
 
       // For nicer stabler error messages, start by checking against
       // an argument being provided both as positional argument and as keyword argument.
@@ -303,12 +305,12 @@
             throw new EvalException(loc, String.format(
                 "%s got multiple values for keyword argument '%s'", this, keyword));
           }
-          kwArg.put(keyword, value, loc, env);
+          kwArg.put(keyword, value, loc, thread);
         }
       }
       if (hasKwParam) {
         // TODO(bazel-team): create a fresh mutable dict, like Python does
-        arguments[kwParamIndex] = SkylarkDict.copyOf(env, kwArg);
+        arguments[kwParamIndex] = SkylarkDict.copyOf(thread, kwArg);
       }
 
       // Check that all mandatory parameters were filled in general case 2c.
@@ -381,22 +383,23 @@
    * @param args a list of all positional arguments (as in *starArg)
    * @param kwargs a map for key arguments (as in **kwArgs)
    * @param ast the expression for this function's definition
-   * @param env the Environment in the function is called
+   * @param thread the StarlarkThread in the function is called
    * @return the value resulting from evaluating the function with the given arguments
    * @throws EvalException-s containing source information.
    */
-  public Object call(List<Object> args,
+  public Object call(
+      List<Object> args,
       @Nullable Map<String, Object> kwargs,
       @Nullable FuncallExpression ast,
-      Environment env)
+      StarlarkThread thread)
       throws EvalException, InterruptedException {
     Preconditions.checkState(isConfigured(), "Function %s was not configured", getName());
 
     // ast is null when called from Java (as there's no Skylark call site).
     Location loc = ast == null ? Location.BUILTIN : ast.getLocation();
 
-    Object[] arguments = processArguments(args, kwargs, loc, env);
-    return callWithArgArray(arguments, ast, env, location);
+    Object[] arguments = processArguments(args, kwargs, loc, thread);
+    return callWithArgArray(arguments, ast, thread, location);
   }
 
   /**
@@ -404,11 +407,11 @@
    *
    * @param args an array of argument values sorted as per the signature.
    * @param ast the source code for the function if user-defined
-   * @param env the lexical environment of the function call
+   * @param thread the Starlark thread for the call
    * @throws InterruptedException may be thrown in the function implementations.
    */
   // Don't make it abstract, so that subclasses may be defined that @Override the outer call() only.
-  protected Object call(Object[] args, @Nullable FuncallExpression ast, Environment env)
+  protected Object call(Object[] args, @Nullable FuncallExpression ast, StarlarkThread thread)
       throws EvalException, InterruptedException {
     throw new EvalException(
         (ast == null) ? Location.BUILTIN : ast.getLocation(),
@@ -420,12 +423,12 @@
    * been resolved into positional ones.
    *
    * @param ast the expression for this function's definition
-   * @param env the Environment in the function is called
+   * @param thread the StarlarkThread in the function is called
    * @return the value resulting from evaluating the function with the given arguments
    * @throws EvalException-s containing source information.
    */
   public Object callWithArgArray(
-      Object[] arguments, @Nullable FuncallExpression ast, Environment env, Location loc)
+      Object[] arguments, @Nullable FuncallExpression ast, StarlarkThread thread, Location loc)
       throws EvalException, InterruptedException {
     Preconditions.checkState(isConfigured(), "Function %s was not configured", getName());
     canonicalizeArguments(arguments, loc);
@@ -434,7 +437,7 @@
       if (Callstack.enabled) {
         Callstack.push(this);
       }
-      return call(arguments, ast, env);
+      return call(arguments, ast, thread);
     } finally {
       if (Callstack.enabled) {
         Callstack.pop();
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/BuildFileAST.java b/src/main/java/com/google/devtools/build/lib/syntax/BuildFileAST.java
index 737f220..7f7e7b5 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/BuildFileAST.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/BuildFileAST.java
@@ -123,8 +123,9 @@
   }
 
   /** Returns true if there was no error event. */
-  public boolean replayLexerEvents(Environment env, EventHandler eventHandler) {
-    if (env.getSemantics().incompatibleRestrictStringEscapes() && !stringEscapeEvents.isEmpty()) {
+  public boolean replayLexerEvents(StarlarkThread thread, EventHandler eventHandler) {
+    if (thread.getSemantics().incompatibleRestrictStringEscapes()
+        && !stringEscapeEvents.isEmpty()) {
       Event.replayEventsOn(eventHandler, stringEscapeEvents);
       return false;
     }
@@ -132,7 +133,7 @@
   }
 
   /**
-   * Executes this build file in a given Environment.
+   * Executes this build file in a given StarlarkThread.
    *
    * <p>If, for any reason, execution of a statement cannot be completed, exec throws an {@link
    * EvalException}. This exception is caught here and reported through reporter and execution
@@ -147,10 +148,11 @@
    * @return true if no error occurred during execution.
    */
   // TODO(adonovan): move to EvalUtils.
-  public boolean exec(Environment env, EventHandler eventHandler) throws InterruptedException {
+  public boolean exec(StarlarkThread thread, EventHandler eventHandler)
+      throws InterruptedException {
     boolean ok = true;
     for (Statement stmt : statements) {
-      if (!execTopLevelStatement(stmt, env, eventHandler)) {
+      if (!execTopLevelStatement(stmt, thread, eventHandler)) {
         ok = false;
       }
     }
@@ -158,7 +160,7 @@
   }
 
   /**
-   * Executes top-level statement of this build file in a given Environment.
+   * Executes top-level statement of this build file in a given StarlarkThread.
    *
    * <p>If, for any reason, execution of a statement cannot be completed, exec throws an {@link
    * EvalException}. This exception is caught here and reported through reporter. In effect, there
@@ -172,10 +174,11 @@
    *
    * @return true if no error occurred during execution.
    */
-  public boolean execTopLevelStatement(Statement stmt, Environment env, EventHandler eventHandler)
+  public boolean execTopLevelStatement(
+      Statement stmt, StarlarkThread thread, EventHandler eventHandler)
       throws InterruptedException {
     try {
-      Eval.execToplevelStatement(env, stmt);
+      Eval.execToplevelStatement(thread, stmt);
       return true;
     } catch (EvalException e) {
       // Do not report errors caused by a previous parsing error, as it has already been
@@ -283,9 +286,10 @@
   // TODO(adonovan): eliminate. Most callers need validation because they intend to execute the
   // file, and should be made to use higher-level operations in EvalUtils.
   // rest should skip this step. Called from EvaluationTestCase, ParserTest, ASTFileLookupFunction.
-  public BuildFileAST validate(Environment env, boolean isBuildFile, EventHandler eventHandler) {
+  public BuildFileAST validate(
+      StarlarkThread thread, boolean isBuildFile, EventHandler eventHandler) {
     try {
-      ValidationEnvironment.validateFile(this, env, isBuildFile);
+      ValidationEnvironment.validateFile(this, thread, isBuildFile);
       return this;
     } catch (EvalException e) {
       if (!e.isDueToIncompleteAST()) {
@@ -312,7 +316,7 @@
   // (Abolish "statement" and "file+expr" as primary API concepts.)
   // Make callers decide whether they want to execute a file or evaluate an expression.
   @Nullable
-  public Object eval(Environment env) throws EvalException, InterruptedException {
+  public Object eval(StarlarkThread thread) throws EvalException, InterruptedException {
     List<Statement> stmts = statements;
     Expression expr = null;
     int n = statements.size();
@@ -320,22 +324,22 @@
       stmts = statements.subList(0, n - 1);
       expr = ((ExpressionStatement) statements.get(n - 1)).getExpression();
     }
-    Eval.execStatements(env, stmts);
-    return expr == null ? null : Eval.eval(env, expr);
+    Eval.execStatements(thread, stmts);
+    return expr == null ? null : Eval.eval(thread, expr);
   }
 
   /**
    * Parses, resolves and evaluates the input and returns the value of the last statement if it's an
    * Expression or else null. In case of error (either during validation or evaluation), it throws
-   * an EvalException. The return value is as for eval(Environment).
+   * an EvalException. The return value is as for eval(StarlarkThread).
    */
   // Note: uses Starlark (not BUILD) validation semantics.
   // TODO(adonovan): move to EvalUtils; see other eval function.
   @Nullable
-  public static Object eval(ParserInput input, Environment env)
+  public static Object eval(ParserInput input, StarlarkThread thread)
       throws EvalException, InterruptedException {
-    BuildFileAST ast = parseAndValidateSkylark(input, env);
-    return ast.eval(env);
+    BuildFileAST ast = parseAndValidateSkylark(input, thread);
+    return ast.eval(thread);
   }
 
   /**
@@ -343,11 +347,11 @@
    * it throws an EvalException. Uses Starlark (not BUILD) validation semantics.
    */
   // TODO(adonovan): move to EvalUtils; see above.
-  public static BuildFileAST parseAndValidateSkylark(ParserInput input, Environment env)
+  public static BuildFileAST parseAndValidateSkylark(ParserInput input, StarlarkThread thread)
       throws EvalException {
-    BuildFileAST file = parse(input, env.getEventHandler());
-    file.replayLexerEvents(env, env.getEventHandler());
-    ValidationEnvironment.validateFile(file, env, /*isBuildFile=*/ false);
+    BuildFileAST file = parse(input, thread.getEventHandler());
+    file.replayLexerEvents(thread, thread.getEventHandler());
+    ValidationEnvironment.validateFile(file, thread, /*isBuildFile=*/ false);
     return file;
   }
 
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/BuiltinCallable.java b/src/main/java/com/google/devtools/build/lib/syntax/BuiltinCallable.java
index 91389ca..04b0d78 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/BuiltinCallable.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/BuiltinCallable.java
@@ -42,9 +42,9 @@
       List<Object> args,
       @Nullable Map<String, Object> kwargs,
       FuncallExpression ast,
-      Environment env)
+      StarlarkThread thread)
       throws EvalException, InterruptedException {
-    MethodDescriptor methodDescriptor = getMethodDescriptor(env.getSemantics());
+    MethodDescriptor methodDescriptor = getMethodDescriptor(thread.getSemantics());
     Class<?> clazz;
     Object objValue;
 
@@ -62,8 +62,8 @@
         Profiler.instance().profile(ProfilerTask.STARLARK_BUILTIN_FN, methodName)) {
       Object[] javaArguments =
           CallUtils.convertStarlarkArgumentsToJavaMethodArguments(
-              env, ast, methodDescriptor, clazz, args, kwargs);
-      return methodDescriptor.call(objValue, javaArguments, ast.getLocation(), env);
+              thread, ast, methodDescriptor, clazz, args, kwargs);
+      return methodDescriptor.call(objValue, javaArguments, ast.getLocation(), thread);
     }
   }
 
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 8af2052..5887f00 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
@@ -21,8 +21,8 @@
 import com.google.devtools.build.lib.profiler.SilentCloseable;
 import com.google.devtools.build.lib.skylarkinterface.SkylarkPrinter;
 import com.google.devtools.build.lib.skylarkinterface.SkylarkSignature;
-import com.google.devtools.build.lib.syntax.Environment.LexicalFrame;
 import com.google.devtools.build.lib.syntax.SkylarkType.SkylarkFunctionType;
+import com.google.devtools.build.lib.syntax.StarlarkThread.LexicalFrame;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.util.ArrayList;
@@ -133,9 +133,9 @@
 
   @Override
   @Nullable
-  public Object call(Object[] args, @Nullable FuncallExpression ast, Environment env)
+  public Object call(Object[] args, @Nullable FuncallExpression ast, StarlarkThread thread)
       throws EvalException, InterruptedException {
-    Preconditions.checkNotNull(env);
+    Preconditions.checkNotNull(thread);
 
     // ast is null when called from Java (as there's no Skylark call site).
     Location loc = ast == null ? Location.BUILTIN : ast.getLocation();
@@ -154,7 +154,7 @@
             break;
 
           case ENVIRONMENT:
-            args[i] = env;
+            args[i] = thread;
             break;
         }
         i++;
@@ -164,7 +164,8 @@
     // Last but not least, actually make an inner call to the function with the resolved arguments.
     try (SilentCloseable c =
         Profiler.instance().profile(ProfilerTask.STARLARK_BUILTIN_FN, getName())) {
-      env.enterScope(this, SHARED_LEXICAL_FRAME_FOR_BUILTIN_FUNCTION_CALLS, ast, env.getGlobals());
+      thread.enterScope(
+          this, SHARED_LEXICAL_FRAME_FOR_BUILTIN_FUNCTION_CALLS, ast, thread.getGlobals());
       return invokeMethod.invoke(this, args);
     } catch (InvocationTargetException x) {
       Throwable e = x.getCause();
@@ -201,7 +202,7 @@
     } catch (IllegalAccessException e) {
       throw badCallException(loc, e, args);
     } finally {
-      env.exitScope();
+      thread.exitScope();
     }
   }
 
@@ -360,7 +361,7 @@
     }
 
     @Override
-    public Object call(Object[] args, @Nullable FuncallExpression ast, Environment env)
+    public Object call(Object[] args, @Nullable FuncallExpression ast, StarlarkThread thread)
         throws EvalException {
       throw new EvalException(null, "tried to invoke a Factory for function " + this);
     }
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/CallUtils.java b/src/main/java/com/google/devtools/build/lib/syntax/CallUtils.java
index 1e5e6be..459247f 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/CallUtils.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/CallUtils.java
@@ -192,7 +192,7 @@
                 }
               });
 
-  // *args, **kwargs, location, ast, environment, skylark semantics
+  // *args, **kwargs, location, ast, thread, skylark semantics
   private static final int EXTRA_ARGS_COUNT = 6;
 
   /**
@@ -373,7 +373,7 @@
    * Invokes the given structField=true method and returns the result.
    *
    * <p>The given method must <b>not</b> require extra-interpreter parameters, such as {@link
-   * Environment}. This method throws {@link IllegalArgumentException} for violations.
+   * StarlarkThread}. This method throws {@link IllegalArgumentException} for violations.
    *
    * @param methodDescriptor the descriptor of the method to invoke
    * @param fieldName the name of the struct field
@@ -387,7 +387,7 @@
     Preconditions.checkArgument(
         methodDescriptor.isStructField(), "Can only be invoked on structField callables");
     Preconditions.checkArgument(
-        !methodDescriptor.isUseEnvironment()
+        !methodDescriptor.isUseStarlarkThread()
             || !methodDescriptor.isUseStarlarkSemantics()
             || !methodDescriptor.isUseLocation(),
         "Cannot be invoked on structField callables with extra interpreter params");
@@ -403,14 +403,14 @@
    * @param args a list of positional Starlark arguments
    * @param kwargs a map of keyword Starlark arguments; keys are the used keyword, and values are
    *     their corresponding values in the method call
-   * @param environment the current Starlark environment
+   * @param thread the Starlark thread for the call
    * @return the array of arguments which may be passed to {@link MethodDescriptor#call}
    * @throws EvalException if the given set of arguments are invalid for the given method. For
    *     example, if any arguments are of unexpected type, or not all mandatory parameters are
    *     specified by the user
    */
   static Object[] convertStarlarkArgumentsToJavaMethodArguments(
-      Environment environment,
+      StarlarkThread thread,
       FuncallExpression call,
       MethodDescriptor method,
       Class<?> objClass,
@@ -523,18 +523,18 @@
         }
         extraKwargs = extraKwargsBuilder.build();
       } else {
-        throw unexpectedKeywordArgumentException(call, keys, method, objClass, environment);
+        throw unexpectedKeywordArgumentException(call, keys, method, objClass, thread);
       }
     }
 
-    // Then add any skylark-interpreter arguments (for example kwargs or the Environment).
+    // Then add any skylark-interpreter arguments (for example kwargs or the StarlarkThread).
     if (acceptsExtraArgs) {
       builder.add(Tuple.copyOf(extraArgs));
     }
     if (acceptsExtraKwargs) {
-      builder.add(SkylarkDict.copyOf(environment, extraKwargs));
+      builder.add(SkylarkDict.copyOf(thread, extraKwargs));
     }
-    appendExtraInterpreterArgs(builder, method, call, call.getLocation(), environment);
+    appendExtraInterpreterArgs(builder, method, call, call.getLocation(), thread);
 
     return builder.toArray();
   }
@@ -565,7 +565,7 @@
       Set<String> unexpectedKeywords,
       MethodDescriptor method,
       Class<?> objClass,
-      Environment env) {
+      StarlarkThread thread) {
     // Check if any of the unexpected keywords are for parameters which are disabled by the
     // current semantic flags. Throwing an error with information about the misconfigured
     // semantic flag is likely far more helpful.
@@ -573,7 +573,7 @@
       if (param.isDisabledInCurrentSemantics() && unexpectedKeywords.contains(param.getName())) {
         FlagIdentifier flagIdentifier = param.getFlagResponsibleForDisable();
         // If the flag is True, it must be a deprecation flag. Otherwise it's an experimental flag.
-        if (env.getSemantics().flagValue(flagIdentifier)) {
+        if (thread.getSemantics().flagValue(flagIdentifier)) {
           return new EvalException(
               call.getLocation(),
               String.format(
@@ -640,25 +640,28 @@
    * the caller to validate this invariant.
    */
   static List<Object> extraInterpreterArgs(
-      MethodDescriptor method, @Nullable FuncallExpression ast, Location loc, Environment env) {
+      MethodDescriptor method,
+      @Nullable FuncallExpression ast,
+      Location loc,
+      StarlarkThread thread) {
     List<Object> builder = new ArrayList<>();
-    appendExtraInterpreterArgs(builder, method, ast, loc, env);
+    appendExtraInterpreterArgs(builder, method, ast, loc, thread);
     return ImmutableList.copyOf(builder);
   }
 
   /**
    * Same as {@link #extraInterpreterArgs(MethodDescriptor, FuncallExpression, Location,
-   * Environment)} but appends args to a passed {@code builder} to avoid unnecessary allocations of
-   * intermediate instances.
+   * StarlarkThread)} but appends args to a passed {@code builder} to avoid unnecessary allocations
+   * of intermediate instances.
    *
-   * @see #extraInterpreterArgs(MethodDescriptor, FuncallExpression, Location, Environment)
+   * @see #extraInterpreterArgs(MethodDescriptor, FuncallExpression, Location, StarlarkThread)
    */
   private static void appendExtraInterpreterArgs(
       List<Object> builder,
       MethodDescriptor method,
       @Nullable FuncallExpression ast,
       Location loc,
-      Environment env) {
+      StarlarkThread thread) {
     if (method.isUseLocation()) {
       builder.add(loc);
     }
@@ -668,11 +671,11 @@
       }
       builder.add(ast);
     }
-    if (method.isUseEnvironment()) {
-      builder.add(env);
+    if (method.isUseStarlarkThread()) {
+      builder.add(thread);
     }
     if (method.isUseStarlarkSemantics()) {
-      builder.add(env.getSemantics());
+      builder.add(thread.getSemantics());
     }
   }
 
@@ -710,7 +713,7 @@
 
   /** Invoke object.method() and return the result. */
   static Object callMethod(
-      Environment env,
+      StarlarkThread thread,
       FuncallExpression call,
       Object object,
       ArrayList<Object> posargs,
@@ -720,7 +723,7 @@
       throws EvalException, InterruptedException {
     // Case 1: Object is a String. String is an unusual special case.
     if (object instanceof String) {
-      return callStringMethod(env, call, (String) object, methodName, posargs, kwargs);
+      return callStringMethod(thread, call, (String) object, methodName, posargs, kwargs);
     }
 
     // Case 2: Object is a Java object with a matching @SkylarkCallable method.
@@ -728,12 +731,12 @@
     // java method 'bar()', this avoids evaluating 'foo.bar' in isolation (which would require
     // creating a throwaway function-like object).
     MethodDescriptor methodDescriptor =
-        CallUtils.getMethod(env.getSemantics(), object.getClass(), methodName);
+        CallUtils.getMethod(thread.getSemantics(), object.getClass(), methodName);
     if (methodDescriptor != null && !methodDescriptor.isStructField()) {
       Object[] javaArguments =
           convertStarlarkArgumentsToJavaMethodArguments(
-              env, call, methodDescriptor, object.getClass(), posargs, kwargs);
-      return methodDescriptor.call(object, javaArguments, call.getLocation(), env);
+              thread, call, methodDescriptor, object.getClass(), posargs, kwargs);
+      return methodDescriptor.call(object, javaArguments, call.getLocation(), thread);
     }
 
     // Case 3: Object is a function registered with the BuiltinRegistry.
@@ -743,16 +746,16 @@
         Runtime.getBuiltinRegistry().getFunction(object.getClass(), methodName);
     if (legacyRuntimeFunction != null) {
       return callLegacyBuiltinRegistryFunction(
-          call, legacyRuntimeFunction, object, posargs, kwargs, env);
+          call, legacyRuntimeFunction, object, posargs, kwargs, thread);
     }
 
     // Case 4: All other cases. Evaluate "foo.bar" as a dot expression, then try to invoke it
     // as a callable.
-    Object functionObject = EvalUtils.getAttr(env, dotLocation, object, methodName);
+    Object functionObject = EvalUtils.getAttr(thread, dotLocation, object, methodName);
     if (functionObject == null) {
       throw missingMethodException(call, object.getClass(), methodName);
     } else {
-      return call(env, call, functionObject, posargs, kwargs);
+      return call(thread, call, functionObject, posargs, kwargs);
     }
   }
 
@@ -762,16 +765,16 @@
       Object object,
       ArrayList<Object> posargs,
       Map<String, Object> kwargs,
-      Environment env)
+      StarlarkThread thread)
       throws EvalException, InterruptedException {
     if (!isNamespace(object.getClass())) {
       posargs.add(0, object);
     }
-    return legacyRuntimeFunction.call(posargs, kwargs, call, env);
+    return legacyRuntimeFunction.call(posargs, kwargs, call, thread);
   }
 
   private static Object callStringMethod(
-      Environment env,
+      StarlarkThread thread,
       FuncallExpression call,
       String objValue,
       String methodName,
@@ -782,19 +785,19 @@
     // to StringModule, and thus need to include the actual string as a 'self' parameter.
     posargs.add(0, objValue);
 
-    MethodDescriptor method = getMethod(env.getSemantics(), StringModule.class, methodName);
+    MethodDescriptor method = getMethod(thread.getSemantics(), StringModule.class, methodName);
     if (method == null) {
       throw missingMethodException(call, StringModule.class, methodName);
     }
 
     Object[] javaArguments =
         convertStarlarkArgumentsToJavaMethodArguments(
-            env, call, method, StringModule.class, posargs, kwargs);
-    return method.call(StringModule.INSTANCE, javaArguments, call.getLocation(), env);
+            thread, call, method, StringModule.class, posargs, kwargs);
+    return method.call(StringModule.INSTANCE, javaArguments, call.getLocation(), thread);
   }
 
   static Object call(
-      Environment env,
+      StarlarkThread thread,
       FuncallExpression call,
       Object fn,
       ArrayList<Object> posargs,
@@ -803,13 +806,13 @@
 
     if (fn instanceof StarlarkCallable) {
       StarlarkCallable callable = (StarlarkCallable) fn;
-      return callable.call(posargs, ImmutableMap.copyOf(kwargs), call, env);
-    } else if (hasSelfCallMethod(env.getSemantics(), fn.getClass())) {
-      MethodDescriptor descriptor = getSelfCallMethodDescriptor(env.getSemantics(), fn);
+      return callable.call(posargs, ImmutableMap.copyOf(kwargs), call, thread);
+    } else if (hasSelfCallMethod(thread.getSemantics(), fn.getClass())) {
+      MethodDescriptor descriptor = getSelfCallMethodDescriptor(thread.getSemantics(), fn);
       Object[] javaArguments =
           convertStarlarkArgumentsToJavaMethodArguments(
-              env, call, descriptor, fn.getClass(), posargs, kwargs);
-      return descriptor.call(fn, javaArguments, call.getLocation(), env);
+              thread, call, descriptor, fn.getClass(), posargs, kwargs);
+      return descriptor.call(fn, javaArguments, call.getLocation(), thread);
     } else {
       throw new EvalException(
           call.getLocation(), "'" + EvalUtils.getDataTypeName(fn) + "' object is not callable");
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/Debugger.java b/src/main/java/com/google/devtools/build/lib/syntax/Debugger.java
index 9997010..39b658b 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/Debugger.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/Debugger.java
@@ -22,7 +22,7 @@
 public interface Debugger {
 
   /** Notify the debugger that execution is at the point immediately before {@code loc}. */
-  void before(Environment env, Location loc);
+  void before(StarlarkThread thread, Location loc);
 
   /** Notify the debugger that it will no longer receive events from the interpreter. */
   void close();
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/Eval.java b/src/main/java/com/google/devtools/build/lib/syntax/Eval.java
index be3a172..63d5dd2 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/Eval.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/Eval.java
@@ -29,14 +29,14 @@
 
 /** A syntax-tree-walking evaluator. */
 // TODO(adonovan): make this class the sole locus of tree-based evaluation logic.
-// Make all its methods static, and thread Environment (soon: StarlarkThread) explicitly.
-// The only actual state is the return value, which can be saved in the Environment's call frame.
+// Make all its methods static, and thread StarlarkThread (soon: StarlarkThread) explicitly.
+// The only actual state is the return value, which can be saved in the StarlarkThread's call frame.
 // Move remaining Expression.eval logic here, and simplify.
 final class Eval {
 
   private static final AtomicReference<Debugger> debugger = new AtomicReference<>();
 
-  private final Environment env;
+  private final StarlarkThread thread;
   private final Debugger dbg;
   private Object result = Runtime.NONE;
 
@@ -49,37 +49,37 @@
     }
   }
 
-  static Object execStatements(Environment env, List<Statement> statements)
+  static Object execStatements(StarlarkThread thread, List<Statement> statements)
       throws EvalException, InterruptedException {
-    Eval eval = new Eval(env);
+    Eval eval = new Eval(thread);
     eval.execStatementsInternal(statements);
     return eval.result;
   }
 
-  static void execToplevelStatement(Environment env, Statement stmt)
+  static void execToplevelStatement(StarlarkThread thread, Statement stmt)
       throws EvalException, InterruptedException {
     // Ignore the returned BREAK/CONTINUE/RETURN/PASS token:
     // the first three don't exist at top-level, and the last is a no-op.
-    new Eval(env).exec(stmt);
+    new Eval(thread).exec(stmt);
   }
 
-  private Eval(Environment env) {
-    this.env = env;
+  private Eval(StarlarkThread thread) {
+    this.thread = thread;
     this.dbg = debugger.get(); // capture value and use for lifetime of one Eval
   }
 
   private void execAssignment(AssignmentStatement node) throws EvalException, InterruptedException {
-    Object rvalue = eval(env, node.getRHS());
-    assign(node.getLHS(), rvalue, env, node.getLocation());
+    Object rvalue = eval(thread, node.getRHS());
+    assign(node.getLHS(), rvalue, thread, node.getLocation());
   }
 
   private TokenKind execFor(ForStatement node) throws EvalException, InterruptedException {
-    Object o = eval(env, node.getCollection());
-    Iterable<?> col = EvalUtils.toIterable(o, node.getLocation(), env);
+    Object o = eval(thread, node.getCollection());
+    Iterable<?> col = EvalUtils.toIterable(o, node.getLocation(), thread);
     EvalUtils.lock(o, node.getLocation());
     try {
       for (Object it : col) {
-        assign(node.getLHS(), it, env, node.getLocation());
+        assign(node.getLHS(), it, thread, node.getLocation());
 
         switch (execStatementsInternal(node.getBlock())) {
           case PASS:
@@ -109,7 +109,7 @@
     if (defaultExpressions != null) {
       defaultValues = new ArrayList<>(defaultExpressions.size());
       for (Expression expr : defaultExpressions) {
-        defaultValues.add(eval(env, expr));
+        defaultValues.add(eval(thread, expr));
       }
     }
 
@@ -119,18 +119,18 @@
       throw new EvalException(node.getLocation(), "Keyword-only argument is forbidden.");
     }
 
-    env.updateAndExport(
+    thread.updateAndExport(
         node.getIdentifier().getName(),
         new StarlarkFunction(
             node.getIdentifier().getName(),
             node.getIdentifier().getLocation(),
             FunctionSignature.WithValues.create(sig, defaultValues, /*types=*/ null),
             node.getStatements(),
-            env.getGlobals()));
+            thread.getGlobals()));
   }
 
   private TokenKind execIf(IfStatement node) throws EvalException, InterruptedException {
-    boolean cond = EvalUtils.toBoolean(eval(env, node.getCondition()));
+    boolean cond = EvalUtils.toBoolean(eval(thread, node.getCondition()));
     if (cond) {
       return execStatementsInternal(node.getThenBlock());
     } else if (node.getElseBlock() != null) {
@@ -152,8 +152,8 @@
         }
         // The key is the original name that was used to define the symbol
         // in the loaded bzl file.
-        env.importSymbol(node.getImport().getValue(), name, declared.getName());
-      } catch (Environment.LoadFailedException e) {
+        thread.importSymbol(node.getImport().getValue(), name, declared.getName());
+      } catch (StarlarkThread.LoadFailedException e) {
         throw new EvalException(node.getLocation(), e.getMessage());
       }
     }
@@ -162,14 +162,14 @@
   private TokenKind execReturn(ReturnStatement node) throws EvalException, InterruptedException {
     Expression ret = node.getReturnExpression();
     if (ret != null) {
-      this.result = eval(env, ret);
+      this.result = eval(thread, ret);
     }
     return TokenKind.RETURN;
   }
 
   private TokenKind exec(Statement st) throws EvalException, InterruptedException {
     if (dbg != null) {
-      dbg.before(env, st.getLocation());
+      dbg.before(thread, st.getLocation());
     }
 
     try {
@@ -188,7 +188,7 @@
         execAugmentedAssignment((AugmentedAssignmentStatement) st);
         return TokenKind.PASS;
       case EXPRESSION:
-        eval(env, ((ExpressionStatement) st).getExpression());
+        eval(thread, ((ExpressionStatement) st).getExpression());
         return TokenKind.PASS;
       case FLOW:
         return ((FlowStatement) st).getKind();
@@ -224,17 +224,17 @@
    * Updates the environment bindings, and possibly mutates objects, so as to assign the given value
    * to the given expression. The expression must be valid for an {@code LValue}.
    */
-  private static void assign(Expression expr, Object value, Environment env, Location loc)
+  private static void assign(Expression expr, Object value, StarlarkThread thread, Location loc)
       throws EvalException, InterruptedException {
     if (expr instanceof Identifier) {
-      assignIdentifier((Identifier) expr, value, env);
+      assignIdentifier((Identifier) expr, value, thread);
     } else if (expr instanceof IndexExpression) {
-      Object object = eval(env, ((IndexExpression) expr).getObject());
-      Object key = eval(env, ((IndexExpression) expr).getKey());
-      assignItem(object, key, value, env, loc);
+      Object object = eval(thread, ((IndexExpression) expr).getObject());
+      Object key = eval(thread, ((IndexExpression) expr).getKey());
+      assignItem(object, key, value, thread, loc);
     } else if (expr instanceof ListExpression) {
       ListExpression list = (ListExpression) expr;
-      assignList(list, value, env, loc);
+      assignList(list, value, thread, loc);
     } else {
       // Not possible for validated ASTs.
       throw new EvalException(loc, "cannot assign to '" + expr + "'");
@@ -242,9 +242,9 @@
   }
 
   /** Binds a variable to the given value in the environment. */
-  private static void assignIdentifier(Identifier ident, Object value, Environment env)
+  private static void assignIdentifier(Identifier ident, Object value, StarlarkThread thread)
       throws EvalException {
-    env.updateAndExport(ident.getName(), value);
+    thread.updateAndExport(ident.getName(), value);
   }
 
   /**
@@ -256,14 +256,15 @@
    */
   @SuppressWarnings("unchecked")
   private static void assignItem(
-      Object object, Object key, Object value, Environment env, Location loc) throws EvalException {
+      Object object, Object key, Object value, StarlarkThread thread, Location loc)
+      throws EvalException {
     if (object instanceof SkylarkDict) {
       SkylarkDict<Object, Object> dict = (SkylarkDict<Object, Object>) object;
-      dict.put(key, value, loc, env);
+      dict.put(key, value, loc, thread);
     } else if (object instanceof SkylarkList.MutableList) {
       SkylarkList.MutableList<Object> list = (SkylarkList.MutableList<Object>) object;
       int index = EvalUtils.getSequenceIndex(key, list.size(), loc);
-      list.set(index, value, loc, env.mutability());
+      list.set(index, value, loc, thread.mutability());
     } else {
       throw new EvalException(
           loc,
@@ -279,9 +280,10 @@
    * @throws EvalException if the list literal has length 0, or if the value is not an iterable of
    *     matching length
    */
-  private static void assignList(ListExpression list, Object value, Environment env, Location loc)
+  private static void assignList(
+      ListExpression list, Object value, StarlarkThread thread, Location loc)
       throws EvalException, InterruptedException {
-    Collection<?> collection = EvalUtils.toCollection(value, loc, env);
+    Collection<?> collection = EvalUtils.toCollection(value, loc, thread);
     int len = list.getElements().size();
     if (len == 0) {
       throw new EvalException(
@@ -297,7 +299,7 @@
     }
     int i = 0;
     for (Object item : collection) {
-      assign(list.getElements().get(i), item, env, loc);
+      assign(list.getElements().get(i), item, thread, loc);
       i++;
     }
   }
@@ -319,21 +321,21 @@
     Location loc = stmt.getLocation();
 
     if (lhs instanceof Identifier) {
-      Object x = eval(env, lhs);
-      Object y = eval(env, rhs);
-      Object z = inplaceBinaryOp(op, x, y, env, loc);
-      assignIdentifier((Identifier) lhs, z, env);
+      Object x = eval(thread, lhs);
+      Object y = eval(thread, rhs);
+      Object z = inplaceBinaryOp(op, x, y, thread, loc);
+      assignIdentifier((Identifier) lhs, z, thread);
     } else if (lhs instanceof IndexExpression) {
       // object[index] op= y
       // The object and key should be evaluated only once, so we don't use lhs.eval().
       IndexExpression index = (IndexExpression) lhs;
-      Object object = eval(env, index.getObject());
-      Object key = eval(env, index.getKey());
-      Object x = EvalUtils.index(object, key, env, loc);
+      Object object = eval(thread, index.getObject());
+      Object key = eval(thread, index.getKey());
+      Object x = EvalUtils.index(object, key, thread, loc);
       // Evaluate rhs after lhs.
-      Object y = eval(env, rhs);
-      Object z = inplaceBinaryOp(op, x, y, env, loc);
-      assignItem(object, key, z, env, loc);
+      Object y = eval(thread, rhs);
+      Object z = inplaceBinaryOp(op, x, y, thread, loc);
+      assignItem(object, key, z, thread, loc);
     } else if (lhs instanceof ListExpression) {
       throw new EvalException(loc, "cannot perform augmented assignment on a list literal");
     } else {
@@ -343,7 +345,7 @@
   }
 
   private static Object inplaceBinaryOp(
-      TokenKind op, Object x, Object y, Environment env, Location location)
+      TokenKind op, Object x, Object y, StarlarkThread thread, Location location)
       throws EvalException, InterruptedException {
     // list += iterable  behaves like  list.extend(iterable)
     // TODO(b/141263526): following Python, allow list+=iterable (but not list+iterable).
@@ -351,10 +353,10 @@
         && x instanceof SkylarkList.MutableList
         && y instanceof SkylarkList.MutableList) {
       SkylarkList.MutableList<?> list = (SkylarkList.MutableList) x;
-      list.extend(y, location, env);
+      list.extend(y, location, thread);
       return list;
     }
-    return EvalUtils.binaryOp(op, x, y, env, location);
+    return EvalUtils.binaryOp(op, x, y, thread, location);
   }
 
   // ---- expressions ----
@@ -378,17 +380,18 @@
    * @throws EvalException if the expression could not be evaluated.
    * @throws InterruptedException may be thrown in a sub class.
    */
-  static Object eval(Environment env, Expression expr) throws EvalException, InterruptedException {
+  static Object eval(StarlarkThread thread, Expression expr)
+      throws EvalException, InterruptedException {
     // TODO(adonovan): don't push and pop all the time. We should only need the stack of function
     // call frames, and we should recycle them.
-    // TODO(adonovan): put the Environment (Starlark thread) into the Java thread-local store
+    // TODO(adonovan): put the StarlarkThread (Starlark thread) into the Java thread-local store
     // once only, in enterScope, and undo this in exitScope.
     try {
       if (Callstack.enabled) {
         Callstack.push(expr);
       }
       try {
-        return doEval(env, expr);
+        return doEval(thread, expr);
       } catch (EvalException ex) {
         throw maybeTransformException(expr, ex);
       }
@@ -399,45 +402,45 @@
     }
   }
 
-  private static Object doEval(Environment env, Expression expr)
+  private static Object doEval(StarlarkThread thread, Expression expr)
       throws EvalException, InterruptedException {
     switch (expr.kind()) {
       case BINARY_OPERATOR:
         {
           BinaryOperatorExpression binop = (BinaryOperatorExpression) expr;
-          Object x = eval(env, binop.getX());
+          Object x = eval(thread, binop.getX());
           // AND and OR require short-circuit evaluation.
           switch (binop.getOperator()) {
             case AND:
-              return EvalUtils.toBoolean(x) ? Eval.eval(env, binop.getY()) : x;
+              return EvalUtils.toBoolean(x) ? Eval.eval(thread, binop.getY()) : x;
             case OR:
-              return EvalUtils.toBoolean(x) ? x : Eval.eval(env, binop.getY());
+              return EvalUtils.toBoolean(x) ? x : Eval.eval(thread, binop.getY());
             default:
-              Object y = eval(env, binop.getY());
-              return EvalUtils.binaryOp(binop.getOperator(), x, y, env, binop.getLocation());
+              Object y = eval(thread, binop.getY());
+              return EvalUtils.binaryOp(binop.getOperator(), x, y, thread, binop.getLocation());
           }
         }
 
       case COMPREHENSION:
-        return evalComprehension(env, (Comprehension) expr);
+        return evalComprehension(thread, (Comprehension) expr);
 
       case CONDITIONAL:
         {
           ConditionalExpression cond = (ConditionalExpression) expr;
-          Object v = eval(env, cond.getCondition());
-          return eval(env, EvalUtils.toBoolean(v) ? cond.getThenCase() : cond.getElseCase());
+          Object v = eval(thread, cond.getCondition());
+          return eval(thread, EvalUtils.toBoolean(v) ? cond.getThenCase() : cond.getElseCase());
         }
 
       case DICT_EXPR:
         {
           DictExpression dictexpr = (DictExpression) expr;
-          SkylarkDict<Object, Object> dict = SkylarkDict.of(env);
+          SkylarkDict<Object, Object> dict = SkylarkDict.of(thread);
           Location loc = dictexpr.getLocation();
           for (DictExpression.Entry entry : dictexpr.getEntries()) {
-            Object k = eval(env, entry.getKey());
-            Object v = eval(env, entry.getValue());
+            Object k = eval(thread, entry.getKey());
+            Object v = eval(thread, entry.getValue());
             int before = dict.size();
-            dict.put(k, v, loc, env);
+            dict.put(k, v, loc, thread);
             if (dict.size() == before) {
               throw new EvalException(
                   loc, "Duplicated key " + Printer.repr(k) + " when creating dictionary");
@@ -449,10 +452,10 @@
       case DOT:
         {
           DotExpression dot = (DotExpression) expr;
-          Object object = eval(env, dot.getObject());
+          Object object = eval(thread, dot.getObject());
           String name = dot.getField().getName();
-          Object result = EvalUtils.getAttr(env, dot.getLocation(), object, name);
-          return checkResult(object, result, name, dot.getLocation(), env.getSemantics());
+          Object result = EvalUtils.getAttr(thread, dot.getLocation(), object, name);
+          return checkResult(object, result, name, dot.getLocation(), thread.getSemantics());
         }
 
       case FUNCALL:
@@ -466,15 +469,15 @@
           // a closure for x.f if f is a Java method.
           if (call.getFunction() instanceof DotExpression) {
             DotExpression dot = (DotExpression) call.getFunction();
-            Object object = Eval.eval(env, dot.getObject());
-            evalArguments(env, call, posargs, kwargs);
+            Object object = Eval.eval(thread, dot.getObject());
+            evalArguments(thread, call, posargs, kwargs);
             return CallUtils.callMethod(
-                env, call, object, posargs, kwargs, dot.getField().getName(), dot.getLocation());
+                thread, call, object, posargs, kwargs, dot.getField().getName(), dot.getLocation());
           }
 
-          Object fn = Eval.eval(env, call.getFunction());
-          evalArguments(env, call, posargs, kwargs);
-          return CallUtils.call(env, call, fn, posargs, kwargs);
+          Object fn = Eval.eval(thread, call.getFunction());
+          evalArguments(thread, call, posargs, kwargs);
+          return CallUtils.call(thread, call, fn, posargs, kwargs);
         }
 
       case IDENTIFIER:
@@ -483,9 +486,9 @@
           String name = id.getName();
           if (id.getScope() == null) {
             // Legacy behavior, to be removed.
-            Object result = env.lookup(name);
+            Object result = thread.lookup(name);
             if (result == null) {
-              throw createInvalidIdentifierException(id, env.getVariableNames());
+              throw createInvalidIdentifierException(id, thread.getVariableNames());
             }
             return result;
           }
@@ -493,13 +496,13 @@
           Object result;
           switch (id.getScope()) {
             case Local:
-              result = env.localLookup(name);
+              result = thread.localLookup(name);
               break;
             case Module:
-              result = env.moduleLookup(name);
+              result = thread.moduleLookup(name);
               break;
             case Universe:
-              result = env.universeLookup(name);
+              result = thread.universeLookup(name);
               break;
             default:
               throw new IllegalStateException(id.getScope().toString());
@@ -523,9 +526,9 @@
       case INDEX:
         {
           IndexExpression index = (IndexExpression) expr;
-          Object object = eval(env, index.getObject());
-          Object key = eval(env, index.getKey());
-          return EvalUtils.index(object, key, env, index.getLocation());
+          Object object = eval(thread, index.getObject());
+          Object key = eval(thread, index.getKey());
+          return EvalUtils.index(object, key, thread, index.getLocation());
         }
 
       case INTEGER_LITERAL:
@@ -536,26 +539,26 @@
           ListExpression list = (ListExpression) expr;
           ArrayList<Object> result = new ArrayList<>(list.getElements().size());
           for (Expression elem : list.getElements()) {
-            result.add(eval(env, elem));
+            result.add(eval(thread, elem));
           }
           return list.isTuple()
               ? SkylarkList.Tuple.copyOf(result) // TODO(adonovan): opt: avoid copy
-              : SkylarkList.MutableList.wrapUnsafe(env, result);
+              : SkylarkList.MutableList.wrapUnsafe(thread, result);
         }
 
       case SLICE:
         {
           SliceExpression slice = (SliceExpression) expr;
-          Object object = eval(env, slice.getObject());
-          Object start = slice.getStart() == null ? Runtime.NONE : eval(env, slice.getStart());
-          Object end = slice.getEnd() == null ? Runtime.NONE : eval(env, slice.getEnd());
-          Object step = slice.getStep() == null ? Runtime.NONE : eval(env, slice.getStep());
+          Object object = eval(thread, slice.getObject());
+          Object start = slice.getStart() == null ? Runtime.NONE : eval(thread, slice.getStart());
+          Object end = slice.getEnd() == null ? Runtime.NONE : eval(thread, slice.getEnd());
+          Object step = slice.getStep() == null ? Runtime.NONE : eval(thread, slice.getStep());
           Location loc = slice.getLocation();
 
           // TODO(adonovan): move the rest into a public EvalUtils.slice() operator.
 
           if (object instanceof SkylarkList) {
-            return ((SkylarkList<?>) object).getSlice(start, end, step, loc, env.mutability());
+            return ((SkylarkList<?>) object).getSlice(start, end, step, loc, thread.mutability());
           }
 
           if (object instanceof String) {
@@ -589,7 +592,7 @@
       case UNARY_OPERATOR:
         {
           UnaryOperatorExpression unop = (UnaryOperatorExpression) expr;
-          Object x = eval(env, unop.getX());
+          Object x = eval(thread, unop.getX());
           return EvalUtils.unaryOp(unop.getOperator(), x, unop.getLocation());
         }
     }
@@ -630,9 +633,9 @@
         id.getLocation(), "name '" + id.getName() + "' is not defined" + suggestion);
   }
 
-  private static Object evalComprehension(Environment env, Comprehension comp)
+  private static Object evalComprehension(StarlarkThread thread, Comprehension comp)
       throws EvalException, InterruptedException {
-    final SkylarkDict<Object, Object> dict = comp.isDict() ? SkylarkDict.of(env) : null;
+    final SkylarkDict<Object, Object> dict = comp.isDict() ? SkylarkDict.of(thread) : null;
     final ArrayList<Object> list = comp.isDict() ? null : new ArrayList<>();
 
     // The Lambda class serves as a recursive lambda closure.
@@ -646,13 +649,13 @@
           if (clause instanceof Comprehension.For) {
             Comprehension.For forClause = (Comprehension.For) clause;
 
-            Object iterable = eval(env, forClause.getIterable());
+            Object iterable = eval(thread, forClause.getIterable());
             Location loc = comp.getLocation();
-            Iterable<?> listValue = EvalUtils.toIterable(iterable, loc, env);
+            Iterable<?> listValue = EvalUtils.toIterable(iterable, loc, thread);
             EvalUtils.lock(iterable, loc);
             try {
               for (Object elem : listValue) {
-                Eval.assign(forClause.getVars(), elem, env, loc);
+                Eval.assign(forClause.getVars(), elem, thread, loc);
                 execClauses(index + 1);
               }
             } finally {
@@ -661,7 +664,7 @@
 
           } else {
             Comprehension.If ifClause = (Comprehension.If) clause;
-            if (EvalUtils.toBoolean(eval(env, ifClause.getCondition()))) {
+            if (EvalUtils.toBoolean(eval(thread, ifClause.getCondition()))) {
               execClauses(index + 1);
             }
           }
@@ -671,12 +674,12 @@
         // base case: evaluate body and add to result.
         if (dict != null) {
           DictExpression.Entry body = (DictExpression.Entry) comp.getBody();
-          Object k = eval(env, body.getKey());
-          EvalUtils.checkValidDictKey(k, env);
-          Object v = eval(env, body.getValue());
-          dict.put(k, v, comp.getLocation(), env);
+          Object k = eval(thread, body.getKey());
+          EvalUtils.checkValidDictKey(k, thread);
+          Object v = eval(thread, body.getValue());
+          dict.put(k, v, comp.getLocation(), thread);
         } else {
-          list.add(eval(env, ((Expression) comp.getBody())));
+          list.add(eval(thread, ((Expression) comp.getBody())));
         }
       }
     }
@@ -691,12 +694,12 @@
       if (clause instanceof Comprehension.For) {
         for (Identifier ident :
             Identifier.boundIdentifiers(((Comprehension.For) clause).getVars())) {
-          env.removeLocalBinding(ident.getName());
+          thread.removeLocalBinding(ident.getName());
         }
       }
     }
 
-    return comp.isDict() ? dict : SkylarkList.MutableList.copyOf(env, list);
+    return comp.isDict() ? dict : SkylarkList.MutableList.copyOf(thread, list);
   }
 
   /** Returns an exception which should be thrown instead of the original one. */
@@ -775,11 +778,14 @@
    * @param posargs a list to which all positional arguments will be added
    * @param kwargs a mutable map to which all keyword arguments will be added. A mutable map is used
    *     here instead of an immutable map builder to deal with duplicates without memory overhead
-   * @param env the current environment
+   * @param thread the Starlark thread for the call
    */
   @SuppressWarnings("unchecked")
   private static void evalArguments(
-      Environment env, FuncallExpression call, List<Object> posargs, Map<String, Object> kwargs)
+      StarlarkThread thread,
+      FuncallExpression call,
+      List<Object> posargs,
+      Map<String, Object> kwargs)
       throws EvalException, InterruptedException {
 
     // Optimize allocations for the common case where they are no duplicates.
@@ -792,7 +798,7 @@
     // (O(1) for ImmutableList) to avoid the iterator overhead.
     for (int i = 0; i < call.getArguments().size(); i++) {
       Argument.Passed arg = call.getArguments().get(i);
-      Object value = Eval.eval(env, arg.getValue());
+      Object value = Eval.eval(thread, arg.getValue());
       if (arg.isPositional()) {
         posargs.add(value);
       } else if (arg.isStar()) { // expand the starArg
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/EvalUtils.java b/src/main/java/com/google/devtools/build/lib/syntax/EvalUtils.java
index 77760dd..8c99b36 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/EvalUtils.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/EvalUtils.java
@@ -92,8 +92,8 @@
             return Integer.compare((Integer) o1, (Integer) o2);
           }
 
-          o1 = SkylarkType.convertToSkylark(o1, (Environment) null);
-          o2 = SkylarkType.convertToSkylark(o2, (Environment) null);
+          o1 = SkylarkType.convertToSkylark(o1, (StarlarkThread) null);
+          o2 = SkylarkType.convertToSkylark(o2, (StarlarkThread) null);
 
           if (o1 instanceof SkylarkList
               && o2 instanceof SkylarkList
@@ -122,9 +122,9 @@
    * @param o an Object to validate
    * @throws EvalException if o is not a valid key
    */
-  public static void checkValidDictKey(Object o, Environment env) throws EvalException {
+  public static void checkValidDictKey(Object o, StarlarkThread thread) throws EvalException {
     // TODO(bazel-team): check that all recursive elements are both Immutable AND Comparable.
-    if (env != null && env.getSemantics().incompatibleDisallowHashingFrozenMutables()) {
+    if (thread != null && thread.getSemantics().incompatibleDisallowHashingFrozenMutables()) {
       if (isHashable(o)) {
         return;
       }
@@ -342,7 +342,7 @@
     }
   }
 
-  public static Collection<?> toCollection(Object o, Location loc, @Nullable Environment env)
+  public static Collection<?> toCollection(Object o, Location loc, @Nullable StarlarkThread thread)
       throws EvalException {
     if (o instanceof Collection) {
       return (Collection<?>) o;
@@ -366,7 +366,7 @@
         throw new EvalException(loc, e);
       }
     } else if (o instanceof SkylarkNestedSet) {
-      return nestedSetToCollection((SkylarkNestedSet) o, loc, env);
+      return nestedSetToCollection((SkylarkNestedSet) o, loc, thread);
     } else {
       throw new EvalException(loc,
           "type '" + getDataTypeName(o) + "' is not a collection");
@@ -374,8 +374,8 @@
   }
 
   private static Collection<?> nestedSetToCollection(
-      SkylarkNestedSet set, Location loc, @Nullable Environment env) throws EvalException {
-    if (env != null && env.getSemantics().incompatibleDepsetIsNotIterable()) {
+      SkylarkNestedSet set, Location loc, @Nullable StarlarkThread thread) throws EvalException {
+    if (thread != null && thread.getSemantics().incompatibleDepsetIsNotIterable()) {
       throw new EvalException(
           loc,
           "type 'depset' is not iterable. Use the `to_list()` method to get a list. Use "
@@ -395,14 +395,14 @@
     }
   }
 
-  public static Iterable<?> toIterable(Object o, Location loc, @Nullable Environment env)
+  public static Iterable<?> toIterable(Object o, Location loc, @Nullable StarlarkThread thread)
       throws EvalException {
     if (o instanceof SkylarkNestedSet) {
-      return nestedSetToCollection((SkylarkNestedSet) o, loc, env);
+      return nestedSetToCollection((SkylarkNestedSet) o, loc, thread);
     } else if (o instanceof Iterable) {
       return (Iterable<?>) o;
     } else if (o instanceof Map) {
-      return toCollection(o, loc, env);
+      return toCollection(o, loc, thread);
     } else {
       throw new EvalException(loc,
           "type '" + getDataTypeName(o) + "' is not iterable");
@@ -424,12 +424,12 @@
    *     is no longer supported.
    */
   @Deprecated
-  public static Iterable<?> toIterableStrict(Object o, Location loc, @Nullable Environment env)
-      throws EvalException {
+  public static Iterable<?> toIterableStrict(
+      Object o, Location loc, @Nullable StarlarkThread thread) throws EvalException {
     if (o instanceof Iterable) {
       return (Iterable<?>) o;
     } else if (o instanceof SkylarkNestedSet) {
-      return nestedSetToCollection((SkylarkNestedSet) o, loc, env);
+      return nestedSetToCollection((SkylarkNestedSet) o, loc, thread);
     } else {
       throw new EvalException(loc,
           "expected Iterable or depset, but got '" + getDataTypeName(o) + "' (strings and maps "
@@ -582,19 +582,15 @@
   /**
    * Build a SkylarkDict of kwarg arguments from a list, removing null-s or None-s.
    *
-   * @param env the Environment in which this map can be mutated.
-   * @param init a series of key, value pairs (as consecutive arguments)
-   *   as in {@code optionMap(k1, v1, k2, v2, k3, v3)}
-   *   where each key is a String, each value is an arbitrary Objet.
-   * @return a {@code Map<String, Object>} that has all the specified entries,
-   *   where key, value pairs appearing earlier have precedence,
-   *   i.e. {@code k1, v1} may override {@code k3, v3}.
-   *
-   * Ignore any entry where the value is null or None.
-   * Keys cannot be null.
+   * @param thread the StarlarkThread in which this map can be mutated.
+   * @param init a series of key, value pairs (as consecutive arguments) as in {@code optionMap(k1,
+   *     v1, k2, v2, k3, v3)} where each key is a String, each value is an arbitrary Objet.
+   * @return a {@code Map<String, Object>} that has all the specified entries, where key, value
+   *     pairs appearing earlier have precedence, i.e. {@code k1, v1} may override {@code k3, v3}.
+   *     <p>Ignore any entry where the value is null or None. Keys cannot be null.
    */
   @SuppressWarnings("unchecked")
-  public static <K, V> SkylarkDict<K, V> optionMap(Environment env, Object... init) {
+  public static <K, V> SkylarkDict<K, V> optionMap(StarlarkThread thread, Object... init) {
     ImmutableMap.Builder<K, V> b = new ImmutableMap.Builder<>();
     Preconditions.checkState(init.length % 2 == 0);
     for (int i = init.length - 2; i >= 0; i -= 2) {
@@ -604,7 +600,7 @@
         b.put(key, value);
       }
     }
-    return SkylarkDict.copyOf(env, b.build());
+    return SkylarkDict.copyOf(thread, b.build());
   }
 
   /**
@@ -617,23 +613,23 @@
   }
 
   /** Returns the named field or method of the specified object. */
-  static Object getAttr(Environment env, Location loc, Object object, String name)
+  static Object getAttr(StarlarkThread thread, Location loc, Object object, String name)
       throws EvalException, InterruptedException {
     MethodDescriptor method =
         object instanceof Class<?>
-            ? CallUtils.getMethod(env.getSemantics(), (Class<?>) object, name)
-            : CallUtils.getMethod(env.getSemantics(), object.getClass(), name);
+            ? CallUtils.getMethod(thread.getSemantics(), (Class<?>) object, name)
+            : CallUtils.getMethod(thread.getSemantics(), object.getClass(), name);
     if (method != null && method.isStructField()) {
       return method.call(
           object,
-          CallUtils.extraInterpreterArgs(method, /*ast=*/ null, loc, env).toArray(),
+          CallUtils.extraInterpreterArgs(method, /*ast=*/ null, loc, thread).toArray(),
           loc,
-          env);
+          thread);
     }
 
     if (object instanceof SkylarkClassObject) {
       try {
-        return ((SkylarkClassObject) object).getValue(loc, env.getSemantics(), name);
+        return ((SkylarkClassObject) object).getValue(loc, thread.getSemantics(), name);
       } catch (IllegalArgumentException ex) { // TODO(adonovan): why necessary?
         throw new EvalException(loc, ex);
       }
@@ -649,7 +645,7 @@
       // ClassObjects may have fields that are annotated with @SkylarkCallable.
       // Since getValue() does not know about those, we cannot expect that result is a valid object.
       if (result != null) {
-        result = SkylarkType.convertToSkylark(result, env);
+        result = SkylarkType.convertToSkylark(result, thread);
         // If we access NestedSets using ClassObject.getValue() we won't know the generic type,
         // so we have to disable it. This should not happen.
         SkylarkType.checkTypeAllowedInSkylark(result, loc);
@@ -710,15 +706,15 @@
   }
 
   /** Evaluates an eager binary operation, {@code x op y}. (Excludes AND and OR.) */
-  static Object binaryOp(TokenKind op, Object x, Object y, Environment env, Location location)
+  static Object binaryOp(TokenKind op, Object x, Object y, StarlarkThread thread, Location location)
       throws EvalException, InterruptedException {
     try {
       switch (op) {
         case PLUS:
-          return plus(x, y, env, location);
+          return plus(x, y, thread, location);
 
         case PIPE:
-          return pipe(x, y, env, location);
+          return pipe(x, y, thread, location);
 
         case AMPERSAND:
           return and(x, y, location);
@@ -736,7 +732,7 @@
           return minus(x, y, location);
 
         case STAR:
-          return mult(x, y, env, location);
+          return mult(x, y, thread, location);
 
         case SLASH:
           throw new EvalException(
@@ -769,10 +765,10 @@
           return compare(x, y, location) >= 0;
 
         case IN:
-          return in(x, y, env, location);
+          return in(x, y, thread, location);
 
         case NOT_IN:
-          return !in(x, y, env, location);
+          return !in(x, y, thread, location);
 
         default:
           throw new AssertionError("Unsupported binary operator: " + op);
@@ -792,7 +788,8 @@
   }
 
   /** Implements 'x + y'. */
-  static Object plus(Object x, Object y, Environment env, Location location) throws EvalException {
+  static Object plus(Object x, Object y, StarlarkThread thread, Location location)
+      throws EvalException {
     // int + int
     if (x instanceof Integer && y instanceof Integer) {
       return Math.addExact((Integer) x, (Integer) y);
@@ -815,18 +812,18 @@
     }
 
     if (x instanceof MutableList && y instanceof MutableList) {
-      return MutableList.concat((MutableList<?>) x, (MutableList<?>) y, env.mutability());
+      return MutableList.concat((MutableList<?>) x, (MutableList<?>) y, thread.mutability());
     }
 
     if (x instanceof SkylarkDict && y instanceof SkylarkDict) {
-      if (env.getSemantics().incompatibleDisallowDictPlus()) {
+      if (thread.getSemantics().incompatibleDisallowDictPlus()) {
         throw new EvalException(
             location,
             "The `+` operator for dicts is deprecated and no longer supported. Please use the "
                 + "`update` method instead. You can temporarily enable the `+` operator by passing "
                 + "the flag --incompatible_disallow_dict_plus=false");
       }
-      return SkylarkDict.plus((SkylarkDict<?, ?>) x, (SkylarkDict<?, ?>) y, env);
+      return SkylarkDict.plus((SkylarkDict<?, ?>) x, (SkylarkDict<?, ?>) y, thread);
     }
 
     if (x instanceof Concatable && y instanceof Concatable) {
@@ -842,7 +839,7 @@
 
     // TODO(bazel-team): Remove deprecated operator.
     if (x instanceof SkylarkNestedSet) {
-      if (env.getSemantics().incompatibleDepsetUnion()) {
+      if (thread.getSemantics().incompatibleDepsetUnion()) {
         throw new EvalException(
             location,
             "`+` operator on a depset is forbidden. See "
@@ -856,12 +853,12 @@
   }
 
   /** Implements 'x | y'. */
-  private static Object pipe(Object x, Object y, Environment env, Location location)
+  private static Object pipe(Object x, Object y, StarlarkThread thread, Location location)
       throws EvalException {
     if (x instanceof Integer && y instanceof Integer) {
       return ((Integer) x) | ((Integer) y);
     } else if (x instanceof SkylarkNestedSet) {
-      if (env.getSemantics().incompatibleDepsetUnion()) {
+      if (thread.getSemantics().incompatibleDepsetUnion()) {
         throw new EvalException(
             location,
             "`|` operator on a depset is forbidden. See "
@@ -883,7 +880,7 @@
   }
 
   /** Implements 'x * y'. */
-  private static Object mult(Object x, Object y, Environment env, Location location)
+  private static Object mult(Object x, Object y, StarlarkThread thread, Location location)
       throws EvalException {
     Integer number = null;
     Object otherFactor = null;
@@ -904,7 +901,7 @@
         return Strings.repeat((String) otherFactor, Math.max(0, number));
       } else if (otherFactor instanceof SkylarkList && !(otherFactor instanceof RangeList)) {
         // Similar to Python, a factor < 1 leads to an empty string.
-        return ((SkylarkList<?>) otherFactor).repeat(number, env.mutability());
+        return ((SkylarkList<?>) otherFactor).repeat(number, thread.mutability());
       }
     }
     throw unknownBinaryOperator(x, y, TokenKind.STAR, location);
@@ -1006,9 +1003,9 @@
   }
 
   /** Implements 'x in y'. */
-  private static boolean in(Object x, Object y, Environment env, Location location)
+  private static boolean in(Object x, Object y, StarlarkThread thread, Location location)
       throws EvalException {
-    if (env.getSemantics().incompatibleDepsetIsNotIterable() && y instanceof SkylarkNestedSet) {
+    if (thread.getSemantics().incompatibleDepsetIsNotIterable() && y instanceof SkylarkNestedSet) {
       throw new EvalException(
           location,
           "argument of type '"
@@ -1018,7 +1015,7 @@
               + "Use --incompatible_depset_is_not_iterable=false to temporarily disable "
               + "this check.");
     } else if (y instanceof SkylarkQueryable) {
-      return ((SkylarkQueryable) y).containsKey(x, location, env);
+      return ((SkylarkQueryable) y).containsKey(x, location, thread);
     } else if (y instanceof String) {
       if (x instanceof String) {
         return ((String) y).contains((String) x);
@@ -1092,14 +1089,14 @@
    *
    * @throws EvalException if {@code object} is not a sequence or mapping.
    */
-  public static Object index(Object object, Object key, Environment env, Location loc)
+  public static Object index(Object object, Object key, StarlarkThread thread, Location loc)
       throws EvalException, InterruptedException {
     if (object instanceof SkylarkIndexable) {
       Object result = ((SkylarkIndexable) object).getIndex(key, loc);
       // TODO(bazel-team): We shouldn't have this convertToSkylark call here. If it's needed at all,
       // it should go in the implementations of SkylarkIndexable#getIndex that produce non-Skylark
       // values.
-      return SkylarkType.convertToSkylark(result, env);
+      return SkylarkType.convertToSkylark(result, thread);
     } else if (object instanceof String) {
       String string = (String) object;
       int index = getSequenceIndex(key, string.length(), loc);
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/MethodDescriptor.java b/src/main/java/com/google/devtools/build/lib/syntax/MethodDescriptor.java
index 8241b91..de6e0f9 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/MethodDescriptor.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/MethodDescriptor.java
@@ -47,7 +47,7 @@
   private final boolean allowReturnNones;
   private final boolean useLocation;
   private final boolean useAst;
-  private final boolean useEnvironment;
+  private final boolean useStarlarkThread;
   private final boolean useStarlarkSemantics;
 
   private MethodDescriptor(
@@ -64,7 +64,7 @@
       boolean allowReturnNones,
       boolean useLocation,
       boolean useAst,
-      boolean useEnvironment,
+      boolean useStarlarkThread,
       boolean useStarlarkSemantics) {
     this.method = method;
     this.annotation = annotation;
@@ -79,7 +79,7 @@
     this.allowReturnNones = allowReturnNones;
     this.useLocation = useLocation;
     this.useAst = useAst;
-    this.useEnvironment = useEnvironment;
+    this.useStarlarkThread = useStarlarkThread;
     this.useStarlarkSemantics = useStarlarkSemantics;
   }
 
@@ -110,7 +110,7 @@
         annotation.allowReturnNones(),
         annotation.useLocation(),
         annotation.useAst(),
-        annotation.useEnvironment(),
+        annotation.useStarlarkThread(),
         annotation.useStarlarkSemantics());
   }
 
@@ -120,7 +120,7 @@
    * <p>{@code obj} may be {@code null} in case this method is static. Methods with {@code void}
    * return type return {@code None} following Python convention.
    */
-  public Object call(Object obj, Object[] args, Location loc, Environment env)
+  public Object call(Object obj, Object[] args, Location loc, StarlarkThread thread)
       throws EvalException, InterruptedException {
     Preconditions.checkNotNull(obj);
     Object result;
@@ -160,7 +160,7 @@
       }
     }
     // TODO(bazel-team): get rid of this, by having everyone use the Skylark data structures
-    result = SkylarkType.convertToSkylark(result, method, env);
+    result = SkylarkType.convertToSkylark(result, method, thread);
     if (result != null && !EvalUtils.isSkylarkAcceptable(result.getClass())) {
       throw new EvalException(
           loc,
@@ -180,9 +180,9 @@
     return structField;
   }
 
-  /** @see SkylarkCallable#useEnvironment() */
-  public boolean isUseEnvironment() {
-    return useEnvironment;
+  /** @see SkylarkCallable#useStarlarkThread() */
+  public boolean isUseStarlarkThread() {
+    return useStarlarkThread;
   }
 
   /** @see SkylarkCallable#useStarlarkSemantics() */
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 b6575a7..04f6144 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
@@ -63,10 +63,10 @@
       extraPositionals =
           @Param(name = "args", type = SkylarkList.class, doc = "The elements to be checked."),
       useLocation = true,
-      useEnvironment = true)
-  public Object min(SkylarkList<?> args, Location loc, Environment env) throws EvalException {
+      useStarlarkThread = true)
+  public Object min(SkylarkList<?> args, Location loc, StarlarkThread thread) throws EvalException {
     try {
-      return findExtreme(args, EvalUtils.SKYLARK_COMPARATOR.reverse(), loc, env);
+      return findExtreme(args, EvalUtils.SKYLARK_COMPARATOR.reverse(), loc, thread);
     } catch (ComparisonException e) {
       throw new EvalException(loc, e);
     }
@@ -83,10 +83,10 @@
       extraPositionals =
           @Param(name = "args", type = SkylarkList.class, doc = "The elements to be checked."),
       useLocation = true,
-      useEnvironment = true)
-  public Object max(SkylarkList<?> args, Location loc, Environment env) throws EvalException {
+      useStarlarkThread = true)
+  public Object max(SkylarkList<?> args, Location loc, StarlarkThread thread) throws EvalException {
     try {
-      return findExtreme(args, EvalUtils.SKYLARK_COMPARATOR, loc, env);
+      return findExtreme(args, EvalUtils.SKYLARK_COMPARATOR, loc, thread);
     } catch (ComparisonException e) {
       throw new EvalException(loc, e);
     }
@@ -94,12 +94,13 @@
 
   /** Returns the maximum element from this list, as determined by maxOrdering. */
   private static Object findExtreme(
-      SkylarkList<?> args, Ordering<Object> maxOrdering, Location loc, Environment env)
+      SkylarkList<?> args, Ordering<Object> maxOrdering, Location loc, StarlarkThread thread)
       throws EvalException {
     // Args can either be a list of items to compare, or a singleton list whose element is an
     // iterable of items to compare. In either case, there must be at least one item to compare.
     try {
-      Iterable<?> items = (args.size() == 1) ? EvalUtils.toIterable(args.get(0), loc, env) : args;
+      Iterable<?> items =
+          (args.size() == 1) ? EvalUtils.toIterable(args.get(0), loc, thread) : args;
       return maxOrdering.max(items);
     } catch (NoSuchElementException ex) {
       throw new EvalException(loc, "expected at least one item", ex);
@@ -123,9 +124,9 @@
             legacyNamed = true)
       },
       useLocation = true,
-      useEnvironment = true)
-  public Boolean all(Object collection, Location loc, Environment env) throws EvalException {
-    return !hasElementWithBooleanValue(collection, false, loc, env);
+      useStarlarkThread = true)
+  public Boolean all(Object collection, Location loc, StarlarkThread thread) throws EvalException {
+    return !hasElementWithBooleanValue(collection, false, loc, thread);
   }
 
   @SkylarkCallable(
@@ -145,14 +146,14 @@
             legacyNamed = true)
       },
       useLocation = true,
-      useEnvironment = true)
-  public Boolean any(Object collection, Location loc, Environment env) throws EvalException {
-    return hasElementWithBooleanValue(collection, true, loc, env);
+      useStarlarkThread = true)
+  public Boolean any(Object collection, Location loc, StarlarkThread thread) throws EvalException {
+    return hasElementWithBooleanValue(collection, true, loc, thread);
   }
 
   private static boolean hasElementWithBooleanValue(
-      Object collection, boolean value, Location loc, Environment env) throws EvalException {
-    Iterable<?> iterable = EvalUtils.toIterable(collection, loc, env);
+      Object collection, boolean value, Location loc, StarlarkThread thread) throws EvalException {
+    Iterable<?> iterable = EvalUtils.toIterable(collection, loc, thread);
     for (Object obj : iterable) {
       if (EvalUtils.toBoolean(obj) == value) {
         return true;
@@ -192,12 +193,16 @@
             noneable = true)
       },
       useLocation = true,
-      useEnvironment = true)
+      useStarlarkThread = true)
   public MutableList<?> sorted(
-      Object self, final Object key, Boolean reverse, final Location loc, final Environment env)
+      Object self,
+      final Object key,
+      Boolean reverse,
+      final Location loc,
+      final StarlarkThread thread)
       throws EvalException, InterruptedException {
 
-    ArrayList list = new ArrayList(EvalUtils.toCollection(self, loc, env));
+    ArrayList list = new ArrayList(EvalUtils.toCollection(self, loc, thread));
     if (key == Runtime.NONE) {
       try {
         Collections.sort(list, EvalUtils.SKYLARK_COMPARATOR);
@@ -224,7 +229,7 @@
         }
 
         Object callKeyFunc(Object x) throws EvalException, InterruptedException {
-          return keyfn.call(Collections.singletonList(x), ImmutableMap.of(), ast, env);
+          return keyfn.call(Collections.singletonList(x), ImmutableMap.of(), ast, thread);
         }
       }
 
@@ -249,7 +254,7 @@
     if (reverse) {
       Collections.reverse(list);
     }
-    return MutableList.wrapUnsafe(env, list);
+    return MutableList.wrapUnsafe(thread, list);
   }
 
   @SkylarkCallable(
@@ -266,8 +271,8 @@
             legacyNamed = true),
       },
       useLocation = true,
-      useEnvironment = true)
-  public MutableList<?> reversed(Object sequence, Location loc, Environment env)
+      useStarlarkThread = true)
+  public MutableList<?> reversed(Object sequence, Location loc, StarlarkThread thread)
       throws EvalException {
     // We only allow lists and strings.
     if (sequence instanceof SkylarkDict) {
@@ -276,10 +281,10 @@
       throw new EvalException(loc, "Argument to reversed() must be a sequence, not a depset.");
     }
     ArrayDeque<Object> tmpList = new ArrayDeque<>();
-    for (Object element : EvalUtils.toIterable(sequence, loc, env)) {
+    for (Object element : EvalUtils.toIterable(sequence, loc, thread)) {
       tmpList.addFirst(element);
     }
-    return MutableList.copyOf(env, tmpList);
+    return MutableList.copyOf(thread, tmpList);
   }
 
   @SkylarkCallable(
@@ -298,9 +303,9 @@
             legacyNamed = true)
       },
       useLocation = true,
-      useEnvironment = true)
-  public Tuple<?> tuple(Object x, Location loc, Environment env) throws EvalException {
-    return Tuple.copyOf(EvalUtils.toCollection(x, loc, env));
+      useStarlarkThread = true)
+  public Tuple<?> tuple(Object x, Location loc, StarlarkThread thread) throws EvalException {
+    return Tuple.copyOf(EvalUtils.toCollection(x, loc, thread));
   }
 
   @SkylarkCallable(
@@ -319,9 +324,9 @@
             legacyNamed = true)
       },
       useLocation = true,
-      useEnvironment = true)
-  public MutableList<?> list(Object x, Location loc, Environment env) throws EvalException {
-    return MutableList.copyOf(env, EvalUtils.toCollection(x, loc, env));
+      useStarlarkThread = true)
+  public MutableList<?> list(Object x, Location loc, StarlarkThread thread) throws EvalException {
+    return MutableList.copyOf(thread, EvalUtils.toCollection(x, loc, thread));
   }
 
   @SkylarkCallable(
@@ -335,8 +340,8 @@
             legacyNamed = true)
       },
       useLocation = true,
-      useEnvironment = true)
-  public Integer len(Object x, Location loc, Environment env) throws EvalException {
+      useStarlarkThread = true)
+  public Integer len(Object x, Location loc, StarlarkThread thread) throws EvalException {
     if (x instanceof String) {
       return ((String) x).length();
     } else if (x instanceof Map) {
@@ -344,7 +349,7 @@
     } else if (x instanceof SkylarkList) {
       return ((SkylarkList<?>) x).size();
     } else if (x instanceof SkylarkNestedSet) {
-      if (env.getSemantics().incompatibleDepsetIsNotIterable()) {
+      if (thread.getSemantics().incompatibleDepsetIsNotIterable()) {
         throw new EvalException(
             loc,
             EvalUtils.getDataTypeName(x)
@@ -605,14 +610,15 @@
       },
       extraKeywords = @Param(name = "kwargs", doc = "Dictionary of additional entries."),
       useLocation = true,
-      useEnvironment = true)
+      useStarlarkThread = true)
   public SkylarkDict<?, ?> dict(
-      Object args, SkylarkDict<?, ?> kwargs, Location loc, Environment env) throws EvalException {
+      Object args, SkylarkDict<?, ?> kwargs, Location loc, StarlarkThread thread)
+      throws EvalException {
     SkylarkDict<?, ?> argsDict =
         args instanceof SkylarkDict
             ? (SkylarkDict) args
-            : SkylarkDict.getDictFromArgs("dict", args, loc, env);
-    return SkylarkDict.plus(argsDict, kwargs, env);
+            : SkylarkDict.getDictFromArgs("dict", args, loc, thread);
+    return SkylarkDict.plus(argsDict, kwargs, thread);
   }
 
   @SkylarkCallable(
@@ -632,17 +638,17 @@
             defaultValue = "0",
             named = true)
       },
-      useEnvironment = true,
+      useStarlarkThread = true,
       useLocation = true)
-  public MutableList<?> enumerate(Object input, Integer start, Location loc, Environment env)
+  public MutableList<?> enumerate(Object input, Integer start, Location loc, StarlarkThread thread)
       throws EvalException {
     int count = start;
     ArrayList<SkylarkList<?>> result = new ArrayList<>();
-    for (Object obj : EvalUtils.toCollection(input, loc, env)) {
+    for (Object obj : EvalUtils.toCollection(input, loc, thread)) {
       result.add(Tuple.of(count, obj));
       count++;
     }
-    return MutableList.wrapUnsafe(env, result);
+    return MutableList.wrapUnsafe(thread, result);
   }
 
   @SkylarkCallable(
@@ -704,9 +710,9 @@
             legacyNamed = true)
       },
       useLocation = true,
-      useEnvironment = true)
+      useStarlarkThread = true)
   public SkylarkList<Integer> range(
-      Integer startOrStop, Object stopOrNone, Integer step, Location loc, Environment env)
+      Integer startOrStop, Object stopOrNone, Integer step, Location loc, StarlarkThread thread)
       throws EvalException {
     int start;
     int stop;
@@ -746,13 +752,13 @@
             // TODO(cparsons): This parameter should be positional-only.
             legacyNamed = true)
       },
-      useEnvironment = true)
-  public Boolean hasAttr(Object obj, String name, Environment env) throws EvalException {
+      useStarlarkThread = true)
+  public Boolean hasAttr(Object obj, String name, StarlarkThread thread) throws EvalException {
     if (obj instanceof ClassObject && ((ClassObject) obj).getValue(name) != null) {
       return true;
     }
     // shouldn't this filter things with struct_field = false?
-    return EvalUtils.hasMethod(env.getSemantics(), obj, name);
+    return EvalUtils.hasMethod(thread.getSemantics(), obj, name);
   }
 
   @SkylarkCallable(
@@ -786,15 +792,16 @@
             noneable = true)
       },
       useLocation = true,
-      useEnvironment = true)
-  public Object getAttr(Object obj, String name, Object defaultValue, Location loc, Environment env)
+      useStarlarkThread = true)
+  public Object getAttr(
+      Object obj, String name, Object defaultValue, Location loc, StarlarkThread thread)
       throws EvalException, InterruptedException {
-    Object result = EvalUtils.getAttr(env, loc, obj, name);
+    Object result = EvalUtils.getAttr(thread, loc, obj, name);
     if (result == null) {
       if (defaultValue != Runtime.UNBOUND) {
         return defaultValue;
       }
-      throw EvalUtils.getMissingFieldException(obj, name, loc, env.getSemantics(), "attribute");
+      throw EvalUtils.getMissingFieldException(obj, name, loc, thread.getSemantics(), "attribute");
     }
     return result;
   }
@@ -813,16 +820,17 @@
             noneable = true)
       },
       useLocation = true,
-      useEnvironment = true)
-  public MutableList<?> dir(Object object, Location loc, Environment env) throws EvalException {
+      useStarlarkThread = true)
+  public MutableList<?> dir(Object object, Location loc, StarlarkThread thread)
+      throws EvalException {
     // Order the fields alphabetically.
     Set<String> fields = new TreeSet<>();
     if (object instanceof ClassObject) {
       fields.addAll(((ClassObject) object).getFieldNames());
     }
     fields.addAll(Runtime.getBuiltinRegistry().getFunctionNames(object.getClass()));
-    fields.addAll(CallUtils.getMethodNames(env.getSemantics(), object.getClass()));
-    return MutableList.copyOf(env, fields);
+    fields.addAll(CallUtils.getMethodNames(thread.getSemantics(), object.getClass()));
+    return MutableList.copyOf(thread, fields);
   }
 
   @SkylarkCallable(
@@ -881,18 +889,19 @@
       // NB: as compared to Python3, we're missing optional named-only arguments 'end' and 'file'
       extraPositionals = @Param(name = "args", doc = "The objects to print."),
       useLocation = true,
-      useEnvironment = true)
-  public Runtime.NoneType print(String sep, SkylarkList<?> starargs, Location loc, Environment env)
+      useStarlarkThread = true)
+  public Runtime.NoneType print(
+      String sep, SkylarkList<?> starargs, Location loc, StarlarkThread thread)
       throws EvalException {
     try {
       String msg = starargs.stream().map(Printer::debugPrint).collect(joining(sep));
       // As part of the integration test "skylark_flag_test.sh", if the
       // "--internal_skylark_flag_test_canary" flag is enabled, append an extra marker string to
       // the output.
-      if (env.getSemantics().internalSkylarkFlagTestCanary()) {
+      if (thread.getSemantics().internalSkylarkFlagTestCanary()) {
         msg += "<== skylark flag test ==>";
       }
-      env.handleEvent(Event.debug(loc, msg));
+      thread.handleEvent(Event.debug(loc, msg));
       return Runtime.NONE;
     } catch (NestedSetDepthException exception) {
       throw new EvalException(
@@ -1185,12 +1194,12 @@
               + "zip([1, 2], [3, 4, 5])  # == [(1, 3), (2, 4)]</pre>",
       extraPositionals = @Param(name = "args", doc = "lists to zip."),
       useLocation = true,
-      useEnvironment = true)
-  public MutableList<?> zip(SkylarkList<?> args, Location loc, Environment env)
+      useStarlarkThread = true)
+  public MutableList<?> zip(SkylarkList<?> args, Location loc, StarlarkThread thread)
       throws EvalException {
     Iterator<?>[] iterators = new Iterator<?>[args.size()];
     for (int i = 0; i < args.size(); i++) {
-      iterators[i] = EvalUtils.toIterable(args.get(i), loc, env).iterator();
+      iterators[i] = EvalUtils.toIterable(args.get(i), loc, thread).iterator();
     }
     ArrayList<Tuple<?>> result = new ArrayList<>();
     boolean allHasNext;
@@ -1208,7 +1217,7 @@
         result.add(Tuple.copyOf(elem));
       }
     } while (allHasNext);
-    return MutableList.wrapUnsafe(env, result);
+    return MutableList.wrapUnsafe(thread, result);
   }
 
   /** Skylark int type. */
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/Mutability.java b/src/main/java/com/google/devtools/build/lib/syntax/Mutability.java
index d994d1f..76ef1a2 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/Mutability.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/Mutability.java
@@ -22,29 +22,30 @@
 import java.util.List;
 
 /**
- * An object that manages the capability to mutate Skylark objects and their {@link Environment}s.
- * Collectively, the managed objects are called {@link Freezable}s.
+ * An object that manages the capability to mutate Skylark objects and their {@link
+ * StarlarkThread}s. Collectively, the managed objects are called {@link Freezable}s.
  *
- * <p>Each {@code Environment}, and each of the mutable Skylark values (i.e., {@link
- * StarlarkMutable}s) that are created in that {@code Environment}, holds a pointer to the same
- * {@code Mutability} instance. Once the {@code Environment} is done evaluating, its {@code
+ * <p>Each {@code StarlarkThread}, and each of the mutable Skylark values (i.e., {@link
+ * StarlarkMutable}s) that are created in that {@code StarlarkThread}, holds a pointer to the same
+ * {@code Mutability} instance. Once the {@code StarlarkThread} is done evaluating, its {@code
  * Mutability} is irreversibly closed ("frozen"). At that point, it is no longer possible to change
- * either the bindings in that {@code Environment} or the state of its objects. This protects each
- * {@code Environment} from unintentional and unsafe modification.
+ * either the bindings in that {@code StarlarkThread} or the state of its objects. This protects
+ * each {@code StarlarkThread} from unintentional and unsafe modification.
  *
- * <p>{@code Mutability}s enforce isolation between {@code Environment}s; it is illegal for an
- * evaluation in one {@code Environment} to affect the bindings or values of another. In particular,
- * the {@code Environment} for any Skylark module is frozen before its symbols can be imported for
- * use by another module. Each individual {@code Environment}'s evaluation is single-threaded, so
- * this isolation also translates to thread safety. Any number of threads may simultaneously access
- * frozen data. (The {@code Mutability} itself is also thread-safe if and only if it is frozen.}
+ * <p>{@code Mutability}s enforce isolation between {@code StarlarkThread}s; it is illegal for an
+ * evaluation in one {@code StarlarkThread} to affect the bindings or values of another. In
+ * particular, the {@code StarlarkThread} for any Skylark module is frozen before its symbols can be
+ * imported for use by another module. Each individual {@code StarlarkThread}'s evaluation is
+ * single-threaded, so this isolation also translates to thread safety. Any number of threads may
+ * simultaneously access frozen data. (The {@code Mutability} itself is also thread-safe if and only
+ * if it is frozen.}
  *
  * <p>Although the mutability pointer of a {@code Freezable} contains some debugging information
  * about its context, this should not affect the {@code Freezable}'s semantics. From a behavioral
  * point of view, the only thing that matters is whether the {@code Mutability} is frozen, not what
  * particular {@code Mutability} object is pointed to.
  *
- * <p>A {@code Mutability} also tracks which {@code Freezable} objects in its {@code Environment}
+ * <p>A {@code Mutability} also tracks which {@code Freezable} objects in its {@code StarlarkThread}
  * are temporarily locked from mutation. This is used to prevent modification of iterables during
  * loops. A {@code Freezable} may be locked multiple times (e.g., nested loops over the same
  * iterable). Locking an object does not prohibit mutating its deeply contained values, such as in
@@ -71,18 +72,18 @@
  * try (Mutability mutability = Mutability.create(fmt, ...)) { ... }
  * }</pre>
  *
- * The general pattern is to create a {@code Mutability}, build an {@code Environment}, mutate that
- * {@code Environment} and its objects, and possibly return the result from within the {@code try}
- * block, relying on the try-with-resource construct to ensure that everything gets frozen before
- * the result is used. The only code that should create a {@code Mutability} without using
- * try-with-resource is test code that is not part of the Bazel jar.
+ * The general pattern is to create a {@code Mutability}, build an {@code StarlarkThread}, mutate
+ * that {@code StarlarkThread} and its objects, and possibly return the result from within the
+ * {@code try} block, relying on the try-with-resource construct to ensure that everything gets
+ * frozen before the result is used. The only code that should create a {@code Mutability} without
+ * using try-with-resource is test code that is not part of the Bazel jar.
  *
  * <p>We keep some (unchecked) invariants regarding where {@code Mutability} objects may appear
  * within a compound value.
  *
  * <ol>
  *   <li>A compound value can never contain an unfrozen {@code Mutability} for any {@code
- *       Environment} except the one currently being evaluated.
+ *       StarlarkThread} except the one currently being evaluated.
  *   <li>If a value has the special {@link #IMMUTABLE} {@code Mutability}, all of its contents are
  *       themselves deeply immutable too (i.e. have frozen {@code Mutability}s).
  *   <li>If a value has the special {@link #SHALLOW_IMMUTABLE} {@code Mutability}, its contents may
@@ -94,14 +95,14 @@
  * {@code #SHALLOW_IMMUTABLE} instance. This knowledge is used by {@link
  * StarlarkMutable#isImmutable} to prune traversals of a compound value.
  *
- * <p>There is a special API for freezing individual values rather than whole {@code Environment}s.
- * Because this API makes it easier to violate the above invariants, you should avoid using it if at
- * all possible; at the moment it is only used for serialization. Under this API, you may call
- * {@link Freezable#unsafeShallowFreeze} to reset a value's {@code Mutability} pointer to be {@link
- * #IMMUTABLE}. This operation has no effect on the {@code Mutability} itself. It is up to the
- * caller to preserve or restore the above invariants by ensuring that any deeply contained values
- * are also frozen. For safety and explicitness, this operation is disallowed unless the {@code
- * Mutability}'s {@link #allowsUnsafeShallowFreeze} method returns true.
+ * <p>There is a special API for freezing individual values rather than whole {@code
+ * StarlarkThread}s. Because this API makes it easier to violate the above invariants, you should
+ * avoid using it if at all possible; at the moment it is only used for serialization. Under this
+ * API, you may call {@link Freezable#unsafeShallowFreeze} to reset a value's {@code Mutability}
+ * pointer to be {@link #IMMUTABLE}. This operation has no effect on the {@code Mutability} itself.
+ * It is up to the caller to preserve or restore the above invariants by ensuring that any deeply
+ * contained values are also frozen. For safety and explicitness, this operation is disallowed
+ * unless the {@code Mutability}'s {@link #allowsUnsafeShallowFreeze} method returns true.
  */
 public final class Mutability implements AutoCloseable {
 
@@ -287,9 +288,9 @@
   }
 
   /**
-   * An object that refers to a {@link Mutability} to decide whether to allow mutation. All
-   * {@link Freezable} Skylark objects created within a given {@link Environment} will share the
-   * same {@code Mutability} as that {@code Environment}.
+   * An object that refers to a {@link Mutability} to decide whether to allow mutation. All {@link
+   * Freezable} Skylark objects created within a given {@link StarlarkThread} will share the same
+   * {@code Mutability} as that {@code StarlarkThread}.
    */
   public interface Freezable {
     /**
@@ -355,11 +356,11 @@
       throw new MutabilityException("trying to mutate a frozen object");
     }
 
-    // Consider an {@link Environment} e1, in which is created {@link StarlarkFunction} f1, that
+    // Consider an {@link StarlarkThread} e1, in which is created {@link StarlarkFunction} f1, that
     // closes over some variable v1 bound to list l1. If somehow, via the magic of callbacks, f1 or
-    // l1 is passed as an argument to some function f2 evaluated in {@link Environment} e2 while e1
-    // is still mutable, then e2, being a different {@link Environment}, should not be allowed to
-    // mutate objects from e1. It's a bug, that shouldn't happen in our current code base, so we
+    // l1 is passed as an argument to some function f2 evaluated in {@link StarlarkThread} e2 while
+    // e1 is still mutable, then e2, being a different {@link StarlarkThread}, should not be allowed
+    // to mutate objects from e1. It's a bug, that shouldn't happen in our current code base, so we
     // throw an IllegalArgumentException. If in the future such situations are allowed to happen,
     // then we should throw a MutabilityException instead.
     if (!object.mutability().equals(mutability)) {
@@ -380,7 +381,7 @@
   /**
    * A {@code Mutability} indicating that a value is deeply immutable.
    *
-   * <p>It is not associated with any particular {@link Environment}.
+   * <p>It is not associated with any particular {@link StarlarkThread}.
    */
   public static final Mutability IMMUTABLE = create("IMMUTABLE").freeze();
 
@@ -395,7 +396,7 @@
   // TODO(bazel-team): We might be able to remove this instance, and instead have tuples and other
   // immutable types store the same Mutability as other values in that environment. Then we can
   // simplify the Mutability invariant, and implement deep-immutability checking in constant time
-  // for values whose Environments have been frozen.
+  // for values whose StarlarkThreads have been frozen.
   //
   // This would also affect structs (SkylarkInfo). Maybe they would implement an interface similar
   // to StarlarkMutable, or the relevant methods could be worked into SkylarkValue.
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/Runtime.java b/src/main/java/com/google/devtools/build/lib/syntax/Runtime.java
index a8d7181..740fcd8 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/Runtime.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/Runtime.java
@@ -319,8 +319,8 @@
    * All Skylark builtins.
    *
    * <p>Note that just because a symbol is registered here does not necessarily mean that it is
-   * accessible in a particular {@link Environment}. This registry should include any builtin that
-   * is available in any environment.
+   * accessible in a particular {@link StarlarkThread}. This registry should include any builtin
+   * that is available in any environment.
    *
    * <p>Thread safety: This object is unsynchronized. The register functions are typically called
    * from within static initializer blocks, which should be fine.
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 eda856f..844a27c 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
@@ -77,8 +77,8 @@
     this.mutability = mutability == null ? Mutability.IMMUTABLE : mutability;
   }
 
-  private SkylarkDict(@Nullable Environment env) {
-    this.mutability = env == null ? Mutability.IMMUTABLE : env.mutability();
+  private SkylarkDict(@Nullable StarlarkThread thread) {
+    this.mutability = thread == null ? Mutability.IMMUTABLE : thread.mutability();
   }
 
   @SkylarkCallable(
@@ -97,9 +97,9 @@
             doc = "The default value to use (instead of None) if the key is not found.")
       },
       allowReturnNones = true,
-      useEnvironment = true)
-  public Object get(Object key, Object defaultValue, Environment env) throws EvalException {
-    if (containsKey(key, null, env)) {
+      useStarlarkThread = true)
+  public Object get(Object key, Object defaultValue, StarlarkThread thread) throws EvalException {
+    if (containsKey(key, null, thread)) {
       return this.get(key);
     }
     return defaultValue;
@@ -122,12 +122,12 @@
             doc = "a default value if the key is absent."),
       },
       useLocation = true,
-      useEnvironment = true)
-  public Object pop(Object key, Object defaultValue, Location loc, Environment env)
+      useStarlarkThread = true)
+  public Object pop(Object key, Object defaultValue, Location loc, StarlarkThread thread)
       throws EvalException {
     Object value = get(key);
     if (value != null) {
-      remove(key, loc, env.mutability());
+      remove(key, loc, thread.mutability());
       return value;
     }
     if (defaultValue != Runtime.UNBOUND) {
@@ -145,27 +145,25 @@
               + "If the dictionary is empty, calling <code>popitem()</code> fails. "
               + "It is deterministic which pair is returned.",
       useLocation = true,
-      useEnvironment = true
-  )
-  public Tuple<Object> popitem(Location loc, Environment env)
-      throws EvalException {
+      useStarlarkThread = true)
+  public Tuple<Object> popitem(Location loc, StarlarkThread thread) throws EvalException {
     if (isEmpty()) {
       throw new EvalException(loc, "popitem(): dictionary is empty");
     }
     Object key = keySet().iterator().next();
     Object value = get(key);
-    remove(key, loc, env.mutability());
+    remove(key, loc, thread.mutability());
     return Tuple.of(key, value);
   }
 
   @SkylarkCallable(
-    name = "setdefault",
-    doc =
-        "If <code>key</code> is in the dictionary, return its value. "
-            + "If not, insert key with a value of <code>default</code> "
-            + "and return <code>default</code>. "
-            + "<code>default</code> defaults to <code>None</code>.",
-    parameters = {
+      name = "setdefault",
+      doc =
+          "If <code>key</code> is in the dictionary, return its value. "
+              + "If not, insert key with a value of <code>default</code> "
+              + "and return <code>default</code>. "
+              + "<code>default</code> defaults to <code>None</code>.",
+      parameters = {
         @Param(name = "key", type = Object.class, doc = "The key."),
         @Param(
             name = "default",
@@ -173,23 +171,17 @@
             defaultValue = "None",
             named = true,
             noneable = true,
-            doc = "a default value if the key is absent."
-        ),
-    },
-    useLocation = true,
-    useEnvironment = true
-  )
-  public Object setdefault(
-      K key,
-      V defaultValue,
-      Location loc,
-      Environment env)
+            doc = "a default value if the key is absent."),
+      },
+      useLocation = true,
+      useStarlarkThread = true)
+  public Object setdefault(K key, V defaultValue, Location loc, StarlarkThread thread)
       throws EvalException {
     Object value = get(key);
     if (value != null) {
       return value;
     }
-    put(key, defaultValue, loc, env);
+    put(key, defaultValue, loc, thread);
     return defaultValue;
   }
 
@@ -217,62 +209,62 @@
       },
       extraKeywords = @Param(name = "kwargs", doc = "Dictionary of additional entries."),
       useLocation = true,
-      useEnvironment = true)
+      useStarlarkThread = true)
   public Runtime.NoneType update(
-      Object args, SkylarkDict<?, ?> kwargs, Location loc, Environment env) throws EvalException {
+      Object args, SkylarkDict<?, ?> kwargs, Location loc, StarlarkThread thread)
+      throws EvalException {
     // TODO(adonovan): opt: don't materialize dict; call put directly.
 
     // All these types and casts are lies.
     SkylarkDict<K, V> dict =
         args instanceof SkylarkDict
             ? (SkylarkDict<K, V>) args
-            : getDictFromArgs("update", args, loc, env);
-    dict = SkylarkDict.plus(dict, (SkylarkDict<K, V>) kwargs, env);
-    putAll(dict, loc, env.mutability(), env);
+            : getDictFromArgs("update", args, loc, thread);
+    dict = SkylarkDict.plus(dict, (SkylarkDict<K, V>) kwargs, thread);
+    putAll(dict, loc, thread.mutability(), thread);
     return Runtime.NONE;
   }
 
   @SkylarkCallable(
-    name = "values",
-    doc =
-        "Returns the list of values:"
-            + "<pre class=\"language-python\">"
-            + "{2: \"a\", 4: \"b\", 1: \"c\"}.values() == [\"a\", \"b\", \"c\"]</pre>\n",
-    useEnvironment = true
-  )
-  public MutableList<?> invoke(Environment env) throws EvalException {
-    return MutableList.copyOf(env, values());
+      name = "values",
+      doc =
+          "Returns the list of values:"
+              + "<pre class=\"language-python\">"
+              + "{2: \"a\", 4: \"b\", 1: \"c\"}.values() == [\"a\", \"b\", \"c\"]</pre>\n",
+      useStarlarkThread = true)
+  public MutableList<?> invoke(StarlarkThread thread) throws EvalException {
+    return MutableList.copyOf(thread, values());
   }
 
   @SkylarkCallable(
-    name = "items",
-    doc =
-        "Returns the list of key-value tuples:"
-            + "<pre class=\"language-python\">"
-            + "{2: \"a\", 4: \"b\", 1: \"c\"}.items() == [(2, \"a\"), (4, \"b\"), (1, \"c\")]"
-            + "</pre>\n",
-    useEnvironment = true
-  )
-  public MutableList<?> items(Environment env) throws EvalException {
+      name = "items",
+      doc =
+          "Returns the list of key-value tuples:"
+              + "<pre class=\"language-python\">"
+              + "{2: \"a\", 4: \"b\", 1: \"c\"}.items() == [(2, \"a\"), (4, \"b\"), (1, \"c\")]"
+              + "</pre>\n",
+      useStarlarkThread = true)
+  public MutableList<?> items(StarlarkThread thread) throws EvalException {
     ArrayList<Object> list = Lists.newArrayListWithCapacity(size());
     for (Map.Entry<?, ?> entries : entrySet()) {
       list.add(Tuple.of(entries.getKey(), entries.getValue()));
     }
-    return MutableList.wrapUnsafe(env, list);
+    return MutableList.wrapUnsafe(thread, list);
   }
 
-  @SkylarkCallable(name = "keys",
-    doc = "Returns the list of keys:"
-        + "<pre class=\"language-python\">{2: \"a\", 4: \"b\", 1: \"c\"}.keys() == [2, 4, 1]"
-        + "</pre>\n",
-    useEnvironment = true
-  )
-  public MutableList<?> keys(Environment env) throws EvalException {
+  @SkylarkCallable(
+      name = "keys",
+      doc =
+          "Returns the list of keys:"
+              + "<pre class=\"language-python\">{2: \"a\", 4: \"b\", 1: \"c\"}.keys() == [2, 4, 1]"
+              + "</pre>\n",
+      useStarlarkThread = true)
+  public MutableList<?> keys(StarlarkThread thread) throws EvalException {
     ArrayList<Object> list = Lists.newArrayListWithCapacity(size());
     for (Map.Entry<?, ?> entries : entrySet()) {
       list.add(entries.getKey());
     }
-    return MutableList.wrapUnsafe(env, list);
+    return MutableList.wrapUnsafe(thread, list);
   }
 
   private static final SkylarkDict<?, ?> EMPTY = withMutability(Mutability.IMMUTABLE);
@@ -290,19 +282,19 @@
   }
 
   /** @return a dict mutable in given environment only */
-  public static <K, V> SkylarkDict<K, V> of(@Nullable Environment env) {
-    return new SkylarkDict<>(env);
+  public static <K, V> SkylarkDict<K, V> of(@Nullable StarlarkThread thread) {
+    return new SkylarkDict<>(thread);
   }
 
   /** @return a dict mutable in given environment only, with given initial key and value */
-  public static <K, V> SkylarkDict<K, V> of(@Nullable Environment env, K k, V v) {
-    return SkylarkDict.<K, V>of(env).putUnsafe(k, v);
+  public static <K, V> SkylarkDict<K, V> of(@Nullable StarlarkThread thread, K k, V v) {
+    return SkylarkDict.<K, V>of(thread).putUnsafe(k, v);
   }
 
   /** @return a dict mutable in given environment only, with two given initial key value pairs */
   public static <K, V> SkylarkDict<K, V> of(
-      @Nullable Environment env, K k1, V v1, K k2, V v2) {
-    return SkylarkDict.<K, V>of(env).putUnsafe(k1, v1).putUnsafe(k2, v2);
+      @Nullable StarlarkThread thread, K k1, V v1, K k2, V v2) {
+    return SkylarkDict.<K, V>of(thread).putUnsafe(k1, v1).putUnsafe(k2, v2);
   }
 
   // TODO(bazel-team): Make other methods that take in mutabilities instead of environments, make
@@ -315,8 +307,8 @@
 
   /** @return a dict mutable in given environment only, with contents copied from given map */
   public static <K, V> SkylarkDict<K, V> copyOf(
-      @Nullable Environment env, Map<? extends K, ? extends V> m) {
-    return SkylarkDict.<K, V>of(env).putAllUnsafe(m);
+      @Nullable StarlarkThread thread, Map<? extends K, ? extends V> m) {
+    return SkylarkDict.<K, V>of(thread).putAllUnsafe(m);
   }
 
   /** Puts the given entry into the dict, without calling {@link #checkMutable}. */
@@ -367,12 +359,12 @@
 
   /**
    * Convenience version of {@link #put(K, V, Location, Mutability)} that uses the {@link
-   * Mutability} of an {@link Environment}.
+   * Mutability} of an {@link StarlarkThread}.
    */
   // TODO(bazel-team): Decide whether to eliminate this overload.
-  public void put(K key, V value, Location loc, Environment env) throws EvalException {
+  public void put(K key, V value, Location loc, StarlarkThread thread) throws EvalException {
     checkMutable(loc, mutability);
-    EvalUtils.checkValidDictKey(key, env);
+    EvalUtils.checkValidDictKey(key, thread);
     contents.put(key, value);
   }
 
@@ -385,11 +377,12 @@
    * @throws EvalException if some key is invalid or the dict is frozen
    */
   public <KK extends K, VV extends V> void putAll(
-      Map<KK, VV> map, Location loc, Mutability mutability, Environment env) throws EvalException {
+      Map<KK, VV> map, Location loc, Mutability mutability, StarlarkThread thread)
+      throws EvalException {
     checkMutable(loc, mutability);
     for (Map.Entry<KK, VV> e : map.entrySet()) {
       KK k = e.getKey();
-      EvalUtils.checkValidDictKey(k, env);
+      EvalUtils.checkValidDictKey(k, thread);
       contents.put(k, e.getValue());
     }
   }
@@ -412,12 +405,9 @@
       name = "clear",
       doc = "Remove all items from the dictionary.",
       useLocation = true,
-      useEnvironment = true
-  )
-  public Runtime.NoneType clearDict(
-      Location loc, Environment env)
-      throws EvalException {
-    clear(loc, env.mutability());
+      useStarlarkThread = true)
+  public Runtime.NoneType clearDict(Location loc, StarlarkThread thread) throws EvalException {
+    clear(loc, thread.mutability());
     return Runtime.NONE;
   }
 
@@ -521,9 +511,10 @@
   }
 
   @Override
-  public final boolean containsKey(Object key, Location loc, Environment env) throws EvalException {
-    if (env.getSemantics().incompatibleDisallowDictLookupUnhashableKeys()) {
-      EvalUtils.checkValidDictKey(key, env);
+  public final boolean containsKey(Object key, Location loc, StarlarkThread thread)
+      throws EvalException {
+    if (thread.getSemantics().incompatibleDisallowDictLookupUnhashableKeys()) {
+      EvalUtils.checkValidDictKey(key, thread);
     }
     return this.containsKey(key);
   }
@@ -531,24 +522,25 @@
   public static <K, V> SkylarkDict<K, V> plus(
       SkylarkDict<? extends K, ? extends V> left,
       SkylarkDict<? extends K, ? extends V> right,
-      @Nullable Environment env) {
-    SkylarkDict<K, V> result = SkylarkDict.of(env);
+      @Nullable StarlarkThread thread) {
+    SkylarkDict<K, V> result = SkylarkDict.of(thread);
     result.putAllUnsafe(left);
     result.putAllUnsafe(right);
     return result;
   }
 
   static <K, V> SkylarkDict<K, V> getDictFromArgs(
-      String funcname, Object args, Location loc, @Nullable Environment env) throws EvalException {
+      String funcname, Object args, Location loc, @Nullable StarlarkThread thread)
+      throws EvalException {
     Iterable<?> seq;
     try {
-      seq = EvalUtils.toIterable(args, loc, env);
+      seq = EvalUtils.toIterable(args, loc, thread);
     } catch (EvalException ex) {
       throw new EvalException(
           loc,
           String.format("in %s, got %s, want iterable", funcname, EvalUtils.getDataTypeName(args)));
     }
-    SkylarkDict<K, V> result = SkylarkDict.of(env);
+    SkylarkDict<K, V> result = SkylarkDict.of(thread);
     int pos = 0;
     for (Object item : seq) {
       Iterable<?> seq2;
@@ -572,7 +564,7 @@
                 funcname, pos, pair.size()));
       }
       // These casts are lies
-      result.put((K) pair.get(0), (V) pair.get(1), loc, env);
+      result.put((K) pair.get(0), (V) pair.get(1), loc, thread);
       pos++;
     }
     return result;
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 c0f4f31..5dc7c41 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
@@ -197,8 +197,8 @@
    */
   // TODO(bazel-team): Eliminate this function in favor of a new MutableList factory method. With
   // such a method, we may no longer need to take null as a possible value for the Mutability or
-  // Environment. That in turn would allow us to overload MutableList#of to take either a Mutability
-  // or Environment.
+  // StarlarkThread. That in turn would allow us to overload MutableList#of to take either a
+  // Mutability or StarlarkThread.
   public static <E> SkylarkList<E> createImmutable(Iterable<? extends E> contents) {
     return MutableList.copyOf(Mutability.IMMUTABLE, contents);
   }
@@ -242,8 +242,9 @@
      * performance reasons. May be used when the calling code will not modify the supplied list
      * after calling (honor system).
      */
-    static <T> MutableList<T> wrapUnsafe(@Nullable Environment env, ArrayList<T> rawContents) {
-      return wrapUnsafe(env == null ? null : env.mutability(), rawContents);
+    static <T> MutableList<T> wrapUnsafe(
+        @Nullable StarlarkThread thread, ArrayList<T> rawContents) {
+      return wrapUnsafe(thread == null ? null : thread.mutability(), rawContents);
     }
 
     /**
@@ -285,24 +286,22 @@
 
     /**
      * Returns a {@code MutableList} whose items are given by an iterable and which has the {@link
-     * Mutability} belonging to the given {@link Environment}. If {@code env} is null, the list is
-     * immutable.
+     * Mutability} belonging to the given {@link StarlarkThread}. If {@code thread} is null, the
+     * list is immutable.
      */
     public static <T> MutableList<T> copyOf(
-        @Nullable Environment env, Iterable<? extends T> contents) {
-      return MutableList.copyOf(
-          env == null ? null : env.mutability(),
-          contents);
+        @Nullable StarlarkThread thread, Iterable<? extends T> contents) {
+      return MutableList.copyOf(thread == null ? null : thread.mutability(), contents);
     }
 
     /**
      * Returns a {@code MutableList} with the given items and the {@link Mutability} of the given
-     * {@link Environment}. If {@code env} is null, the list is immutable.
+     * {@link StarlarkThread}. If {@code thread} is null, the list is immutable.
      */
-    public static <T> MutableList<T> of(@Nullable Environment env, T... contents) {
+    public static <T> MutableList<T> of(@Nullable StarlarkThread thread, T... contents) {
       // Safe since we're taking a copy of the input.
       return MutableList.wrapUnsafe(
-          env == null ? null : env.mutability(), Lists.newArrayList(contents));
+          thread == null ? null : thread.mutability(), Lists.newArrayList(contents));
     }
 
     @Override
@@ -437,17 +436,14 @@
         doc =
             "Removes the first item from the list whose value is x. "
                 + "It is an error if there is no such item.",
-        parameters = {
-            @Param(name = "x", type = Object.class, doc = "The object to remove.")
-        },
+        parameters = {@Param(name = "x", type = Object.class, doc = "The object to remove.")},
         useLocation = true,
-        useEnvironment = true
-    )
-    public Runtime.NoneType removeObject(Object x, Location loc, Environment env)
+        useStarlarkThread = true)
+    public Runtime.NoneType removeObject(Object x, Location loc, StarlarkThread thread)
         throws EvalException {
       for (int i = 0; i < size(); i++) {
         if (get(i).equals(x)) {
-          remove(i, loc, env.mutability());
+          remove(i, loc, thread.mutability());
           return Runtime.NONE;
         }
       }
@@ -469,21 +465,20 @@
     }
 
     @SkylarkCallable(
-      name = "append",
-      doc = "Adds an item to the end of the list.",
-      parameters = {
-          @Param(name = "item",
-            type = Object.class,
-            doc = "Item to add at the end.",
-            noneable = true)
-      },
-      useLocation = true,
-      useEnvironment = true
-    )
-    public Runtime.NoneType append(
-        E item, Location loc, Environment env)
+        name = "append",
+        doc = "Adds an item to the end of the list.",
+        parameters = {
+          @Param(
+              name = "item",
+              type = Object.class,
+              doc = "Item to add at the end.",
+              noneable = true)
+        },
+        useLocation = true,
+        useStarlarkThread = true)
+    public Runtime.NoneType append(E item, Location loc, StarlarkThread thread)
         throws EvalException {
-      add(item, loc, env.mutability());
+      add(item, loc, thread.mutability());
       return Runtime.NONE;
     }
 
@@ -491,27 +486,25 @@
         name = "clear",
         doc = "Removes all the elements of the list.",
         useLocation = true,
-        useEnvironment = true)
-    public Runtime.NoneType clearMethod(Location loc, Environment env) throws EvalException {
-      checkMutable(loc, env.mutability());
+        useStarlarkThread = true)
+    public Runtime.NoneType clearMethod(Location loc, StarlarkThread thread) throws EvalException {
+      checkMutable(loc, thread.mutability());
       contents.clear();
       return Runtime.NONE;
     }
 
     @SkylarkCallable(
-      name = "insert",
-      doc = "Inserts an item at a given position.",
-      parameters = {
+        name = "insert",
+        doc = "Inserts an item at a given position.",
+        parameters = {
           @Param(name = "index", type = Integer.class, doc = "The index of the given position."),
           @Param(name = "item", type = Object.class, doc = "The item.", noneable = true)
-      },
-      useLocation = true,
-      useEnvironment = true
-    )
-    public Runtime.NoneType insert(
-        Integer index, E item, Location loc, Environment env)
+        },
+        useLocation = true,
+        useStarlarkThread = true)
+    public Runtime.NoneType insert(Integer index, E item, Location loc, StarlarkThread thread)
         throws EvalException {
-      add(EvalUtils.clampRangeEndpoint(index, size()), item, loc, env.mutability());
+      add(EvalUtils.clampRangeEndpoint(index, size()), item, loc, thread.mutability());
       return Runtime.NONE;
     }
 
@@ -522,11 +515,13 @@
           @Param(name = "items", type = Object.class, doc = "Items to add at the end.")
         },
         useLocation = true,
-        useEnvironment = true)
-    public Runtime.NoneType extend(Object items, Location loc, Environment env)
+        useStarlarkThread = true)
+    public Runtime.NoneType extend(Object items, Location loc, StarlarkThread thread)
         throws EvalException {
       addAll(
-          (Collection<? extends E>) EvalUtils.toCollection(items, loc, env), loc, env.mutability());
+          (Collection<? extends E>) EvalUtils.toCollection(items, loc, thread),
+          loc,
+          thread.mutability());
       return Runtime.NONE;
     }
 
@@ -571,36 +566,33 @@
     }
 
     @SkylarkCallable(
-      name = "pop",
-      doc =
-          "Removes the item at the given position in the list, and returns it. "
-              + "If no <code>index</code> is specified, "
-              + "it removes and returns the last item in the list.",
-      parameters = {
+        name = "pop",
+        doc =
+            "Removes the item at the given position in the list, and returns it. "
+                + "If no <code>index</code> is specified, "
+                + "it removes and returns the last item in the list.",
+        parameters = {
           @Param(
               name = "i",
               type = Integer.class,
               noneable = true,
               defaultValue = "None",
-              doc = "The index of the item."
-          )
-      },
-      useLocation = true,
-      useEnvironment = true
-    )
-    public Object pop(Object i, Location loc, Environment env)
-        throws EvalException {
+              doc = "The index of the item.")
+        },
+        useLocation = true,
+        useStarlarkThread = true)
+    public Object pop(Object i, Location loc, StarlarkThread thread) throws EvalException {
       int arg = i == Runtime.NONE ? -1 : (Integer) i;
       int index = EvalUtils.getSequenceIndex(arg, size(), loc);
       Object result = get(index);
-      remove(index, loc, env.mutability());
+      remove(index, loc, thread.mutability());
       return result;
     }
   }
 
   /**
    * A Skylark tuple, i.e. the value represented by {@code (1, 2, 3)}. Tuples are always immutable
-   * (regardless of the {@link Environment} they are created in).
+   * (regardless of the {@link StarlarkThread} they are created in).
    */
   @SkylarkModule(
       name = "tuple",
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/SkylarkNestedSet.java b/src/main/java/com/google/devtools/build/lib/syntax/SkylarkNestedSet.java
index 66f0d85..313bd0e 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/SkylarkNestedSet.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/SkylarkNestedSet.java
@@ -331,14 +331,13 @@
               + "of the given depset and <code>new_elements</code>. Use the "
               + "<code>transitive</code> constructor argument instead.",
       parameters = {
-          @Param(name = "new_elements", type = Object.class, doc = "The elements to be added.")
+        @Param(name = "new_elements", type = Object.class, doc = "The elements to be added.")
       },
       useLocation = true,
-      useEnvironment = true
-  )
-  public SkylarkNestedSet union(Object newElements, Location loc, Environment env)
+      useStarlarkThread = true)
+  public SkylarkNestedSet union(Object newElements, Location loc, StarlarkThread thread)
       throws EvalException {
-    if (env.getSemantics().incompatibleDepsetUnion()) {
+    if (thread.getSemantics().incompatibleDepsetUnion()) {
       throw new EvalException(
           loc,
           "depset method `.union` has been removed. See "
@@ -361,11 +360,11 @@
               + "</code>-ordered depsets, and for elements of child depsets whose order differs "
               + "from that of the parent depset. The list is a copy; modifying it has no effect "
               + "on the depset and vice versa.",
-      useEnvironment = true,
+      useStarlarkThread = true,
       useLocation = true)
-  public MutableList<Object> toList(Location location, Environment env) throws EvalException {
+  public MutableList<Object> toList(Location location, StarlarkThread thread) throws EvalException {
     try {
-      return MutableList.copyOf(env, this.toCollection());
+      return MutableList.copyOf(thread, this.toCollection());
     } catch (NestedSetDepthException exception) {
       throw new EvalException(
           location,
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/SkylarkQueryable.java b/src/main/java/com/google/devtools/build/lib/syntax/SkylarkQueryable.java
index 6d00b7b..79e0482 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/SkylarkQueryable.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/SkylarkQueryable.java
@@ -28,7 +28,8 @@
   // Variant used when called directly from a Starlark thread.
   // This is a temporary workaround to enable --incompatible_disallow_dict_lookup_unhashable_keys.
   // TODO(adonovan): remove when that flag is removed.
-  default boolean containsKey(Object key, Location loc, Environment env) throws EvalException {
+  default boolean containsKey(Object key, Location loc, StarlarkThread thread)
+      throws EvalException {
     return this.containsKey(key, loc);
   }
 }
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/SkylarkSignatureProcessor.java b/src/main/java/com/google/devtools/build/lib/syntax/SkylarkSignatureProcessor.java
index 45b536c..83723fa 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/SkylarkSignatureProcessor.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/SkylarkSignatureProcessor.java
@@ -243,15 +243,15 @@
           return defaultValue;
         }
         try (Mutability mutability = Mutability.create("initialization")) {
-          // Note that this Skylark environment ignores command line flags.
-          Environment env =
-              Environment.builder(mutability)
+          // Note that this Skylark thread ignores command line flags.
+          StarlarkThread thread =
+              StarlarkThread.builder(mutability)
                   .useDefaultSemantics()
-                  .setGlobals(Environment.CONSTANTS_ONLY)
-                  .setEventHandler(Environment.FAIL_FAST_HANDLER)
+                  .setGlobals(StarlarkThread.CONSTANTS_ONLY)
+                  .setEventHandler(StarlarkThread.FAIL_FAST_HANDLER)
                   .build()
                   .update("unbound", Runtime.UNBOUND);
-          defaultValue = BuildFileAST.eval(ParserInput.fromLines(paramDefaultValue), env);
+          defaultValue = BuildFileAST.eval(ParserInput.fromLines(paramDefaultValue), thread);
           defaultValueCache.put(paramDefaultValue, defaultValue);
           return defaultValue;
         }
@@ -269,7 +269,7 @@
   public static ExtraArgKind[] getExtraArgs(SkylarkSignature annotation) {
     final int numExtraArgs =
         Booleans.countTrue(
-            annotation.useLocation(), annotation.useAst(), annotation.useEnvironment());
+            annotation.useLocation(), annotation.useAst(), annotation.useStarlarkThread());
     if (numExtraArgs == 0) {
       return null;
     }
@@ -281,7 +281,7 @@
     if (annotation.useAst()) {
       extraArgs[i++] = ExtraArgKind.SYNTAX_TREE;
     }
-    if (annotation.useEnvironment()) {
+    if (annotation.useStarlarkThread()) {
       extraArgs[i++] = ExtraArgKind.ENVIRONMENT;
     }
     return extraArgs;
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/SkylarkType.java b/src/main/java/com/google/devtools/build/lib/syntax/SkylarkType.java
index 8320ef8..373e9fd 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/SkylarkType.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/SkylarkType.java
@@ -780,22 +780,18 @@
     throw new IllegalStateException("Cannot infer type from method signature " + method);
   }
 
-  /**
-   * Converts an object retrieved from a Java method to a Skylark-compatible type.
-   */
-  static Object convertToSkylark(Object object, Method method, @Nullable Environment env) {
+  /** Converts an object retrieved from a Java method to a Skylark-compatible type. */
+  static Object convertToSkylark(Object object, Method method, @Nullable StarlarkThread thread) {
     if (object instanceof NestedSet<?>) {
       return SkylarkNestedSet.of(
           SkylarkType.of(getGenericTypeFromMethod(method)), (NestedSet<?>) object);
     }
-    return convertToSkylark(object, env);
+    return convertToSkylark(object, thread);
   }
 
-  /**
-   * Converts an object to a Skylark-compatible type if possible.
-   */
-  public static Object convertToSkylark(Object object, @Nullable Environment env) {
-    return convertToSkylark(object, env == null ? null : env.mutability());
+  /** Converts an object to a Skylark-compatible type if possible. */
+  public static Object convertToSkylark(Object object, @Nullable StarlarkThread thread) {
+    return convertToSkylark(object, thread == null ? null : thread.mutability());
   }
 
   /**
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/SkylarkUtils.java b/src/main/java/com/google/devtools/build/lib/syntax/SkylarkUtils.java
index d8e3f8a..d8289cd 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/SkylarkUtils.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/SkylarkUtils.java
@@ -27,35 +27,35 @@
     ANALYSIS
   }
 
-  public static void setPhase(Environment env, Phase phase) {
-    env.setThreadLocal(Phase.class, phase);
+  public static void setPhase(StarlarkThread thread, Phase phase) {
+    thread.setThreadLocal(Phase.class, phase);
   }
 
-  private static Phase getPhase(Environment env) {
-    Phase phase = env.getThreadLocal(Phase.class);
+  private static Phase getPhase(StarlarkThread thread) {
+    Phase phase = thread.getThreadLocal(Phase.class);
     return phase == null ? Phase.ANALYSIS : phase;
   }
 
   /**
-   * Checks that the current Environment is in the loading or the workspace phase.
+   * Checks that the current StarlarkThread is in the loading or the workspace phase.
    *
    * @param symbol name of the function being only authorized thus.
    */
-  public static void checkLoadingOrWorkspacePhase(Environment env, String symbol, Location loc)
-      throws EvalException {
-    if (getPhase(env) == Phase.ANALYSIS) {
+  public static void checkLoadingOrWorkspacePhase(
+      StarlarkThread thread, String symbol, Location loc) throws EvalException {
+    if (getPhase(thread) == Phase.ANALYSIS) {
       throw new EvalException(loc, symbol + "() cannot be called during the analysis phase");
     }
   }
 
   /**
-   * Checks that the current Environment is in the loading phase.
+   * Checks that the current StarlarkThread is in the loading phase.
    *
    * @param symbol name of the function being only authorized thus.
    */
-  public static void checkLoadingPhase(Environment env, String symbol, Location loc)
+  public static void checkLoadingPhase(StarlarkThread thread, String symbol, Location loc)
       throws EvalException {
-    if (getPhase(env) != Phase.LOADING) {
+    if (getPhase(thread) != Phase.LOADING) {
       throw new EvalException(loc, symbol + "() can only be called during the loading phase");
     }
   }
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/StarlarkCallable.java b/src/main/java/com/google/devtools/build/lib/syntax/StarlarkCallable.java
index 772a836..d721f6d 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/StarlarkCallable.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/StarlarkCallable.java
@@ -29,23 +29,23 @@
   /**
    * Call this function with the given arguments.
    *
-   * Neither the callee nor the caller may modify the args List or kwargs Map.
+   * <p>Neither the callee nor the caller may modify the args List or kwargs Map.
    *
    * @param args the list of positional arguments
    * @param kwargs the mapping of named arguments
    * @param call the syntax tree of the function call
-   * @param env the Environment in which the function is called
+   * @param thread the StarlarkThread in which the function is called
    * @return the result of the call
    * @throws EvalException if there was an error invoking this function
    */
   // TODO(adonovan):
-  // - rename Environment to StarlarkThread and make it the first parameter.
-  // - eliminate the FuncallExpression parameter (which can be accessed through env).
+  // - rename StarlarkThread to StarlarkThread and make it the first parameter.
+  // - eliminate the FuncallExpression parameter (which can be accessed through thread).
   public Object call(
       List<Object> args,
       @Nullable Map<String, Object> kwargs,
       @Nullable FuncallExpression call,
-      Environment env)
+      StarlarkThread thread)
       throws EvalException, InterruptedException;
 
   // TODO(adonovan): add a getName method that defines how this callable appears in a stack trace.
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 c62a3b2..09d56bc 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
@@ -19,7 +19,7 @@
 import com.google.devtools.build.lib.profiler.ProfilerTask;
 import com.google.devtools.build.lib.profiler.SilentCloseable;
 import com.google.devtools.build.lib.skylarkinterface.SkylarkPrinter;
-import com.google.devtools.build.lib.syntax.Environment.LexicalFrame;
+import com.google.devtools.build.lib.syntax.StarlarkThread.LexicalFrame;
 
 /** A StarlarkFunction is the function value created by a Starlark {@code def} statement. */
 public class StarlarkFunction extends BaseFunction {
@@ -27,14 +27,14 @@
   private final ImmutableList<Statement> statements;
 
   // we close over the globals at the time of definition
-  private final Environment.GlobalFrame definitionGlobals;
+  private final StarlarkThread.GlobalFrame definitionGlobals;
 
   public StarlarkFunction(
       String name,
       Location location,
       FunctionSignature.WithValues<Object, SkylarkType> signature,
       ImmutableList<Statement> statements,
-      Environment.GlobalFrame definitionGlobals) {
+      StarlarkThread.GlobalFrame definitionGlobals) {
     super(name, signature, location);
     this.statements = statements;
     this.definitionGlobals = definitionGlobals;
@@ -44,37 +44,39 @@
     return statements;
   }
 
-  public Environment.GlobalFrame getDefinitionGlobals() {
+  public StarlarkThread.GlobalFrame getDefinitionGlobals() {
     return definitionGlobals;
   }
 
   @Override
-  public Object call(Object[] arguments, FuncallExpression ast, Environment env)
+  public Object call(Object[] arguments, FuncallExpression ast, StarlarkThread thread)
       throws EvalException, InterruptedException {
-    if (env.mutability().isFrozen()) {
+    if (thread.mutability().isFrozen()) {
       throw new EvalException(getLocation(), "Trying to call in frozen environment");
     }
-    if (env.isRecursiveCall(this)) {
-      throw new EvalException(getLocation(),
-          String.format("Recursion was detected when calling '%s' from '%s'",
-              getName(), env.getCurrentFunction().getName()));
+    if (thread.isRecursiveCall(this)) {
+      throw new EvalException(
+          getLocation(),
+          String.format(
+              "Recursion was detected when calling '%s' from '%s'",
+              getName(), thread.getCurrentFunction().getName()));
     }
 
     ImmutableList<String> names = signature.getSignature().getNames();
-    LexicalFrame lexicalFrame = LexicalFrame.create(env.mutability(), /*numArgs=*/ names.size());
+    LexicalFrame lexicalFrame = LexicalFrame.create(thread.mutability(), /*numArgs=*/ names.size());
     try (SilentCloseable c =
         Profiler.instance().profile(ProfilerTask.STARLARK_USER_FN, getName())) {
-      env.enterScope(this, lexicalFrame, ast, definitionGlobals);
+      thread.enterScope(this, lexicalFrame, ast, definitionGlobals);
 
-      // Registering the functions's arguments as variables in the local Environment
+      // Registering the functions's arguments as variables in the local StarlarkThread
       // foreach loop is not used to avoid iterator overhead
       for (int i = 0; i < names.size(); ++i) {
-        env.update(names.get(i), arguments[i]);
+        thread.update(names.get(i), arguments[i]);
       }
 
-      return Eval.execStatements(env, statements);
+      return Eval.execStatements(thread, statements);
     } finally {
-      env.exitScope();
+      thread.exitScope();
     }
   }
 
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/StarlarkMutable.java b/src/main/java/com/google/devtools/build/lib/syntax/StarlarkMutable.java
index da8dae4..73e8397 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/StarlarkMutable.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/StarlarkMutable.java
@@ -34,14 +34,14 @@
 public abstract class StarlarkMutable implements Freezable, SkylarkValue {
 
   /**
-   * Checks whether this object is currently mutable in the given {@link Environment}, and throws
+   * Checks whether this object is currently mutable in the given {@link StarlarkThread}, and throws
    * an exception if it is not.
    *
    * @deprecated prefer {@link #checkMutable(Location, Mutability)} instead
    */
   @Deprecated
-  protected void checkMutable(Location loc, Environment env) throws EvalException {
-    checkMutable(loc, env.mutability());
+  protected void checkMutable(Location loc, StarlarkThread thread) throws EvalException {
+    checkMutable(loc, thread.mutability());
   }
 
   /**
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/Environment.java b/src/main/java/com/google/devtools/build/lib/syntax/StarlarkThread.java
similarity index 87%
rename from src/main/java/com/google/devtools/build/lib/syntax/Environment.java
rename to src/main/java/com/google/devtools/build/lib/syntax/StarlarkThread.java
index fbbbef2..a7732e2 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/Environment.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/StarlarkThread.java
@@ -48,30 +48,30 @@
 import javax.annotation.Nullable;
 
 /**
- * An Environment represents a Starlark thread.
+ * An StarlarkThread represents a Starlark thread.
  *
  * <p>It holds the stack of active Starlark and built-in function calls. In addition, it may hold
  * per-thread application state (see {@link #setThreadLocal}) that passes through Starlark functions
  * but does not directly affect them, such as information about the BUILD file being loaded.
  *
- * <p>Every {@code Environment} has a {@link Mutability} field, and must be used within a function
- * that creates and closes this {@link Mutability} with the try-with-resource pattern. This {@link
- * Mutability} is also used when initializing mutable objects within that {@code Environment}. When
- * the {@code Mutability} is closed at the end of the computation, it freezes the {@code
- * Environment} along with all of those objects. This pattern enforces the discipline that there
- * should be no dangling mutable {@code Environment}, or concurrency between interacting {@code
- * Environment}s. It is a Skylark-level error to attempt to mutate a frozen {@code Environment} or
- * its objects, but it is a Java-level error to attempt to mutate an unfrozen {@code Environment} or
- * its objects from within a different {@code Environment}.
+ * <p>Every {@code StarlarkThread} has a {@link Mutability} field, and must be used within a
+ * function that creates and closes this {@link Mutability} with the try-with-resource pattern. This
+ * {@link Mutability} is also used when initializing mutable objects within that {@code
+ * StarlarkThread}. When the {@code Mutability} is closed at the end of the computation, it freezes
+ * the {@code StarlarkThread} along with all of those objects. This pattern enforces the discipline
+ * that there should be no dangling mutable {@code StarlarkThread}, or concurrency between
+ * interacting {@code StarlarkThread}s. It is a Skylark-level error to attempt to mutate a frozen
+ * {@code StarlarkThread} or its objects, but it is a Java-level error to attempt to mutate an
+ * unfrozen {@code StarlarkThread} or its objects from within a different {@code StarlarkThread}.
  *
- * <p>One creates an Environment using the {@link #builder} function, then populates it with {@link
- * #setup} and sometimes {@link #setupOverride}, before to evaluate code in it with {@link
+ * <p>One creates an StarlarkThread using the {@link #builder} function, then populates it with
+ * {@link #setup} and sometimes {@link #setupOverride}, before to evaluate code in it with {@link
  * BuildFileAST#eval}, or with {@link BuildFileAST#exec} (where the AST was obtained by passing a
- * {@link ValidationEnvironment} constructed from the Environment to {@link BuildFileAST#parse}.
- * When the computation is over, the frozen Environment can still be queried with {@link #lookup}.
+ * {@link ValidationEnvironment} constructed from the StarlarkThread to {@link BuildFileAST#parse}.
+ * When the computation is over, the frozen StarlarkThread can still be queried with {@link
+ * #lookup}.
  */
-// TODO(adonovan): further steps for Environmental remediation:
-// This class should be renamed StarlarkThread, for that is what it is.
+// TODO(adonovan): further steps for StarlarkThread remediation:
 // Its API should expose the following concepts, and no more:
 // 1) "thread local variables": this holds per-thread application
 //    state such as the current Label, or BUILD package, for all the
@@ -94,7 +94,7 @@
 //    Advanced clients such as the debugger, and the generator_name rule attribute, also need:
 //    - the function value (Warning: careless clients can pin closures in memory)
 //    - Object getLocalValue(Identifier parameter).
-//    3) Debugging support (thread name, profiling counters, etc).
+// 3) Debugging support (thread name, profiling counters, etc).
 // And that is all. See go.starlark.net for the model.
 //
 // The Frame interface should be hidden from clients and then eliminated.
@@ -113,7 +113,7 @@
 // Once the API is small and sound, we can start to represent all
 // the lexical frames within a single function using just an array,
 // indexed by a small integer computed during the validation pass.
-public final class Environment implements Freezable {
+public final class StarlarkThread implements Freezable {
 
   /**
    * A mapping of bindings, either mutable or immutable according to an associated {@link
@@ -121,11 +121,11 @@
    * unspecified.
    *
    * <p>Any non-frozen {@link Frame} must have the same {@link Mutability} as the current {@link
-   * Environment}, to avoid interference from other evaluation contexts. For example, a {@link
-   * StarlarkFunction} will close over the global frame of the {@link Environment} in which it was
-   * defined. When the function is called from other {@link Environment}s (possibly simultaneously),
-   * that global frame must already be frozen; a new local {@link Frame} is created to represent the
-   * lexical scope of the function.
+   * StarlarkThread}, to avoid interference from other evaluation contexts. For example, a {@link
+   * StarlarkFunction} will close over the global frame of the {@link StarlarkThread} in which it
+   * was defined. When the function is called from other {@link StarlarkThread}s (possibly
+   * simultaneously), that global frame must already be frozen; a new local {@link Frame} is created
+   * to represent the lexical scope of the function.
    *
    * <p>A {@link Frame} can have an associated "parent" {@link Frame}, which is used in {@link #get}
    * and {@link #getTransitiveBindings()}
@@ -152,17 +152,17 @@
      * <p>If the binding has the same name as one in a transitive parent, the parent binding is
      * shadowed (i.e., the parent is unaffected).
      *
-     * @param env the {@link Environment} attempting the mutation
+     * @param thread the {@link StarlarkThread} attempting the mutation
      * @param varname the name of the variable to be bound
      * @param value the value to bind to the variable
      */
-    void put(Environment env, String varname, Object value) throws MutabilityException;
+    void put(StarlarkThread thread, String varname, Object value) throws MutabilityException;
 
     /**
      * TODO(laurentlb): Remove this method when possible. It should probably not be part of the
      * public interface.
      */
-    void remove(Environment env, String varname) throws MutabilityException;
+    void remove(StarlarkThread thread, String varname) throws MutabilityException;
 
     /**
      * Returns a map containing all bindings of this {@link Frame} and of its transitive parents,
@@ -202,14 +202,15 @@
     }
 
     @Override
-    public void put(Environment env, String varname, Object value) throws MutabilityException {
-      Mutability.checkMutable(this, env.mutability());
+    public void put(StarlarkThread thread, String varname, Object value)
+        throws MutabilityException {
+      Mutability.checkMutable(this, thread.mutability());
       throw new IllegalStateException();
     }
 
     @Override
-    public void remove(Environment env, String varname) throws MutabilityException {
-      Mutability.checkMutable(this, env.mutability());
+    public void remove(StarlarkThread thread, String varname) throws MutabilityException {
+      Mutability.checkMutable(this, thread.mutability());
       throw new IllegalStateException();
     }
 
@@ -251,14 +252,15 @@
     }
 
     @Override
-    public void put(Environment env, String varname, Object value) throws MutabilityException {
-      Mutability.checkMutable(this, env.mutability());
+    public void put(StarlarkThread thread, String varname, Object value)
+        throws MutabilityException {
+      Mutability.checkMutable(this, thread.mutability());
       bindings.put(varname, value);
     }
 
     @Override
-    public void remove(Environment env, String varname) throws MutabilityException {
-      Mutability.checkMutable(this, env.mutability());
+    public void remove(StarlarkThread thread, String varname) throws MutabilityException {
+      Mutability.checkMutable(this, thread.mutability());
       bindings.remove(varname);
     }
 
@@ -530,16 +532,17 @@
     }
 
     @Override
-    public void put(Environment env, String varname, Object value) throws MutabilityException {
+    public void put(StarlarkThread thread, String varname, Object value)
+        throws MutabilityException {
       checkInitialized();
-      Mutability.checkMutable(this, env.mutability());
+      Mutability.checkMutable(this, thread.mutability());
       bindings.put(varname, value);
     }
 
     @Override
-    public void remove(Environment env, String varname) throws MutabilityException {
+    public void remove(StarlarkThread thread, String varname) throws MutabilityException {
       checkInitialized();
-      Mutability.checkMutable(this, env.mutability());
+      Mutability.checkMutable(this, thread.mutability());
       bindings.remove(varname);
     }
 
@@ -553,7 +556,7 @@
     }
   }
 
-  // The mutability of the Environment comes from its initial global frame.
+  // The mutability of the StarlarkThread comes from its initial global frame.
   private final Mutability mutability;
 
   private final Map<Class<?>, Object> threadLocals = new HashMap<>();
@@ -633,18 +636,18 @@
     }
 
     /**
-     * Constructs using the bindings from the global definitions of the given {@link Environment},
-     * and that {@code Environment}'s transitive hash code.
+     * Constructs using the bindings from the global definitions of the given {@link
+     * StarlarkThread}, and that {@code StarlarkThread}'s transitive hash code.
      */
-    public Extension(Environment env) {
+    public Extension(StarlarkThread thread) {
       // Legacy behavior: all symbols from the global Frame are exported (including symbols
       // introduced by load).
       this(
           ImmutableMap.copyOf(
-              env.getSemantics().incompatibleNoTransitiveLoads()
-                  ? env.globalFrame.getExportedBindings()
-                  : env.globalFrame.getBindings()),
-          env.getTransitiveContentHashCode());
+              thread.getSemantics().incompatibleNoTransitiveLoads()
+                  ? thread.globalFrame.getExportedBindings()
+                  : thread.globalFrame.getBindings()),
+          thread.getTransitiveContentHashCode());
     }
 
     private String getTransitiveContentHashCode() {
@@ -777,8 +780,8 @@
   }
 
   /**
-   * Static Frame for lexical variables that are always looked up in the current Environment or for
-   * the definition Environment of the function currently being evaluated.
+   * Static Frame for lexical variables that are always looked up in the current StarlarkThread or
+   * for the definition StarlarkThread of the function currently being evaluated.
    */
   private Frame lexicalFrame;
 
@@ -816,7 +819,8 @@
    * @param function the function whose scope to enter
    * @param lexical the lexical frame to use
    * @param caller the source AST node for the caller
-   * @param globals the global Frame that this function closes over from its definition Environment
+   * @param globals the global Frame that this function closes over from its definition
+   *     StarlarkThread
    */
   void enterScope(
       BaseFunction function,
@@ -839,7 +843,7 @@
   private final String transitiveHashCode;
 
   /**
-   * Is this a global Environment?
+   * Is this a global StarlarkThread?
    *
    * @return true if the current code is being executed at the top-level, as opposed to inside the
    *     body of a function.
@@ -853,7 +857,7 @@
     return mutability;
   }
 
-  /** Returns the global variables for the Environment (not including dynamic bindings). */
+  /** Returns the global variables for the StarlarkThread (not including dynamic bindings). */
   public GlobalFrame getGlobals() {
     return globalFrame;
   }
@@ -905,14 +909,14 @@
   }
 
   /**
-   * Constructs an Environment. This is the main, most basic constructor.
+   * Constructs an StarlarkThread. This is the main, most basic constructor.
    *
-   * @param globalFrame a frame for the global Environment
+   * @param globalFrame a frame for the global StarlarkThread
    * @param eventHandler an EventHandler for warnings, errors, etc
    * @param importedExtensions Extension-s from which to import bindings with load()
    * @param fileContentHashCode a hash for the source file being evaluated, if any
    */
-  private Environment(
+  private StarlarkThread(
       GlobalFrame globalFrame,
       StarlarkSemantics semantics,
       EventHandler eventHandler,
@@ -930,7 +934,7 @@
   }
 
   /**
-   * A Builder class for Environment.
+   * A Builder class for StarlarkThread.
    *
    * <p>The caller must explicitly set the semantics by calling either {@link #setSemantics} or
    * {@link #useDefaultSemantics}.
@@ -982,14 +986,14 @@
       return this;
     }
 
-    /** Declares content hash for the source file for this Environment. */
+    /** Declares content hash for the source file for this StarlarkThread. */
     public Builder setFileContentHashCode(String fileContentHashCode) {
       this.fileContentHashCode = fileContentHashCode;
       return this;
     }
 
-    /** Builds the Environment. */
-    public Environment build() {
+    /** Builds the StarlarkThread. */
+    public StarlarkThread build() {
       Preconditions.checkArgument(!mutability.isFrozen());
       if (semantics == null) {
         throw new IllegalArgumentException("must call either setSemantics or useDefaultSemantics");
@@ -1020,12 +1024,8 @@
       if (importedExtensions == null) {
         importedExtensions = ImmutableMap.of();
       }
-      return new Environment(
-          globalFrame,
-          semantics,
-          eventHandler,
-          importedExtensions,
-          fileContentHashCode);
+      return new StarlarkThread(
+          globalFrame, semantics, eventHandler, importedExtensions, fileContentHashCode);
     }
   }
 
@@ -1043,7 +1043,7 @@
   }
 
   /** Modifies a binding in the current Frame. If it is the module Frame, also export it. */
-  Environment updateAndExport(String varname, Object value) throws EvalException {
+  StarlarkThread updateAndExport(String varname, Object value) throws EvalException {
     update(varname, value);
     if (isGlobal()) {
       globalFrame.exportedBindings.add(varname);
@@ -1052,25 +1052,25 @@
   }
 
   /**
-   * Modifies a binding in the current Frame of this Environment, as would an {@link
+   * Modifies a binding in the current Frame of this StarlarkThread, as would an {@link
    * AssignmentStatement}. Does not try to modify an inherited binding. This will shadow any
    * inherited binding, which may be an error that you want to guard against before calling this
    * function.
    *
    * @param varname the name of the variable to be bound
    * @param value the value to bind to the variable
-   * @return this Environment, in fluid style
+   * @return this StarlarkThread, in fluid style
    */
-  public Environment update(String varname, Object value) throws EvalException {
+  public StarlarkThread update(String varname, Object value) throws EvalException {
     Preconditions.checkNotNull(value, "trying to assign null to '%s'", varname);
     try {
       lexicalFrame.put(this, varname, value);
     } catch (MutabilityException e) {
       // Note that since at this time we don't accept the global keyword, and don't have closures,
-      // end users should never be able to mutate a frozen Environment, and a MutabilityException
+      // end users should never be able to mutate a frozen StarlarkThread, and a MutabilityException
       // is therefore a failed assertion for Bazel. However, it is possible to shadow a binding
-      // imported from a parent Environment by updating the current Environment, which will not
-      // trigger a MutabilityException.
+      // imported from a parent StarlarkThread by updating the current StarlarkThread, which will
+      // not trigger a MutabilityException.
       throw new AssertionError(
           Printer.format("Can't update %s to %r in frozen environment", varname, value), e);
     }
@@ -1078,14 +1078,14 @@
   }
 
   /**
-   * Initializes a binding in this Environment. It is an error if the variable is already bound.
+   * Initializes a binding in this StarlarkThread. It is an error if the variable is already bound.
    * This is not for end-users, and will throw an AssertionError in case of conflict.
    *
    * @param varname the name of the variable to be bound
    * @param value the value to bind to the variable
-   * @return this Environment, in fluid style
+   * @return this StarlarkThread, in fluid style
    */
-  public Environment setup(String varname, Object value) {
+  public StarlarkThread setup(String varname, Object value) {
     if (lookup(varname) != null) {
       throw new AssertionError(String.format("variable '%s' already bound", varname));
     }
@@ -1098,9 +1098,9 @@
    *
    * @param varname the name of the variable to be bound
    * @param value the value to bind to the variable
-   * @return this Environment, in fluid style
+   * @return this StarlarkThread, in fluid style
    */
-  public Environment setupOverride(String varname, Object value) {
+  public StarlarkThread setupOverride(String varname, Object value) {
     try {
       return update(varname, value);
     } catch (EvalException ee) {
@@ -1167,8 +1167,8 @@
   }
 
   /**
-   * Returns a set of all names of variables that are accessible in this {@code Environment}, in a
-   * deterministic order.
+   * Returns a set of all names of variables that are accessible in this {@code StarlarkThread}, in
+   * a deterministic order.
    */
   // TODO(adonovan): eliminate sole external call from docgen.
   public Set<String> getVariableNames() {
@@ -1190,7 +1190,7 @@
     }
   }
 
-  /** Evaluates a Skylark statement in this environment. (Debugger API) */
+  /** Evaluates a Skylark statement in this thread. (Debugger API) */
   // TODO(adonovan): push this up into the debugger once the eval API is finalized.
   public Object debugEval(ParserInput input) throws EvalException, InterruptedException {
     EvalEventHandler handler = new EvalEventHandler();
@@ -1202,7 +1202,7 @@
     return Eval.eval(this, expr);
   }
 
-  /** Executes a Skylark file (sequence of statements) in this environment. (Debugger API) */
+  /** Executes a Skylark file (sequence of statements) in this thread. (Debugger API) */
   // TODO(adonovan): push this up into the debugger once the exec API is finalized.
   public void debugExec(ParserInput input) throws EvalException, InterruptedException {
     EvalEventHandler handler = new EvalEventHandler();
@@ -1278,18 +1278,18 @@
         return null;
       case INTO:
         // pause at the very next statement
-        return env -> true;
+        return thread -> true;
       case OVER:
-        return env -> isAt(env, pausedContinuation) || isOutside(env, pausedContinuation);
+        return thread -> isAt(thread, pausedContinuation) || isOutside(thread, pausedContinuation);
       case OUT:
         // if we're at the outer-most frame, same as NONE
-        return pausedContinuation == null ? null : env -> isOutside(env, pausedContinuation);
+        return pausedContinuation == null ? null : thread -> isOutside(thread, pausedContinuation);
     }
     throw new IllegalArgumentException("Unsupported stepping type: " + stepping);
   }
 
   /** See stepControl (Debugger API) */
-  public interface ReadyToPause extends Predicate<Environment> {}
+  public interface ReadyToPause extends Predicate<StarlarkThread> {}
 
   /**
    * Describes the stepping behavior that should occur when execution of a thread is continued.
@@ -1316,14 +1316,15 @@
     OUT,
   }
 
-  /** Returns true if {@code env} is in a parent frame of {@code pausedContinuation}. */
-  private static boolean isOutside(Environment env, @Nullable Continuation pausedContinuation) {
-    return pausedContinuation != null && env.continuation == pausedContinuation.continuation;
+  /** Returns true if {@code thread} is in a parent frame of {@code pausedContinuation}. */
+  private static boolean isOutside(
+      StarlarkThread thread, @Nullable Continuation pausedContinuation) {
+    return pausedContinuation != null && thread.continuation == pausedContinuation.continuation;
   }
 
-  /** Returns true if {@code env} is at the same frame as {@code pausedContinuation. */
-  private static boolean isAt(Environment env, @Nullable Continuation pausedContinuation) {
-    return env.continuation == pausedContinuation;
+  /** Returns true if {@code thread} is at the same frame as {@code pausedContinuation. */
+  private static boolean isAt(StarlarkThread thread, @Nullable Continuation pausedContinuation) {
+    return thread.continuation == pausedContinuation;
   }
 
   @Override
@@ -1338,7 +1339,7 @@
 
   @Override
   public String toString() {
-    return String.format("<Environment%s>", mutability());
+    return String.format("<StarlarkThread%s>", mutability());
   }
 
   /**
@@ -1406,31 +1407,32 @@
   }
 
   /**
-   * Returns a hash code calculated from the hash code of this Environment and the transitive
-   * closure of other Environments it loads.
+   * Returns a hash code calculated from the hash code of this StarlarkThread and the transitive
+   * closure of other StarlarkThreads it loads.
    */
   public String getTransitiveContentHashCode() {
     return transitiveHashCode;
   }
 
-  /** A read-only {@link Environment.GlobalFrame} with False/True/None constants only. */
+  /** A read-only {@link StarlarkThread.GlobalFrame} with False/True/None constants only. */
   @AutoCodec static final GlobalFrame CONSTANTS_ONLY = createConstantsGlobals();
 
   /**
-   * A read-only {@link Environment.GlobalFrame} with initial globals as defined in MethodLibrary.
+   * A read-only {@link StarlarkThread.GlobalFrame} with initial globals as defined in
+   * MethodLibrary.
    */
   @AutoCodec public static final GlobalFrame DEFAULT_GLOBALS = createDefaultGlobals();
 
   /** To be removed when all call-sites are updated. */
   public static final GlobalFrame SKYLARK = DEFAULT_GLOBALS;
 
-  private static Environment.GlobalFrame createConstantsGlobals() {
+  private static StarlarkThread.GlobalFrame createConstantsGlobals() {
     ImmutableMap.Builder<String, Object> builder = ImmutableMap.builder();
     Runtime.addConstantsToBuilder(builder);
     return GlobalFrame.createForBuiltins(builder.build());
   }
 
-  private static Environment.GlobalFrame createDefaultGlobals() {
+  private static StarlarkThread.GlobalFrame createDefaultGlobals() {
     ImmutableMap.Builder<String, Object> builder = ImmutableMap.builder();
     Runtime.addConstantsToBuilder(builder);
     MethodLibrary.addBindingsToBuilder(builder);
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/StringModule.java b/src/main/java/com/google/devtools/build/lib/syntax/StringModule.java
index 3de26fa..ef57182 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/StringModule.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/StringModule.java
@@ -110,11 +110,11 @@
             doc = "The objects to join.")
       },
       useLocation = true,
-      useEnvironment = true)
-  public String join(String self, Object elements, Location loc, Environment env)
+      useStarlarkThread = true)
+  public String join(String self, Object elements, Location loc, StarlarkThread thread)
       throws EvalException {
-    Collection<?> items = EvalUtils.toCollection(elements, loc, env);
-    if (env.getSemantics().incompatibleStringJoinRequiresStrings()) {
+    Collection<?> items = EvalUtils.toCollection(elements, loc, thread);
+    if (thread.getSemantics().incompatibleStringJoinRequiresStrings()) {
       for (Object item : items) {
         if (!(item instanceof String)) {
           throw new EvalException(
@@ -337,10 +337,10 @@
             defaultValue = "None",
             doc = "The maximum number of splits.")
       },
-      useEnvironment = true,
+      useStarlarkThread = true,
       useLocation = true)
   public MutableList<String> split(
-      String self, String sep, Object maxSplitO, Location loc, Environment env)
+      String self, String sep, Object maxSplitO, Location loc, StarlarkThread thread)
       throws EvalException {
     if (sep.isEmpty()) {
       throw new EvalException(loc, "Empty separator");
@@ -360,7 +360,7 @@
       res.add(self.substring(start, end));
       start = end + sep.length();
     }
-    return MutableList.wrapUnsafe(env, res);
+    return MutableList.wrapUnsafe(thread, res);
   }
 
   @SkylarkCallable(
@@ -386,10 +386,10 @@
             defaultValue = "None",
             doc = "The maximum number of splits.")
       },
-      useEnvironment = true,
+      useStarlarkThread = true,
       useLocation = true)
   public MutableList<String> rsplit(
-      String self, String sep, Object maxSplitO, Location loc, Environment env)
+      String self, String sep, Object maxSplitO, Location loc, StarlarkThread thread)
       throws EvalException {
     if (sep.isEmpty()) {
       throw new EvalException(loc, "Empty separator");
@@ -410,7 +410,7 @@
       end = start;
     }
     Collections.reverse(res);
-    return MutableList.wrapUnsafe(env, res);
+    return MutableList.wrapUnsafe(thread, res);
   }
 
   @SkylarkCallable(
@@ -429,9 +429,9 @@
             defaultValue = "unbound",
             doc = "The string to split on.")
       },
-      useEnvironment = true,
+      useStarlarkThread = true,
       useLocation = true)
-  public Tuple<String> partition(String self, Object sep, Location loc, Environment env)
+  public Tuple<String> partition(String self, Object sep, Location loc, StarlarkThread thread)
       throws EvalException {
     if (sep == Runtime.UNBOUND) {
         throw new EvalException(
@@ -464,9 +464,9 @@
             defaultValue = "unbound",
             doc = "The string to split on.")
       },
-      useEnvironment = true,
+      useStarlarkThread = true,
       useLocation = true)
-  public Tuple<String> rpartition(String self, Object sep, Location loc, Environment env)
+  public Tuple<String> rpartition(String self, Object sep, Location loc, StarlarkThread thread)
       throws EvalException {
     if (sep == Runtime.UNBOUND) {
         throw new EvalException(
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/ValidationEnvironment.java b/src/main/java/com/google/devtools/build/lib/syntax/ValidationEnvironment.java
index 47e60f7..d3d90b5 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/ValidationEnvironment.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/ValidationEnvironment.java
@@ -82,19 +82,19 @@
     }
   }
 
-  private final Environment env;
+  private final StarlarkThread thread;
   private Block block;
   private int loopCount;
   /** In BUILD files, we have a slightly different behavior for legacy reasons. */
   private final boolean isBuildFile;
 
-  /** Create a ValidationEnvironment for a given global Environment (containing builtins). */
-  private ValidationEnvironment(Environment env, boolean isBuildFile) {
-    Preconditions.checkArgument(env.isGlobal());
-    this.env = env;
+  /** Create a ValidationEnvironment for a given global StarlarkThread (containing builtins). */
+  private ValidationEnvironment(StarlarkThread thread, boolean isBuildFile) {
+    Preconditions.checkArgument(thread.isGlobal());
+    this.thread = thread;
     this.isBuildFile = isBuildFile;
     block = new Block(Scope.Universe, null);
-    Set<String> builtinVariables = env.getVariableNames();
+    Set<String> builtinVariables = thread.getVariableNames();
     block.variables.addAll(builtinVariables);
   }
 
@@ -174,11 +174,11 @@
     if (b == null) {
       // The identifier might not exist because it was restricted (hidden) by the current semantics.
       // If this is the case, output a more helpful error message than 'not found'.
-      FlagGuardedValue result = env.getRestrictedBindings().get(node.getName());
+      FlagGuardedValue result = thread.getRestrictedBindings().get(node.getName());
       if (result != null) {
         throw new ValidationException(
             result.getEvalExceptionFromAttemptingAccess(
-                node.getLocation(), env.getSemantics(), node.getName()));
+                node.getLocation(), thread.getSemantics(), node.getName()));
       }
       throw new ValidationException(Eval.createInvalidIdentifierException(node, getAllSymbols()));
     }
@@ -379,7 +379,7 @@
 
   private void validateToplevelStatements(List<Statement> statements) {
     // Check that load() statements are on top.
-    if (!isBuildFile && env.getSemantics().incompatibleBzlDisallowLoadAfterStatement()) {
+    if (!isBuildFile && thread.getSemantics().incompatibleBzlDisallowLoadAfterStatement()) {
       checkLoadAfterStatement(statements);
     }
 
@@ -396,10 +396,10 @@
 
   // Public entry point, throwing variant.
   // TODO(adonovan): combine with variant below.
-  public static void validateFile(BuildFileAST file, Environment env, boolean isBuildFile)
+  public static void validateFile(BuildFileAST file, StarlarkThread thread, boolean isBuildFile)
       throws EvalException {
     try {
-      ValidationEnvironment venv = new ValidationEnvironment(env, isBuildFile);
+      ValidationEnvironment venv = new ValidationEnvironment(thread, isBuildFile);
       venv.validateToplevelStatements(file.getStatements());
       // Check that no closeBlock was forgotten.
       Preconditions.checkState(venv.block.parent == null);
@@ -410,9 +410,9 @@
 
   // Public entry point, error handling variant.
   public static boolean validateFile(
-      BuildFileAST file, Environment env, boolean isBuildFile, EventHandler eventHandler) {
+      BuildFileAST file, StarlarkThread thread, boolean isBuildFile, EventHandler eventHandler) {
     try {
-      validateFile(file, env, isBuildFile);
+      validateFile(file, thread, isBuildFile);
       return true;
     } catch (EvalException e) {
       if (!e.isDueToIncompleteAST()) {
diff --git a/src/main/java/com/google/devtools/build/skydoc/SkydocMain.java b/src/main/java/com/google/devtools/build/skydoc/SkydocMain.java
index 0ee8dd3..f1368e8 100644
--- a/src/main/java/com/google/devtools/build/skydoc/SkydocMain.java
+++ b/src/main/java/com/google/devtools/build/skydoc/SkydocMain.java
@@ -56,9 +56,6 @@
 import com.google.devtools.build.lib.skylarkbuildapi.test.TestingBootstrap;
 import com.google.devtools.build.lib.syntax.BaseFunction;
 import com.google.devtools.build.lib.syntax.BuildFileAST;
-import com.google.devtools.build.lib.syntax.Environment;
-import com.google.devtools.build.lib.syntax.Environment.Extension;
-import com.google.devtools.build.lib.syntax.Environment.GlobalFrame;
 import com.google.devtools.build.lib.syntax.EvalException;
 import com.google.devtools.build.lib.syntax.LoadStatement;
 import com.google.devtools.build.lib.syntax.MethodLibrary;
@@ -67,6 +64,9 @@
 import com.google.devtools.build.lib.syntax.Runtime;
 import com.google.devtools.build.lib.syntax.StarlarkFunction;
 import com.google.devtools.build.lib.syntax.StarlarkSemantics;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
+import com.google.devtools.build.lib.syntax.StarlarkThread.Extension;
+import com.google.devtools.build.lib.syntax.StarlarkThread.GlobalFrame;
 import com.google.devtools.build.lib.syntax.Statement;
 import com.google.devtools.build.lib.syntax.StringLiteral;
 import com.google.devtools.build.skydoc.fakebuildapi.FakeActionsInfoProvider;
@@ -159,7 +159,7 @@
 
   private final EventHandler eventHandler = new SystemOutEventHandler();
   private final LinkedHashSet<Path> pending = new LinkedHashSet<>();
-  private final Map<Path, Environment> loaded = new HashMap<>();
+  private final Map<Path, StarlarkThread> loaded = new HashMap<>();
   private final SkylarkFileAccessor fileAccessor;
   private final List<String> depRoots;
   private final String workspaceName;
@@ -293,7 +293,7 @@
    *     docstring, an empty string will be printed.
    * @throws InterruptedException if evaluation is interrupted
    */
-  public Environment eval(
+  public StarlarkThread eval(
       StarlarkSemantics semantics,
       Label label,
       ImmutableMap.Builder<String, RuleInfo> ruleInfoMap,
@@ -310,7 +310,7 @@
 
     List<AspectInfoWrapper> aspectInfoList = new ArrayList<>();
 
-    Environment env =
+    StarlarkThread thread =
         recursiveEval(
             semantics, label, ruleInfoList, providerInfoList, aspectInfoList, moduleDocMap);
 
@@ -329,7 +329,8 @@
                 Collectors.toMap(AspectInfoWrapper::getIdentifierFunction, Functions.identity()));
 
     // Sort the bindings so their ordering is deterministic.
-    TreeMap<String, Object> sortedBindings = new TreeMap<>(env.getGlobals().getExportedBindings());
+    TreeMap<String, Object> sortedBindings =
+        new TreeMap<>(thread.getGlobals().getExportedBindings());
 
     for (Entry<String, Object> envEntry : sortedBindings.entrySet()) {
       if (ruleFunctions.containsKey(envEntry.getValue())) {
@@ -360,7 +361,7 @@
       }
     }
 
-    return env;
+    return thread;
   }
 
   /**
@@ -410,7 +411,7 @@
    *     method will add to this list as it evaluates additional files
    * @throws InterruptedException if evaluation is interrupted
    */
-  private Environment recursiveEval(
+  private StarlarkThread recursiveEval(
       StarlarkSemantics semantics,
       Label label,
       List<RuleInfoWrapper> ruleInfoList,
@@ -439,7 +440,7 @@
         String module = load.getImport().getValue();
         Label relativeLabel = label.getRelativeWithRemapping(module, ImmutableMap.of());
         try {
-          Environment importEnv =
+          StarlarkThread importThread =
               recursiveEval(
                   semantics,
                   relativeLabel,
@@ -447,7 +448,7 @@
                   providerInfoList,
                   aspectInfoList,
                   moduleDocMap);
-          imports.put(module, new Extension(importEnv));
+          imports.put(module, new Extension(importThread));
         } catch (NoSuchFileException noSuchFileException) {
           throw new StarlarkEvaluationException(
               String.format(
@@ -457,13 +458,13 @@
       }
     }
 
-    Environment env =
+    StarlarkThread thread =
         evalSkylarkBody(semantics, file, imports, ruleInfoList, providerInfoList, aspectInfoList);
 
     pending.remove(path);
-    env.mutability().freeze();
-    loaded.put(path, env);
-    return env;
+    thread.mutability().freeze();
+    loaded.put(path, thread);
+    return thread;
   }
 
   private Path pathOfLabel(Label label) {
@@ -487,7 +488,7 @@
   }
 
   /** Evaluates the AST from a single skylark file, given the already-resolved imports. */
-  private Environment evalSkylarkBody(
+  private StarlarkThread evalSkylarkBody(
       StarlarkSemantics semantics,
       BuildFileAST buildFileAST,
       Map<String, Extension> imports,
@@ -496,20 +497,20 @@
       List<AspectInfoWrapper> aspectInfoList)
       throws InterruptedException, StarlarkEvaluationException {
 
-    Environment env =
-        createEnvironment(
+    StarlarkThread thread =
+        createStarlarkThread(
             semantics,
             eventHandler,
             globalFrame(ruleInfoList, providerInfoList, aspectInfoList),
             imports);
 
-    if (!buildFileAST.exec(env, eventHandler)) {
+    if (!buildFileAST.exec(thread, eventHandler)) {
       throw new StarlarkEvaluationException("Starlark evaluation error");
     }
 
-    env.mutability().freeze();
+    thread.mutability().freeze();
 
-    return env;
+    return thread;
   }
 
   /**
@@ -635,12 +636,12 @@
     }
   }
 
-  private static Environment createEnvironment(
+  private static StarlarkThread createStarlarkThread(
       StarlarkSemantics semantics,
       EventHandler eventHandler,
       GlobalFrame globals,
       Map<String, Extension> imports) {
-    return Environment.builder(Mutability.create("Skydoc"))
+    return StarlarkThread.builder(Mutability.create("Skydoc"))
         .setSemantics(semantics)
         .setGlobals(globals)
         .setImportedExtensions(imports)
diff --git a/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeBuildApiGlobals.java b/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeBuildApiGlobals.java
index 35d6800..a89f105 100644
--- a/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeBuildApiGlobals.java
+++ b/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeBuildApiGlobals.java
@@ -17,8 +17,8 @@
 import com.google.devtools.build.lib.events.Location;
 import com.google.devtools.build.lib.skylarkbuildapi.LateBoundDefaultApi;
 import com.google.devtools.build.lib.skylarkbuildapi.SkylarkBuildApiGlobals;
-import com.google.devtools.build.lib.syntax.Environment;
 import com.google.devtools.build.lib.syntax.EvalException;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
 
 /**
  * Fake implementation of {@link SkylarkBuildApiGlobals}.
@@ -27,7 +27,7 @@
 
   @Override
   public LateBoundDefaultApi configurationField(
-      String fragment, String name, Location loc, Environment env) throws EvalException {
+      String fragment, String name, Location loc, StarlarkThread thread) throws EvalException {
     return new FakeLateBoundDefaultApi();
   }
 }
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 5b07317..5962883 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
@@ -17,10 +17,10 @@
 import com.google.devtools.build.lib.skylarkbuildapi.ProviderApi;
 import com.google.devtools.build.lib.skylarkinterface.SkylarkPrinter;
 import com.google.devtools.build.lib.syntax.BaseFunction;
-import com.google.devtools.build.lib.syntax.Environment;
 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;
 
 /**
@@ -40,7 +40,7 @@
   }
 
   @Override
-  protected Object call(Object[] args, @Nullable FuncallExpression ast, Environment env)
+  protected Object call(Object[] args, @Nullable FuncallExpression ast, StarlarkThread thread)
       throws EvalException, InterruptedException {
     return new FakeStructApi();
   }
diff --git a/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeSkylarkAttrApi.java b/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeSkylarkAttrApi.java
index 7bfddd9..92552be 100644
--- a/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeSkylarkAttrApi.java
+++ b/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeSkylarkAttrApi.java
@@ -18,11 +18,11 @@
 import com.google.devtools.build.lib.skylarkbuildapi.ProviderApi;
 import com.google.devtools.build.lib.skylarkbuildapi.SkylarkAttrApi;
 import com.google.devtools.build.lib.skylarkinterface.SkylarkPrinter;
-import com.google.devtools.build.lib.syntax.Environment;
 import com.google.devtools.build.lib.syntax.EvalException;
 import com.google.devtools.build.lib.syntax.FuncallExpression;
 import com.google.devtools.build.lib.syntax.SkylarkDict;
 import com.google.devtools.build.lib.syntax.SkylarkList;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
 import com.google.devtools.build.skydoc.rendering.proto.StardocOutputProtos.AttributeType;
 import java.util.ArrayList;
 import java.util.List;
@@ -41,7 +41,7 @@
       Boolean mandatory,
       SkylarkList<?> values,
       FuncallExpression ast,
-      Environment env)
+      StarlarkThread thread)
       throws EvalException {
     return new FakeDescriptor(AttributeType.INT, doc, mandatory, ImmutableList.of());
   }
@@ -53,7 +53,7 @@
       Boolean mandatory,
       SkylarkList<?> values,
       FuncallExpression ast,
-      Environment env)
+      StarlarkThread thread)
       throws EvalException {
     return new FakeDescriptor(AttributeType.STRING, doc, mandatory, ImmutableList.of());
   }
@@ -72,11 +72,11 @@
       Object cfg,
       SkylarkList<?> aspects,
       FuncallExpression ast,
-      Environment env)
+      StarlarkThread thread)
       throws EvalException {
     List<List<String>> allNameGroups = new ArrayList<>();
     if (providers != null) {
-      allNameGroups = allProviderNameGroups(providers, env);
+      allNameGroups = allProviderNameGroups(providers, thread);
     }
     return new FakeDescriptor(AttributeType.LABEL, doc, mandatory, allNameGroups);
   }
@@ -89,7 +89,7 @@
       SkylarkList<?> defaultList,
       String doc,
       FuncallExpression ast,
-      Environment env)
+      StarlarkThread thread)
       throws EvalException {
     return new FakeDescriptor(AttributeType.STRING_LIST, doc, mandatory, ImmutableList.of());
   }
@@ -102,7 +102,7 @@
       SkylarkList<?> defaultList,
       String doc,
       FuncallExpression ast,
-      Environment env)
+      StarlarkThread thread)
       throws EvalException {
     return new FakeDescriptor(AttributeType.INT_LIST, doc, mandatory, ImmutableList.of());
   }
@@ -121,11 +121,11 @@
       Object cfg,
       SkylarkList<?> aspects,
       FuncallExpression ast,
-      Environment env)
+      StarlarkThread thread)
       throws EvalException {
     List<List<String>> allNameGroups = new ArrayList<>();
     if (providers != null) {
-      allNameGroups = allProviderNameGroups(providers, env);
+      allNameGroups = allProviderNameGroups(providers, thread);
     }
     return new FakeDescriptor(AttributeType.LABEL_LIST, doc, mandatory, allNameGroups);
   }
@@ -144,25 +144,25 @@
       Object cfg,
       SkylarkList<?> aspects,
       FuncallExpression ast,
-      Environment env)
+      StarlarkThread thread)
       throws EvalException {
     List<List<String>> allNameGroups = new ArrayList<>();
     if (providers != null) {
-      allNameGroups = allProviderNameGroups(providers, env);
+      allNameGroups = allProviderNameGroups(providers, thread);
     }
     return new FakeDescriptor(AttributeType.LABEL_STRING_DICT, doc, mandatory, allNameGroups);
   }
 
   @Override
   public Descriptor boolAttribute(
-      Boolean defaultO, String doc, Boolean mandatory, FuncallExpression ast, Environment env)
+      Boolean defaultO, String doc, Boolean mandatory, FuncallExpression ast, StarlarkThread thread)
       throws EvalException {
     return new FakeDescriptor(AttributeType.BOOLEAN, doc, mandatory, ImmutableList.of());
   }
 
   @Override
   public Descriptor outputAttribute(
-      Object defaultO, String doc, Boolean mandatory, FuncallExpression ast, Environment env)
+      Object defaultO, String doc, Boolean mandatory, FuncallExpression ast, StarlarkThread thread)
       throws EvalException {
     return new FakeDescriptor(AttributeType.OUTPUT, doc, mandatory, ImmutableList.of());
   }
@@ -175,7 +175,7 @@
       Boolean mandatory,
       Boolean nonEmpty,
       FuncallExpression ast,
-      Environment env)
+      StarlarkThread thread)
       throws EvalException {
     return new FakeDescriptor(AttributeType.OUTPUT_LIST, doc, mandatory, ImmutableList.of());
   }
@@ -188,7 +188,7 @@
       Boolean mandatory,
       Boolean nonEmpty,
       FuncallExpression ast,
-      Environment env)
+      StarlarkThread thread)
       throws EvalException {
     return new FakeDescriptor(AttributeType.STRING_DICT, doc, mandatory, ImmutableList.of());
   }
@@ -201,14 +201,14 @@
       Boolean mandatory,
       Boolean nonEmpty,
       FuncallExpression ast,
-      Environment env)
+      StarlarkThread thread)
       throws EvalException {
     return new FakeDescriptor(AttributeType.STRING_LIST_DICT, doc, mandatory, ImmutableList.of());
   }
 
   @Override
   public Descriptor licenseAttribute(
-      Object defaultO, String doc, Boolean mandatory, FuncallExpression ast, Environment env)
+      Object defaultO, String doc, Boolean mandatory, FuncallExpression ast, StarlarkThread thread)
       throws EvalException {
     return new FakeDescriptor(AttributeType.STRING_LIST, doc, mandatory, ImmutableList.of());
   }
@@ -226,17 +226,17 @@
    * each of the inner lists is a separate group.
    */
   private static List<List<String>> allProviderNameGroups(
-      SkylarkList<?> providers, Environment env) {
+      SkylarkList<?> providers, StarlarkThread thread) {
 
     List<List<String>> allNameGroups = new ArrayList<>();
     for (Object object : providers) {
       List<String> providerNameGroup;
       if (object instanceof SkylarkList) {
         SkylarkList<?> group = (SkylarkList<?>) object;
-        providerNameGroup = parseProviderGroup(group, env);
+        providerNameGroup = parseProviderGroup(group, thread);
         allNameGroups.add(providerNameGroup);
       } else {
-        providerNameGroup = parseProviderGroup(providers, env);
+        providerNameGroup = parseProviderGroup(providers, thread);
         allNameGroups.add(providerNameGroup);
         break;
       }
@@ -250,12 +250,12 @@
    * <p>Each item in the group may be either a {@link ProviderApi} or a {@code String} (representing
    * a legacy provider).
    */
-  private static List<String> parseProviderGroup(SkylarkList<?> group, Environment env) {
+  private static List<String> parseProviderGroup(SkylarkList<?> group, StarlarkThread thread) {
     List<String> providerNameGroup = new ArrayList<>();
     for (Object object : group) {
       if (object instanceof ProviderApi) {
         ProviderApi provider = (ProviderApi) object;
-        String providerName = providerName(provider, env);
+        String providerName = providerName(provider, thread);
         providerNameGroup.add(providerName);
       } else if (object instanceof String) {
         String legacyProvider = (String) object;
@@ -268,14 +268,14 @@
   /**
    * Returns the name of {@code provider}.
    *
-   * <p>{@code env} contains a {@code Map<String, Object>} where the values are built-in objects or
-   * objects defined in the file and the keys are the names of these objects. If a {@code provider}
-   * is in the map, the name of the provider is set as the key of this object in {@code bindings}.
-   * If it is not in the map, the provider may be part of a module in the map and the name will be
-   * set to "Unknown Provider".
+   * <p>{@code thread} contains a {@code Map<String, Object>} where the values are built-in objects
+   * or objects defined in the file and the keys are the names of these objects. If a {@code
+   * provider} is in the map, the name of the provider is set as the key of this object in {@code
+   * bindings}. If it is not in the map, the provider may be part of a module in the map and the
+   * name will be set to "Unknown Provider".
    */
-  private static String providerName(ProviderApi provider, Environment env) {
-    Map<String, Object> bindings = env.getGlobals().getTransitiveBindings();
+  private static String providerName(ProviderApi provider, StarlarkThread thread) {
+    Map<String, Object> bindings = thread.getGlobals().getTransitiveBindings();
     if (bindings.containsValue(provider)) {
       for (Entry<String, Object> envEntry : bindings.entrySet()) {
         if (provider.equals(envEntry.getValue())) {
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 b9a4a26..4376ac4 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
@@ -19,13 +19,13 @@
 import com.google.devtools.build.lib.events.Location;
 import com.google.devtools.build.lib.skylarkbuildapi.SkylarkNativeModuleApi;
 import com.google.devtools.build.lib.syntax.ClassObject;
-import com.google.devtools.build.lib.syntax.Environment;
 import com.google.devtools.build.lib.syntax.EvalException;
 import com.google.devtools.build.lib.syntax.FuncallExpression;
 import com.google.devtools.build.lib.syntax.Runtime.NoneType;
 import com.google.devtools.build.lib.syntax.SkylarkDict;
 import com.google.devtools.build.lib.syntax.SkylarkList;
 import com.google.devtools.build.lib.syntax.SkylarkList.MutableList;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
 import javax.annotation.Nullable;
 
 /** Fake implementation of {@link SkylarkNativeModuleApi}. */
@@ -38,42 +38,52 @@
       Integer excludeDirectories,
       Object allowEmpty,
       FuncallExpression ast,
-      Environment env)
+      StarlarkThread thread)
       throws EvalException, InterruptedException {
-    return MutableList.of(env);
+    return MutableList.of(thread);
   }
 
   @Override
-  public Object existingRule(String name, FuncallExpression ast, Environment env)
+  public Object existingRule(String name, FuncallExpression ast, StarlarkThread thread)
       throws EvalException, InterruptedException {
     return null;
   }
 
   @Override
-  public SkylarkDict<String, SkylarkDict<String, Object>> existingRules(FuncallExpression ast,
-      Environment env) throws EvalException, InterruptedException {
-    return SkylarkDict.of(env);
+  public SkylarkDict<String, SkylarkDict<String, Object>> existingRules(
+      FuncallExpression ast, StarlarkThread thread) throws EvalException, InterruptedException {
+    return SkylarkDict.of(thread);
   }
 
   @Override
-  public NoneType packageGroup(String name, SkylarkList<?> packages, SkylarkList<?> includes,
-      FuncallExpression ast, Environment env) throws EvalException {
+  public NoneType packageGroup(
+      String name,
+      SkylarkList<?> packages,
+      SkylarkList<?> includes,
+      FuncallExpression ast,
+      StarlarkThread thread)
+      throws EvalException {
     return null;
   }
 
   @Override
-  public NoneType exportsFiles(SkylarkList<?> srcs, Object visibility, Object licenses,
-      FuncallExpression ast, Environment env) throws EvalException {
+  public NoneType exportsFiles(
+      SkylarkList<?> srcs,
+      Object visibility,
+      Object licenses,
+      FuncallExpression ast,
+      StarlarkThread thread)
+      throws EvalException {
     return null;
   }
 
   @Override
-  public String packageName(FuncallExpression ast, Environment env) throws EvalException {
+  public String packageName(FuncallExpression ast, StarlarkThread thread) throws EvalException {
     return "";
   }
 
   @Override
-  public String repositoryName(Location location, Environment env) throws EvalException {
+  public String repositoryName(Location location, StarlarkThread thread) throws EvalException {
     return "";
   }
 
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 21ecbe3..711bd23 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
@@ -24,7 +24,6 @@
 import com.google.devtools.build.lib.skylarkbuildapi.SkylarkAspectApi;
 import com.google.devtools.build.lib.skylarkbuildapi.SkylarkRuleFunctionsApi;
 import com.google.devtools.build.lib.syntax.BaseFunction;
-import com.google.devtools.build.lib.syntax.Environment;
 import com.google.devtools.build.lib.syntax.EvalException;
 import com.google.devtools.build.lib.syntax.FuncallExpression;
 import com.google.devtools.build.lib.syntax.Runtime;
@@ -32,6 +31,7 @@
 import com.google.devtools.build.lib.syntax.SkylarkList;
 import com.google.devtools.build.lib.syntax.SkylarkType;
 import com.google.devtools.build.lib.syntax.StarlarkFunction;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
 import com.google.devtools.build.skydoc.rendering.AspectInfoWrapper;
 import com.google.devtools.build.skydoc.rendering.ProviderInfoWrapper;
 import com.google.devtools.build.skydoc.rendering.RuleInfoWrapper;
@@ -145,7 +145,7 @@
       Object buildSetting,
       Object cfg,
       FuncallExpression ast,
-      Environment funcallEnv)
+      StarlarkThread funcallThread)
       throws EvalException {
     ImmutableMap.Builder<String, FakeDescriptor> attrsMapBuilder = ImmutableMap.builder();
     if (attrs != null && attrs != Runtime.NONE) {
@@ -173,7 +173,7 @@
 
   @Override
   public Label label(
-      String labelString, Boolean relativeToCallerRepository, Location loc, Environment env)
+      String labelString, Boolean relativeToCallerRepository, Location loc, StarlarkThread thread)
       throws EvalException {
     try {
       return Label.parseAbsolute(
@@ -198,7 +198,7 @@
       String doc,
       Boolean applyToFiles,
       FuncallExpression ast,
-      Environment funcallEnv)
+      StarlarkThread funcallThread)
       throws EvalException {
     FakeSkylarkAspect fakeAspect = new FakeSkylarkAspect();
     ImmutableMap.Builder<String, FakeDescriptor> attrsMapBuilder = ImmutableMap.builder();
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
index c667aa8..a5ed3bb 100644
--- a/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeStarlarkCallable.java
+++ b/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeStarlarkCallable.java
@@ -15,10 +15,10 @@
 package com.google.devtools.build.skydoc.fakebuildapi;
 
 import com.google.devtools.build.lib.skylarkinterface.SkylarkPrinter;
-import com.google.devtools.build.lib.syntax.Environment;
 import com.google.devtools.build.lib.syntax.FuncallExpression;
 import com.google.devtools.build.lib.syntax.Runtime;
 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;
@@ -40,7 +40,7 @@
       List<Object> args,
       @Nullable Map<String, Object> kwargs,
       @Nullable FuncallExpression call,
-      Environment env) {
+      StarlarkThread thread) {
     return Runtime.NONE;
   }
 
diff --git a/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/apple/FakeAppleCommon.java b/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/apple/FakeAppleCommon.java
index 2f5b0af..225d0fa 100644
--- a/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/apple/FakeAppleCommon.java
+++ b/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/apple/FakeAppleCommon.java
@@ -29,9 +29,9 @@
 import com.google.devtools.build.lib.skylarkbuildapi.apple.DottedVersionApi;
 import com.google.devtools.build.lib.skylarkbuildapi.apple.ObjcProviderApi;
 import com.google.devtools.build.lib.skylarkbuildapi.apple.XcodeConfigProviderApi;
-import com.google.devtools.build.lib.syntax.Environment;
 import com.google.devtools.build.lib.syntax.SkylarkDict;
 import com.google.devtools.build.lib.syntax.SkylarkList;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
 import com.google.devtools.build.skydoc.fakebuildapi.FakeProviderApi;
 import com.google.devtools.build.skydoc.fakebuildapi.FakeSkylarkAspect;
 import com.google.devtools.build.skydoc.fakebuildapi.FakeSplitTransitionProvider;
@@ -122,7 +122,7 @@
       SkylarkRuleContextApi skylarkRuleContext,
       SkylarkList<String> extraLinkopts,
       SkylarkList<? extends FileApi> extraLinkInputs,
-      Environment environment) {
+      StarlarkThread thread) {
     return new FakeStructApi();
   }
 
@@ -144,8 +144,8 @@
   }
 
   @Override
-  public ObjcProviderApi<?> newObjcProvider(Boolean usesSwift, SkylarkDict<?, ?> kwargs,
-      Environment environment) {
+  public ObjcProviderApi<?> newObjcProvider(
+      Boolean usesSwift, SkylarkDict<?, ?> kwargs, StarlarkThread thread) {
     return new FakeObjcProvider();
   }
 
diff --git a/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/config/FakeConfigGlobalLibrary.java b/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/config/FakeConfigGlobalLibrary.java
index d51a1c4..66b7180 100644
--- a/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/config/FakeConfigGlobalLibrary.java
+++ b/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/config/FakeConfigGlobalLibrary.java
@@ -18,9 +18,9 @@
 import com.google.devtools.build.lib.skylarkbuildapi.config.ConfigGlobalLibraryApi;
 import com.google.devtools.build.lib.skylarkbuildapi.config.ConfigurationTransitionApi;
 import com.google.devtools.build.lib.syntax.BaseFunction;
-import com.google.devtools.build.lib.syntax.Environment;
 import com.google.devtools.build.lib.syntax.SkylarkDict;
 import com.google.devtools.build.lib.syntax.StarlarkSemantics;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
 import java.util.List;
 
 /**
@@ -34,7 +34,7 @@
       List<String> inputs,
       List<String> outputs,
       Location location,
-      Environment env) {
+      StarlarkThread thread) {
     return new FakeConfigurationTransition();
   }
 
diff --git a/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/cpp/FakeCcInfo.java b/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/cpp/FakeCcInfo.java
index acc9742..6b097bd 100644
--- a/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/cpp/FakeCcInfo.java
+++ b/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/cpp/FakeCcInfo.java
@@ -19,8 +19,8 @@
 import com.google.devtools.build.lib.skylarkbuildapi.cpp.CcInfoApi;
 import com.google.devtools.build.lib.skylarkbuildapi.cpp.CcLinkingContextApi;
 import com.google.devtools.build.lib.skylarkinterface.SkylarkPrinter;
-import com.google.devtools.build.lib.syntax.Environment;
 import com.google.devtools.build.lib.syntax.EvalException;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
 
 /** Fake implementation of {@link CcInfoApi}. */
 public class FakeCcInfo implements CcInfoApi {
@@ -53,10 +53,7 @@
 
     @Override
     public CcInfoApi createInfo(
-        Object ccCompilationContext,
-        Object ccLinkingInfo,
-        Location location,
-        Environment environment)
+        Object ccCompilationContext, Object ccLinkingInfo, Location location, StarlarkThread thread)
         throws EvalException {
       return new FakeCcInfo();
     }
diff --git a/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/cpp/FakeCcModule.java b/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/cpp/FakeCcModule.java
index 5932393..bf9536c 100644
--- a/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/cpp/FakeCcModule.java
+++ b/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/cpp/FakeCcModule.java
@@ -32,11 +32,11 @@
 import com.google.devtools.build.lib.skylarkbuildapi.cpp.CcToolchainVariablesApi;
 import com.google.devtools.build.lib.skylarkbuildapi.cpp.FeatureConfigurationApi;
 import com.google.devtools.build.lib.skylarkbuildapi.cpp.LibraryToLinkApi;
-import com.google.devtools.build.lib.syntax.Environment;
 import com.google.devtools.build.lib.syntax.EvalException;
 import com.google.devtools.build.lib.syntax.SkylarkDict;
 import com.google.devtools.build.lib.syntax.SkylarkList;
 import com.google.devtools.build.lib.syntax.SkylarkList.Tuple;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
 import com.google.devtools.build.skydoc.fakebuildapi.FakeProviderApi;
 
 /** Fake implementation of {@link CcModuleApi}. */
@@ -148,7 +148,7 @@
       Object interfaceLibrary,
       boolean alwayslink,
       Location location,
-      Environment environment) {
+      StarlarkThread thread) {
     return null;
   }
 
@@ -158,7 +158,7 @@
       Object userLinkFlagsObject,
       SkylarkList<FileApi> nonCodeInputs,
       Location location,
-      Environment env) {
+      StarlarkThread thread) {
     return null;
   }
 
@@ -210,7 +210,7 @@
       boolean disallowPicOutputs,
       boolean disallowNopicOutputs,
       Location location,
-      Environment environment)
+      StarlarkThread thread)
       throws EvalException, InterruptedException {
     return null;
   }
@@ -231,7 +231,7 @@
       boolean disallowDynamicLibraries,
       Object grepIncludes,
       Location location,
-      Environment env)
+      StarlarkThread thread)
       throws InterruptedException, EvalException {
     return null;
   }
@@ -250,7 +250,7 @@
       boolean linkDepsStatically,
       SkylarkList<FileApi> additionalInputs,
       Location location,
-      Environment environment)
+      StarlarkThread thread)
       throws InterruptedException, EvalException {
     return null;
   }
diff --git a/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/java/FakeJavaCommon.java b/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/java/FakeJavaCommon.java
index 4efc396..c2a21cf 100644
--- a/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/java/FakeJavaCommon.java
+++ b/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/java/FakeJavaCommon.java
@@ -24,10 +24,10 @@
 import com.google.devtools.build.lib.skylarkbuildapi.SkylarkRuleContextApi;
 import com.google.devtools.build.lib.skylarkbuildapi.java.JavaCommonApi;
 import com.google.devtools.build.lib.skylarkbuildapi.java.JavaToolchainSkylarkApiProviderApi;
-import com.google.devtools.build.lib.syntax.Environment;
 import com.google.devtools.build.lib.syntax.EvalException;
 import com.google.devtools.build.lib.syntax.SkylarkList;
 import com.google.devtools.build.lib.syntax.StarlarkSemantics;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
 import com.google.devtools.build.skydoc.fakebuildapi.FakeProviderApi;
 
 /** Fake implementation of {@link JavaCommonApi}. */
@@ -66,7 +66,7 @@
       SkylarkList<FileApi> resources,
       Boolean neverlink,
       Location loc,
-      Environment environment)
+      StarlarkThread thread)
       throws EvalException, InterruptedException {
     return new FakeJavaInfo();
   }
diff --git a/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/java/FakeJavaInfo.java b/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/java/FakeJavaInfo.java
index 0e49d50..2f2963e 100644
--- a/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/java/FakeJavaInfo.java
+++ b/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/java/FakeJavaInfo.java
@@ -23,10 +23,10 @@
 import com.google.devtools.build.lib.skylarkbuildapi.java.JavaInfoApi;
 import com.google.devtools.build.lib.skylarkbuildapi.java.JavaRuleOutputJarsProviderApi;
 import com.google.devtools.build.lib.skylarkinterface.SkylarkPrinter;
-import com.google.devtools.build.lib.syntax.Environment;
 import com.google.devtools.build.lib.syntax.EvalException;
 import com.google.devtools.build.lib.syntax.SkylarkList;
 import com.google.devtools.build.lib.syntax.SkylarkNestedSet;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
 
 /**
  * Fake implementation of {@link JavaInfoApi}.
@@ -127,7 +127,7 @@
         SkylarkList<?> exports,
         Object jdepsApi,
         Location loc,
-        Environment env)
+        StarlarkThread thread)
         throws EvalException {
       return new FakeJavaInfo();
     }
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 5587212..3f61a88 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
@@ -18,12 +18,12 @@
 import com.google.common.collect.ImmutableMap;
 import com.google.devtools.build.lib.skylarkbuildapi.repository.RepositoryModuleApi;
 import com.google.devtools.build.lib.syntax.BaseFunction;
-import com.google.devtools.build.lib.syntax.Environment;
 import com.google.devtools.build.lib.syntax.EvalException;
 import com.google.devtools.build.lib.syntax.FuncallExpression;
 import com.google.devtools.build.lib.syntax.Runtime;
 import com.google.devtools.build.lib.syntax.SkylarkDict;
 import com.google.devtools.build.lib.syntax.SkylarkList;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
 import com.google.devtools.build.skydoc.fakebuildapi.FakeDescriptor;
 import com.google.devtools.build.skydoc.fakebuildapi.FakeSkylarkRuleFunctionsApi.AttributeNameComparator;
 import com.google.devtools.build.skydoc.rendering.RuleInfoWrapper;
@@ -56,7 +56,7 @@
       Boolean configure,
       String doc,
       FuncallExpression ast,
-      Environment env)
+      StarlarkThread thread)
       throws EvalException {
     List<AttributeInfo> attrInfos;
     ImmutableMap.Builder<String, FakeDescriptor> attrsMapBuilder = ImmutableMap.builder();
diff --git a/src/main/java/com/google/devtools/starlark/Starlark.java b/src/main/java/com/google/devtools/starlark/Starlark.java
index 1f5abdb..0da0ace 100644
--- a/src/main/java/com/google/devtools/starlark/Starlark.java
+++ b/src/main/java/com/google/devtools/starlark/Starlark.java
@@ -17,11 +17,11 @@
 import com.google.devtools.build.lib.events.EventHandler;
 import com.google.devtools.build.lib.events.EventKind;
 import com.google.devtools.build.lib.syntax.BuildFileAST;
-import com.google.devtools.build.lib.syntax.Environment;
 import com.google.devtools.build.lib.syntax.EvalException;
 import com.google.devtools.build.lib.syntax.Mutability;
 import com.google.devtools.build.lib.syntax.ParserInput;
 import com.google.devtools.build.lib.syntax.Printer;
+import com.google.devtools.build.lib.syntax.StarlarkThread;
 import java.io.BufferedReader;
 import java.io.IOException;
 import java.io.InputStreamReader;
@@ -55,10 +55,10 @@
   private final BufferedReader reader =
       new BufferedReader(new InputStreamReader(System.in, CHARSET));
   private final Mutability mutability = Mutability.create("interpreter");
-  private final Environment env =
-      Environment.builder(mutability)
+  private final StarlarkThread thread =
+      StarlarkThread.builder(mutability)
           .useDefaultSemantics()
-          .setGlobals(Environment.DEFAULT_GLOBALS)
+          .setGlobals(StarlarkThread.DEFAULT_GLOBALS)
           .setEventHandler(PRINT_HANDLER)
           .build();
 
@@ -91,7 +91,7 @@
     String line;
     while ((line = prompt()) != null) {
       try {
-        Object result = BuildFileAST.eval(ParserInput.fromLines(line), env);
+        Object result = BuildFileAST.eval(ParserInput.fromLines(line), thread);
         if (result != null) {
           System.out.println(Printer.repr(result));
         }
@@ -117,7 +117,7 @@
   public int execute(String content) {
     try {
       ParserInput input = ParserInput.create(content, null);
-      BuildFileAST.eval(input, env);
+      BuildFileAST.eval(input, thread);
       return 0;
     } catch (EvalException e) {
       System.err.println(e.print());