Disable the 'default' parameter of attr.output and attr.output_list
This is attached to a new Starlark semantics flag, --incompatible_no_output_attr_default
RELNOTES: The 'default' parameter of attr.output and attr.output_list is removed. This is controlled by --incompatible_no_output_attr_default
PiperOrigin-RevId: 215805602
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 13cce13..51019a7 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
@@ -683,6 +683,13 @@
Object defaultO, String doc, Boolean mandatory, FuncallExpression ast, Environment env)
throws EvalException {
SkylarkUtils.checkLoadingOrWorkspacePhase(env, "attr.output", ast.getLocation());
+
+ if (env.getSemantics().incompatibleNoOutputAttrDefault() && defaultO != Runtime.NONE) {
+ throw new EvalException(ast.getLocation(),
+ "'default' is no longer a supported parameter for attr.output. Use Starlark macros "
+ + "to set the default of output or output_list parameters instead. You can use "
+ + "--incompatible_no_output_attr_default=false to temporarily disable this check.");
+ }
return createNonconfigurableAttrDescriptor(
"output",
EvalUtils.<String, Object>optionMap(env, DEFAULT_ARG, defaultO, MANDATORY_ARG, mandatory),
@@ -694,7 +701,7 @@
@Override
public Descriptor outputListAttribute(
Boolean allowEmpty,
- SkylarkList defaultList,
+ Object defaultList,
String doc,
Boolean mandatory,
Boolean nonEmpty,
@@ -702,6 +709,14 @@
Environment env)
throws EvalException {
SkylarkUtils.checkLoadingOrWorkspacePhase(env, "attr.output_list", ast.getLocation());
+
+ if (env.getSemantics().incompatibleNoOutputAttrDefault() && defaultList != Runtime.NONE) {
+ throw new EvalException(ast.getLocation(),
+ "'default' is no longer a supported parameter for attr.output_list. Use Starlark macros "
+ + "to set the default of output or output_list parameters instead. You can use "
+ + "--incompatible_no_output_attr_default=false to temporarily disable this check.");
+ }
+
return createAttrDescriptor(
"output_list",
EvalUtils.<String, Object>optionMap(
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 e253319..9c19e2b 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
@@ -326,6 +326,19 @@
public boolean incompatibleNewActionsApi;
@Option(
+ name = "incompatible_no_output_attr_default",
+ defaultValue = "false",
+ documentationCategory = OptionDocumentationCategory.SKYLARK_SEMANTICS,
+ effectTags = {OptionEffectTag.BUILD_FILE_SEMANTICS},
+ metadataTags = {
+ OptionMetadataTag.INCOMPATIBLE_CHANGE,
+ OptionMetadataTag.TRIGGERED_BY_ALL_INCOMPATIBLE_CHANGES
+ },
+ help = "If set to true, disables the `default` parameter of the `attr.output` and "
+ + "`attr.output_list` attribute definition functions.")
+ public boolean incompatibleNoOutputAttrDefault;
+
+ @Option(
name = "incompatible_no_support_tools_in_action_inputs",
defaultValue = "false",
documentationCategory = OptionDocumentationCategory.SKYLARK_SEMANTICS,
@@ -501,6 +514,7 @@
.incompatibleExpandDirectories(incompatibleExpandDirectories)
.incompatibleGenerateJavaCommonSourceJar(incompatibleGenerateJavaCommonSourceJar)
.incompatibleNewActionsApi(incompatibleNewActionsApi)
+ .incompatibleNoOutputAttrDefault(incompatibleNoOutputAttrDefault)
.incompatibleNoSupportToolsInActionInputs(incompatibleNoSupportToolsInActionInputs)
.incompatibleNoTargetOutputGroup(incompatibleNoTargetOutputGroup)
.incompatibleNoTransitiveLoads(incompatibleNoTransitiveLoads)
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 96e1f4e..b688d70 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
@@ -756,7 +756,9 @@
defaultValue = "None",
named = true,
positional = false,
- doc = DEFAULT_DOC),
+ doc = "<b><code>default<code> is deprecated for <code>attr.output</code>. Use "
+ + "Starlark macros to set the default for <code>output<code> and "
+ + "<code>output_list</code> attributes. <p>" + DEFAULT_DOC),
@Param(
name = DOC_ARG,
type = String.class,
@@ -796,10 +798,13 @@
@ParamType(type = SkylarkList.class, generic1 = Label.class),
@ParamType(type = UserDefinedFunction.class)
},
- defaultValue = "[]",
+ noneable = true,
+ defaultValue = "None",
named = true,
positional = false,
- doc = DEFAULT_DOC),
+ doc = "<b><code>default<code> is deprecated for <code>attr.output_list</code>. Use "
+ + "Starlark macros to set the default for <code>output<code> and "
+ + "<code>output_list</code> attributes. <p>" + DEFAULT_DOC),
@Param(
name = DOC_ARG,
type = String.class,
@@ -826,7 +831,7 @@
useEnvironment = true)
public Descriptor outputListAttribute(
Boolean allowEmpty,
- SkylarkList<?> defaultList,
+ Object defaultList,
String doc,
Boolean mandatory,
Boolean nonEmpty,
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 9805d61..bad29a9 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
@@ -131,6 +131,8 @@
public abstract boolean incompatibleNewActionsApi();
+ public abstract boolean incompatibleNoOutputAttrDefault();
+
public abstract boolean incompatibleNoSupportToolsInActionInputs();
public abstract boolean incompatibleNoTargetOutputGroup();
@@ -188,6 +190,7 @@
.incompatibleExpandDirectories(false)
.incompatibleGenerateJavaCommonSourceJar(false)
.incompatibleNewActionsApi(false)
+ .incompatibleNoOutputAttrDefault(false)
.incompatibleNoSupportToolsInActionInputs(false)
.incompatibleNoTargetOutputGroup(false)
.incompatibleNoTransitiveLoads(false)
@@ -246,6 +249,8 @@
public abstract Builder incompatibleNewActionsApi(boolean value);
+ public abstract Builder incompatibleNoOutputAttrDefault(boolean value);
+
public abstract Builder incompatibleNoSupportToolsInActionInputs(boolean value);
public abstract Builder incompatibleNoTargetOutputGroup(boolean value);
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 f0ea8a6..d72333a 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
@@ -91,7 +91,7 @@
}
@Override
- public Descriptor outputListAttribute(Boolean allowEmpty, SkylarkList<?> defaultList, String doc,
+ public Descriptor outputListAttribute(Boolean allowEmpty, Object defaultList, String doc,
Boolean mandatory, Boolean nonEmpty, FuncallExpression ast, Environment env)
throws EvalException {
return new FakeDescriptor(Type.OUTPUT_LIST, doc, mandatory);
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 933ef11..3ce2097 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
@@ -141,6 +141,7 @@
"--incompatible_expand_directories=" + rand.nextBoolean(),
"--incompatible_generate_javacommon_source_jar=" + rand.nextBoolean(),
"--incompatible_new_actions_api=" + rand.nextBoolean(),
+ "--incompatible_no_output_attr_default=" + rand.nextBoolean(),
"--incompatible_no_support_tools_in_action_inputs=" + rand.nextBoolean(),
"--incompatible_no_target_output_group=" + rand.nextBoolean(),
"--incompatible_no_transitive_loads=" + rand.nextBoolean(),
@@ -182,6 +183,7 @@
.incompatibleExpandDirectories(rand.nextBoolean())
.incompatibleGenerateJavaCommonSourceJar(rand.nextBoolean())
.incompatibleNewActionsApi(rand.nextBoolean())
+ .incompatibleNoOutputAttrDefault(rand.nextBoolean())
.incompatibleNoSupportToolsInActionInputs(rand.nextBoolean())
.incompatibleNoTargetOutputGroup(rand.nextBoolean())
.incompatibleNoTransitiveLoads(rand.nextBoolean())
diff --git a/src/test/java/com/google/devtools/build/lib/skylark/SkylarkIntegrationTest.java b/src/test/java/com/google/devtools/build/lib/skylark/SkylarkIntegrationTest.java
index c8734de..9d4a1e3 100644
--- a/src/test/java/com/google/devtools/build/lib/skylark/SkylarkIntegrationTest.java
+++ b/src/test/java/com/google/devtools/build/lib/skylark/SkylarkIntegrationTest.java
@@ -1053,6 +1053,90 @@
}
@Test
+ public void testNoOutputAttrDefault() throws Exception {
+ setSkylarkSemanticsOptions("--incompatible_no_output_attr_default=true");
+
+ scratch.file(
+ "test/extension.bzl",
+ "def custom_rule_impl(ctx):",
+ " out_file = ctx.actions.declare_file(ctx.attr._o1.name)",
+ " ctx.actions.write(output=out_file, content='hi')",
+ " return struct(o1=ctx.attr._o1)",
+ "",
+ "def output_fn():",
+ " return Label('//test/skylark:foo.txt')",
+ "",
+ "custom_rule = rule(implementation = custom_rule_impl,",
+ " attrs = {'_o1': attr.output(default = output_fn)})");
+
+ scratch.file(
+ "test/BUILD",
+ "load('//test:extension.bzl', 'custom_rule')",
+ "",
+ "custom_rule(name = 'r')");
+
+ reporter.removeHandler(failFastHandler);
+ getConfiguredTarget("//test:r");
+ assertContainsEvent("'default' is no longer a supported parameter for attr.output");
+ }
+
+ @Test
+ public void testNoOutputListAttrDefault() throws Exception {
+ setSkylarkSemanticsOptions("--incompatible_no_output_attr_default=true");
+
+ scratch.file(
+ "test/extension.bzl",
+ "def custom_rule_impl(ctx):",
+ " return []",
+ "",
+ "custom_rule = rule(implementation = custom_rule_impl,",
+ " attrs = {'outs': attr.output_list(default = [])})");
+
+ scratch.file(
+ "test/BUILD",
+ "load('//test:extension.bzl', 'custom_rule')",
+ "",
+ "custom_rule(name = 'r')");
+
+ reporter.removeHandler(failFastHandler);
+ getConfiguredTarget("//test:r");
+ assertContainsEvent("'default' is no longer a supported parameter for attr.output_list");
+ }
+
+ @Test
+ public void testLegacyOutputAttrDefault() throws Exception {
+ // Note that use of the "default" parameter of attr.output and attr.output_label is deprecated
+ // and barely functional. This test simply serves as proof-of-concept verification that the
+ // legacy behavior remains intact.
+ setSkylarkSemanticsOptions("--incompatible_no_output_attr_default=false");
+
+ scratch.file(
+ "test/skylark/extension.bzl",
+ "def custom_rule_impl(ctx):",
+ " out_file = ctx.actions.declare_file(ctx.attr._o1.name)",
+ " ctx.actions.write(output=out_file, content='hi')",
+ " return struct(o1=ctx.attr._o1,",
+ " o2=ctx.attr.o2)",
+ "",
+ "def output_fn():",
+ " return Label('//test/skylark:foo.txt')",
+ "",
+ "custom_rule = rule(implementation = custom_rule_impl,",
+ " attrs = {'_o1': attr.output(default = output_fn),",
+ " 'o2': attr.output_list(default = [])})");
+
+ scratch.file(
+ "test/skylark/BUILD",
+ "load('//test/skylark:extension.bzl', 'custom_rule')",
+ "",
+ "custom_rule(name = 'cr')");
+
+ ConfiguredTarget target = getConfiguredTarget("//test/skylark:cr");
+ assertThat(target.get("o1")).isEqualTo(Label.parseAbsoluteUnchecked("//test/skylark:foo.txt"));
+ assertThat(target.get("o2")).isEqualTo(MutableList.empty());
+ }
+
+ @Test
public void testRuleClassNonMandatoryEmptyOutputs() throws Exception {
scratch.file(
"test/skylark/extension.bzl",