Remove the deprecated set constructor from Skylark

The `set` constructor used to be deprecated, but it was still possible to use
it by providing --incompatible_disallow_set_constructor=false.

It's still allowed to have `set` in parts of the code that are not executed, this will be deprecated later. You can check if your code is compatible with this future change by using the flag --incompatible_disallow_uncalled_set_constructor (currently the default is "false").

RELNOTES[INC]: The flag --incompatible_disallow_set_constructor is no longer
available, the deprecated `set` constructor is not available anymore.

PiperOrigin-RevId: 176491641
diff --git a/site/docs/skylark/backward-compatibility.md b/site/docs/skylark/backward-compatibility.md
index 61eabd1..4a67bf4 100644
--- a/site/docs/skylark/backward-compatibility.md
+++ b/site/docs/skylark/backward-compatibility.md
@@ -30,6 +30,7 @@
 The following are the backward incompatible changes that are implemented and
 guarded behind flags in the current release:
 
+*   [Set constructor](#set-constructor)
 *   [Keyword-only arguments](#keyword-only-arguments)
 *   [Mutating `+=`](#mutating)
 *   [Dictionary concatenation](#dictionary-concatenation)
@@ -43,6 +44,22 @@
 *   [New actions API](#new-actions-api)
 *   [Checked arithmetic](#checked-arithmetic)
 
+### Set constructor
+
+To maintain a clear distinction between the specialized [`depset`](depsets.md)
+data structure and Python's native `set` datatype (which does not currently
+exist in Skylark), the `set` constructor has been superseded by `depset`. It is
+no longer allowed to run code that calls the old `set` constructor.
+
+However, for a limited time, it will not be an error to reference the `set`
+constructor from code that is not executed (e.g. a function that is never
+called). Enable this flag to confirm that your code does not still refer to the
+old `set` constructor from unexecuted code.
+
+*   Flag: `--incompatible_disallow_uncalled_set_constructor`
+*   Default: `false`
+
+
 ### Keyword-only arguments
 
 Keyword-only parameters are parameters that can be called only using their name.
diff --git a/src/main/java/com/google/devtools/build/lib/packages/SkylarkSemanticsCodec.java b/src/main/java/com/google/devtools/build/lib/packages/SkylarkSemanticsCodec.java
index 52db1ce..1ffb7e2 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/SkylarkSemanticsCodec.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/SkylarkSemanticsCodec.java
@@ -48,6 +48,7 @@
     codedOut.writeBoolNoTag(semantics.incompatibleDisallowDictPlus());
     codedOut.writeBoolNoTag(semantics.incompatibleDisallowKeywordOnlyArgs());
     codedOut.writeBoolNoTag(semantics.incompatibleDisallowToplevelIfStatement());
+    codedOut.writeBoolNoTag(semantics.incompatibleDisallowUncalledSetConstructor());
     codedOut.writeBoolNoTag(semantics.incompatibleListPlusEqualsInplace());
     codedOut.writeBoolNoTag(semantics.incompatibleLoadArgumentIsLabel());
     codedOut.writeBoolNoTag(semantics.incompatibleNewActionsApi());
@@ -70,6 +71,7 @@
     builder.incompatibleDisallowDictPlus(codedIn.readBool());
     builder.incompatibleDisallowKeywordOnlyArgs(codedIn.readBool());
     builder.incompatibleDisallowToplevelIfStatement(codedIn.readBool());
+    builder.incompatibleDisallowUncalledSetConstructor(codedIn.readBool());
     builder.incompatibleListPlusEqualsInplace(codedIn.readBool());
     builder.incompatibleLoadArgumentIsLabel(codedIn.readBool());
     builder.incompatibleNewActionsApi(codedIn.readBool());
diff --git a/src/main/java/com/google/devtools/build/lib/packages/SkylarkSemanticsOptions.java b/src/main/java/com/google/devtools/build/lib/packages/SkylarkSemanticsOptions.java
index 0f8e0c4..6545d06 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/SkylarkSemanticsOptions.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/SkylarkSemanticsOptions.java
@@ -159,6 +159,17 @@
   public boolean incompatibleDisallowToplevelIfStatement;
 
   @Option(
+    name = "incompatible_disallow_uncalled_set_constructor",
+    defaultValue = "false",
+    category = "incompatible changes",
+    documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
+    effectTags = {OptionEffectTag.UNKNOWN},
+    metadataTags = {OptionMetadataTag.INCOMPATIBLE_CHANGE},
+    help = "If set to true, it's not allowed to use `set()` even if that code is never executed."
+  )
+  public boolean incompatibleDisallowUncalledSetConstructor;
+
+  @Option(
     name = "incompatible_list_plus_equals_inplace",
     defaultValue = "true",
     category = "incompatible changes",
@@ -244,6 +255,7 @@
         .incompatibleDisallowDictPlus(incompatibleDisallowDictPlus)
         .incompatibleDisallowKeywordOnlyArgs(incompatibleDisallowKeywordOnlyArgs)
         .incompatibleDisallowToplevelIfStatement(incompatibleDisallowToplevelIfStatement)
+        .incompatibleDisallowUncalledSetConstructor(incompatibleDisallowUncalledSetConstructor)
         .incompatibleListPlusEqualsInplace(incompatibleListPlusEqualsInplace)
         .incompatibleLoadArgumentIsLabel(incompatibleLoadArgumentIsLabel)
         .incompatibleNewActionsApi(incompatibleNewActionsApi)
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/BazelLibrary.java b/src/main/java/com/google/devtools/build/lib/syntax/BazelLibrary.java
index a60ec53..110c9e1 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/BazelLibrary.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/BazelLibrary.java
@@ -175,36 +175,6 @@
   }
 
   @SkylarkSignature(
-    name = "set",
-    returnType = SkylarkNestedSet.class,
-    doc =
-        "A temporary alias for <a href=\"#depset\">depset</a>. "
-            + "Deprecated in favor of <code>depset</code>.",
-    parameters = {
-      @Param(
-        name = "items",
-        type = Object.class,
-        defaultValue = "[]",
-        doc = "Same as for <a href=\"#depset\">depset</a>."
-      ),
-      @Param(
-        name = "order",
-        type = String.class,
-        defaultValue = "\"default\"",
-        doc = "Same as for <a href=\"#depset\">depset</a>."
-      )
-    },
-    useLocation = true
-  )
-  private static final BuiltinFunction set =
-      new BuiltinFunction("set") {
-        public SkylarkNestedSet invoke(Object items, String order, Location loc)
-            throws EvalException {
-          throw new EvalException(loc, "The function 'set' has been removed in favor of 'depset'.");
-        }
-      };
-
-  @SkylarkSignature(
     name = "union",
     objectType = SkylarkNestedSet.class,
     returnType = SkylarkNestedSet.class,
@@ -285,7 +255,7 @@
       };
 
   private static Environment.Frame createGlobals() {
-    List<BaseFunction> bazelGlobalFunctions = ImmutableList.of(select, depset, set, type);
+    List<BaseFunction> bazelGlobalFunctions = ImmutableList.of(select, depset, type);
 
     try (Mutability mutability = Mutability.create("BUILD")) {
       Environment env = Environment.builder(mutability)
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/Identifier.java b/src/main/java/com/google/devtools/build/lib/syntax/Identifier.java
index a0dc773..1bbf78c 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/Identifier.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/Identifier.java
@@ -94,6 +94,13 @@
     if (name.equals("$error$")) {
       return new EvalException(getLocation(), "contains syntax error(s)", true);
     }
+    if (name.equals("set")) {
+      //TODO(vladmos): Remove as soon as the flag is removed
+      return new EvalException(getLocation(),
+          "The function 'set' has been removed in favor of 'depset', please use the latter. "
+              + "You can temporarily refer to the old 'set' constructor from unexecuted code "
+              + "by using --incompatible_disallow_uncalled_set_constructor=false");
+    }
     String suggestion = SpellChecker.didYouMean(name, symbols);
     return new EvalException(getLocation(), "name '" + name + "' is not defined" + suggestion);
   }
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/SkylarkSemantics.java b/src/main/java/com/google/devtools/build/lib/syntax/SkylarkSemantics.java
index 105768f..39a7673 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/SkylarkSemantics.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/SkylarkSemantics.java
@@ -47,6 +47,7 @@
   public abstract boolean incompatibleDisallowDictPlus();
   public abstract boolean incompatibleDisallowKeywordOnlyArgs();
   public abstract boolean incompatibleDisallowToplevelIfStatement();
+  public abstract boolean incompatibleDisallowUncalledSetConstructor();
   public abstract boolean incompatibleListPlusEqualsInplace();
   public abstract boolean incompatibleLoadArgumentIsLabel();
   public abstract boolean incompatibleNewActionsApi();
@@ -68,6 +69,7 @@
       .incompatibleDisallowDictPlus(false)
       .incompatibleDisallowKeywordOnlyArgs(true)
       .incompatibleDisallowToplevelIfStatement(true)
+      .incompatibleDisallowUncalledSetConstructor(false)
       .incompatibleListPlusEqualsInplace(true)
       .incompatibleLoadArgumentIsLabel(false)
       .incompatibleNewActionsApi(false)
@@ -89,6 +91,7 @@
     public abstract Builder incompatibleDisallowDictPlus(boolean value);
     public abstract Builder incompatibleDisallowKeywordOnlyArgs(boolean value);
     public abstract Builder incompatibleDisallowToplevelIfStatement(boolean value);
+    public abstract Builder incompatibleDisallowUncalledSetConstructor(boolean value);
     public abstract Builder incompatibleListPlusEqualsInplace(boolean value);
     public abstract Builder incompatibleLoadArgumentIsLabel(boolean value);
     public abstract Builder incompatibleNewActionsApi(boolean value);
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 451b0d5..cbe6094d 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
@@ -68,6 +68,12 @@
     block.variables.addAll(builtinVariables);
     block.readOnlyVariables.addAll(builtinVariables);
     semantics = env.getSemantics();
+
+    // If the flag is set to false, it should be allowed to have `set`
+    // in non-executable parts of the code.
+    if (!env.getSemantics().incompatibleDisallowUncalledSetConstructor()) {
+      block.variables.add("set");
+    }
   }
 
   @Override
diff --git a/src/test/java/com/google/devtools/build/lib/packages/SkylarkSemanticsConsistencyTest.java b/src/test/java/com/google/devtools/build/lib/packages/SkylarkSemanticsConsistencyTest.java
index f0f203e..2d388ca 100644
--- a/src/test/java/com/google/devtools/build/lib/packages/SkylarkSemanticsConsistencyTest.java
+++ b/src/test/java/com/google/devtools/build/lib/packages/SkylarkSemanticsConsistencyTest.java
@@ -113,13 +113,13 @@
         "--incompatible_disallow_dict_plus=" + rand.nextBoolean(),
         "--incompatible_disallow_keyword_only_args=" + rand.nextBoolean(),
         "--incompatible_disallow_toplevel_if_statement=" + rand.nextBoolean(),
+        "--incompatible_disallow_uncalled_set_constructor=" + rand.nextBoolean(),
         "--incompatible_list_plus_equals_inplace=" + rand.nextBoolean(),
         "--incompatible_load_argument_is_label=" + rand.nextBoolean(),
         "--incompatible_new_actions_api=" + rand.nextBoolean(),
         "--incompatible_string_is_not_iterable=" + rand.nextBoolean(),
         "--internal_do_not_export_builtins=" + rand.nextBoolean(),
-        "--internal_skylark_flag_test_canary=" + rand.nextBoolean()
-    );
+        "--internal_skylark_flag_test_canary=" + rand.nextBoolean());
   }
 
   /**
@@ -137,6 +137,7 @@
         .incompatibleDisallowDictPlus(rand.nextBoolean())
         .incompatibleDisallowKeywordOnlyArgs(rand.nextBoolean())
         .incompatibleDisallowToplevelIfStatement(rand.nextBoolean())
+        .incompatibleDisallowUncalledSetConstructor(rand.nextBoolean())
         .incompatibleListPlusEqualsInplace(rand.nextBoolean())
         .incompatibleLoadArgumentIsLabel(rand.nextBoolean())
         .incompatibleNewActionsApi(rand.nextBoolean())
diff --git a/src/test/java/com/google/devtools/build/lib/syntax/SkylarkNestedSetTest.java b/src/test/java/com/google/devtools/build/lib/syntax/SkylarkNestedSetTest.java
index c8fdba5..3ba8563 100644
--- a/src/test/java/com/google/devtools/build/lib/syntax/SkylarkNestedSetTest.java
+++ b/src/test/java/com/google/devtools/build/lib/syntax/SkylarkNestedSetTest.java
@@ -37,15 +37,27 @@
 
   @Test
   public void testLegacyConstructorNotCalled() throws Exception {
-    env = newEnvironmentWithSkylarkOptions();
+    env =
+        newEnvironmentWithSkylarkOptions("--incompatible_disallow_uncalled_set_constructor=false");
     eval("s = set([1, 2]) if False else depset([3, 4])");
     SkylarkNestedSet s = get("s");
     assertThat(s.getSet(Object.class)).containsExactly(3, 4);
+
+    // Static check are only enabled in .bzl files
+    new SkylarkTest("--incompatible_disallow_uncalled_set_constructor=true")
+        .testIfErrorContains("The function 'set' has been removed in favor of 'depset'",
+            "s = set([1, 2]) if False else depset([3, 4])");
+    new BuildTest("--incompatible_disallow_uncalled_set_constructor=true")
+        .testEval("s = set([1, 2]) if False else depset([3, 4]); s.to_list()", "[3, 4]");
   }
 
   @Test
   public void testLegacyConstructorCalled() throws Exception {
-    new BothModesTest()
+    new BothModesTest("--incompatible_disallow_uncalled_set_constructor=false")
+        .testIfErrorContains("The function 'set' has been removed in favor of 'depset'",
+            "s = set([1, 2])");
+
+    new BothModesTest("--incompatible_disallow_uncalled_set_constructor=true")
         .testIfErrorContains("The function 'set' has been removed in favor of 'depset'",
             "s = set([1, 2])");
   }