Allow/require callers of AbstractPackageLoader to set Skylark semantics explicitly

Previously the default semantics were used unconditionally. Allowing non-default semantics is a feature. Requiring semantics to be specified explicitly helps to avoid unintentional divergence from the caller's intended semantics. We recently did the same thing for Skylark's Environment.Builder (https://github.com/bazelbuild/bazel/commit/b368b39f8ba1e8e8a67af50e5ade9127b2b149d7).

Also pass Skylark semantics through Package.Builder.Helper, so that the extra verification done for shell tests uses the same semantics as the build.

RELNOTES: None
PiperOrigin-RevId: 173544885
diff --git a/src/main/java/com/google/devtools/build/lib/packages/Package.java b/src/main/java/com/google/devtools/build/lib/packages/Package.java
index c6c5d03..4019e87 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/Package.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/Package.java
@@ -34,6 +34,7 @@
 import com.google.devtools.build.lib.events.Location;
 import com.google.devtools.build.lib.packages.AttributeMap.AcceptsLabelAttribute;
 import com.google.devtools.build.lib.packages.License.DistributionType;
+import com.google.devtools.build.lib.syntax.SkylarkSemantics;
 import com.google.devtools.build.lib.util.Preconditions;
 import com.google.devtools.build.lib.util.SpellChecker;
 import com.google.devtools.build.lib.vfs.Canonicalizer;
@@ -713,9 +714,10 @@
 
       /**
        * Called after {@link com.google.devtools.build.lib.skyframe.PackageFunction} is completely
-       * done loading the given {@link Package}.
+       * done loading the given {@link Package}. {@code skylarkSemantics} are the semantics used to
+       * evaluate the build.
        */
-      void onLoadingComplete(Package pkg);
+      void onLoadingComplete(Package pkg, SkylarkSemantics skylarkSemantics);
     }
 
     /** {@link Helper} that simply calls the {@link Package} constructor. */
@@ -731,7 +733,7 @@
       }
 
       @Override
-      public void onLoadingComplete(Package pkg) {
+      public void onLoadingComplete(Package pkg, SkylarkSemantics skylarkSemantics) {
       }
     }
 
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 015ac01..e144aa8 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
@@ -1607,8 +1607,8 @@
    * Called by a caller of {@link #createPackageFromPreprocessingAst} after this caller has fully
    * loaded the package.
    */
-  public void afterDoneLoadingPackage(Package pkg) {
-    packageBuilderHelper.onLoadingComplete(pkg);
+  public void afterDoneLoadingPackage(Package pkg, SkylarkSemantics skylarkSemantics) {
+    packageBuilderHelper.onLoadingComplete(pkg, skylarkSemantics);
   }
 
   /**
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 c5d7232..4893ac0 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
@@ -423,6 +423,10 @@
    */
   private SkyValue getExternalPackage(Environment env, Path packageLookupPath)
       throws PackageFunctionException, InterruptedException {
+    SkylarkSemantics skylarkSemantics = PrecomputedValue.SKYLARK_SEMANTICS.get(env);
+    if (skylarkSemantics == null) {
+      return null;
+    }
     RootedPath workspacePath = RootedPath.toRootedPath(
         packageLookupPath, Label.EXTERNAL_PACKAGE_FILE_NAME);
     SkyKey workspaceKey = ExternalPackageFunction.key(workspacePath);
@@ -458,7 +462,7 @@
     }
 
     if (packageFactory != null) {
-      packageFactory.afterDoneLoadingPackage(pkg);
+      packageFactory.afterDoneLoadingPackage(pkg, skylarkSemantics);
     }
     return new PackageValue(pkg);
   }
@@ -621,7 +625,7 @@
     // We know this SkyFunction will not be called again, so we can remove the cache entry.
     packageFunctionCache.invalidate(packageId);
 
-    packageFactory.afterDoneLoadingPackage(pkg);
+    packageFactory.afterDoneLoadingPackage(pkg, skylarkSemantics);
     return new PackageValue(pkg);
   }
 
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/packages/AbstractPackageLoader.java b/src/main/java/com/google/devtools/build/lib/skyframe/packages/AbstractPackageLoader.java
index 9ea8e98..3462284 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/packages/AbstractPackageLoader.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/packages/AbstractPackageLoader.java
@@ -111,6 +111,7 @@
   };
   private final Reporter reporter;
   protected final RuleClassProvider ruleClassProvider;
+  protected SkylarkSemantics skylarkSemantics;
   protected final ImmutableMap<SkyFunctionName, SkyFunction> extraSkyFunctions;
   protected final AtomicReference<PathPackageLocator> pkgLocatorRef;
   protected final ExternalFilesHelper externalFilesHelper;
@@ -124,6 +125,7 @@
     protected final Path workspaceDir;
     protected final BlazeDirectories directories;
     protected RuleClassProvider ruleClassProvider = getDefaultRuleClassProvider();
+    protected SkylarkSemantics skylarkSemantics;
     protected Reporter reporter = new Reporter(new EventBus());
     protected Map<SkyFunctionName, SkyFunction> extraSkyFunctions = new HashMap<>();
     protected List<PrecomputedValue.Injected> extraPrecomputedValues = new ArrayList<>();
@@ -146,6 +148,16 @@
       return this;
     }
 
+    public Builder setSkylarkSemantics(SkylarkSemantics semantics) {
+      this.skylarkSemantics = semantics;
+      return this;
+    }
+
+    public Builder useDefaultSkylarkSemantics() {
+      this.skylarkSemantics = SkylarkSemantics.DEFAULT_SEMANTICS;
+      return this;
+    }
+
     public Builder setReporter(Reporter reporter) {
       this.reporter = reporter;
       return this;
@@ -177,7 +189,20 @@
       return this;
     }
 
-    public abstract PackageLoader build();
+    /** Throws {@link IllegalArgumentException} if builder args are incomplete/inconsistent. */
+    protected void validate() {
+      if (skylarkSemantics == null) {
+        throw new IllegalArgumentException(
+            "must call either setSkylarkSemantics or useDefaultSkylarkSemantics");
+      }
+    }
+
+    public final PackageLoader build() {
+      validate();
+      return buildImpl();
+    }
+
+    protected abstract PackageLoader buildImpl();
 
     protected abstract RuleClassProvider getDefaultRuleClassProvider();
 
@@ -189,6 +214,7 @@
     PathPackageLocator pkgLocator =
         new PathPackageLocator(null, ImmutableList.of(workspaceDir));
     this.ruleClassProvider = builder.ruleClassProvider;
+    this.skylarkSemantics = builder.skylarkSemantics;
     this.reporter = builder.reporter;
     this.extraSkyFunctions = ImmutableMap.copyOf(builder.extraSkyFunctions);
     this.pkgLocatorRef = new AtomicReference<>(pkgLocator);
@@ -210,12 +236,14 @@
     };
     this.preinjectedDiff =
         makePreinjectedDiff(
+            skylarkSemantics,
             pkgLocator,
             builder.defaultsPackageContents,
             ImmutableList.copyOf(builder.extraPrecomputedValues));
   }
 
   private static ImmutableDiff makePreinjectedDiff(
+      SkylarkSemantics skylarkSemantics,
       PathPackageLocator pkgLocator,
       String defaultsPackageContents,
       ImmutableList<PrecomputedValue.Injected> extraPrecomputedValues) {
@@ -237,7 +265,7 @@
     }
     PrecomputedValue.PATH_PACKAGE_LOCATOR.set(injectable, pkgLocator);
     PrecomputedValue.DEFAULT_VISIBILITY.set(injectable, ConstantRuleVisibility.PRIVATE);
-    PrecomputedValue.SKYLARK_SEMANTICS.set(injectable, SkylarkSemantics.DEFAULT_SEMANTICS);
+    PrecomputedValue.SKYLARK_SEMANTICS.set(injectable, skylarkSemantics);
     PrecomputedValue.DEFAULTS_PACKAGE_CONTENTS.set(injectable, defaultsPackageContents);
     PrecomputedValue.BLACKLISTED_PACKAGE_PREFIXES_FILE.set(injectable, PathFragment.EMPTY_FRAGMENT);
     return new ImmutableDiff(ImmutableList.<SkyKey>of(), valuesToInject);
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/packages/BazelPackageLoader.java b/src/main/java/com/google/devtools/build/lib/skyframe/packages/BazelPackageLoader.java
index 159b69b..e32a18a 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/packages/BazelPackageLoader.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/packages/BazelPackageLoader.java
@@ -81,7 +81,7 @@
     }
 
     @Override
-    public BazelPackageLoader build() {
+    public BazelPackageLoader buildImpl() {
       return new BazelPackageLoader(this);
     }