Introduce new flag `--incompatible_string_join_requires_strings`
https://github.com/bazelbuild/bazel/issues/7802
RELNOTES:
A new flag `--incompatible_string_join_requires_strings` is introduced. The sequence argument of `string.join` must contain only string elements.
PiperOrigin-RevId: 240775005
diff --git a/src/main/java/com/google/devtools/build/lib/packages/StarlarkSemanticsOptions.java b/src/main/java/com/google/devtools/build/lib/packages/StarlarkSemanticsOptions.java
index 57d1324..07a6e50 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/StarlarkSemanticsOptions.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/StarlarkSemanticsOptions.java
@@ -326,6 +326,21 @@
public boolean incompatibleDisallowNativeInBuildFile;
@Option(
+ name = "incompatible_string_join_requires_strings",
+ defaultValue = "false",
+ documentationCategory = OptionDocumentationCategory.STARLARK_SEMANTICS,
+ effectTags = {OptionEffectTag.BUILD_FILE_SEMANTICS},
+ metadataTags = {
+ OptionMetadataTag.INCOMPATIBLE_CHANGE,
+ OptionMetadataTag.TRIGGERED_BY_ALL_INCOMPATIBLE_CHANGES
+ },
+ help =
+ "If set to true, the argument of `string.join` must be an iterable whose elements are "
+ + "strings. If set to false, elements are first converted to string. "
+ + "See https://github.com/bazelbuild/bazel/issues/7802")
+ public boolean incompatibleStringJoinRequiresStrings;
+
+ @Option(
name = "incompatible_disallow_struct_provider_syntax",
defaultValue = "false",
documentationCategory = OptionDocumentationCategory.STARLARK_SEMANTICS,
@@ -552,6 +567,7 @@
.incompatibleNoTransitiveLoads(incompatibleNoTransitiveLoads)
.incompatibleRemapMainRepo(incompatibleRemapMainRepo)
.incompatibleRemoveNativeMavenJar(incompatibleRemoveNativeMavenJar)
+ .incompatibleStringJoinRequiresStrings(incompatibleStringJoinRequiresStrings)
.incompatibleUseToolchainProvidersInJavaCommon(
incompatibleUseToolchainProvidersInJavaCommon)
.internalSkylarkFlagTestCanary(internalSkylarkFlagTestCanary)
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/StarlarkSemantics.java b/src/main/java/com/google/devtools/build/lib/syntax/StarlarkSemantics.java
index cf03d59..4a84325 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/StarlarkSemantics.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/StarlarkSemantics.java
@@ -174,6 +174,8 @@
public abstract boolean incompatibleRemoveNativeMavenJar();
+ public abstract boolean incompatibleStringJoinRequiresStrings();
+
public abstract boolean internalSkylarkFlagTestCanary();
public abstract boolean incompatibleUseToolchainProvidersInJavaCommon();
@@ -227,6 +229,7 @@
.incompatibleNoTransitiveLoads(true)
.incompatibleRemapMainRepo(false)
.incompatibleRemoveNativeMavenJar(false)
+ .incompatibleStringJoinRequiresStrings(false)
.internalSkylarkFlagTestCanary(false)
.incompatibleDoNotSplitLinkingCmdline(false)
.build();
@@ -298,6 +301,8 @@
public abstract Builder incompatibleRemoveNativeMavenJar(boolean value);
+ public abstract Builder incompatibleStringJoinRequiresStrings(boolean value);
+
public abstract Builder incompatibleUseToolchainProvidersInJavaCommon(boolean value);
public abstract Builder internalSkylarkFlagTestCanary(boolean value);
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 7390fa8..d16eb5f 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
@@ -99,10 +99,25 @@
+ "</pre>",
parameters = {
@Param(name = "self", type = String.class),
- @Param(name = "elements", legacyNamed = true, type = SkylarkList.class,
+ @Param(
+ name = "elements",
+ legacyNamed = true,
+ type = SkylarkList.class,
doc = "The objects to join.")
- })
- public String join(String self, SkylarkList<?> elements) throws ConversionException {
+ },
+ useLocation = true,
+ useEnvironment = true)
+ public String join(String self, SkylarkList<?> elements, Location loc, Environment env)
+ throws ConversionException, EvalException {
+ if (env.getSemantics().incompatibleStringJoinRequiresStrings()) {
+ for (Object item : elements) {
+ if (!(item instanceof String)) {
+ throw new EvalException(
+ loc,
+ "sequence element must be a string (got '" + EvalUtils.getDataTypeName(item) + "')");
+ }
+ }
+ }
return Joiner.on(self).join(elements);
}
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 ebe9004..91ab07b 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
@@ -155,6 +155,7 @@
"--incompatible_no_transitive_loads=" + rand.nextBoolean(),
"--incompatible_remap_main_repo=" + rand.nextBoolean(),
"--incompatible_remove_native_maven_jar=" + rand.nextBoolean(),
+ "--incompatible_string_join_requires_strings=" + rand.nextBoolean(),
"--incompatible_use_toolchain_providers_in_java_common=" + rand.nextBoolean(),
"--internal_skylark_flag_test_canary=" + rand.nextBoolean(),
"--incompatible_do_not_split_linking_cmdline=" + rand.nextBoolean());
@@ -200,6 +201,7 @@
.incompatibleNoTransitiveLoads(rand.nextBoolean())
.incompatibleRemapMainRepo(rand.nextBoolean())
.incompatibleRemoveNativeMavenJar(rand.nextBoolean())
+ .incompatibleStringJoinRequiresStrings(rand.nextBoolean())
.incompatibleUseToolchainProvidersInJavaCommon(rand.nextBoolean())
.internalSkylarkFlagTestCanary(rand.nextBoolean())
.incompatibleDoNotSplitLinkingCmdline(rand.nextBoolean())
diff --git a/src/test/java/com/google/devtools/build/lib/syntax/MethodLibraryTest.java b/src/test/java/com/google/devtools/build/lib/syntax/MethodLibraryTest.java
index af019ff..12d3287 100644
--- a/src/test/java/com/google/devtools/build/lib/syntax/MethodLibraryTest.java
+++ b/src/test/java/com/google/devtools/build/lib/syntax/MethodLibraryTest.java
@@ -754,4 +754,17 @@
+ "for call to method join(elements) of 'string'",
"','.join(elements=['foo', 'bar'])");
}
+
+ @Test
+ public void testStringJoinRequiresStrings() throws Exception {
+ new SkylarkTest("--incompatible_string_join_requires_strings")
+ .testIfErrorContains(
+ "sequence element must be a string (got 'int')", "', '.join(['foo', 2])");
+ }
+
+ @Test
+ public void testStringJoinDoesNotRequireStrings() throws Exception {
+ new SkylarkTest("--incompatible_string_join_requires_strings=false")
+ .testEval("', '.join(['foo', 2])", "'foo, 2'");
+ }
}