Skylark no longer crashes when the default value of an attribute is a label string that points to a remote repository.
Fixes #1442.
--
MOS_MIGRATED_REVID=132320130
diff --git a/src/main/java/com/google/devtools/build/lib/packages/Attribute.java b/src/main/java/com/google/devtools/build/lib/packages/Attribute.java
index fed7bd4..80bba9b 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/Attribute.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/Attribute.java
@@ -620,14 +620,24 @@
/**
* See value(TYPE) above. This method is only meant for Skylark usage.
+ *
+ * <p>The parameter {@code context} is relevant iff the default value is a Label string.
+ * In this case, {@code context} must point to the parent Label in order to be able to convert
+ * the default value string to a proper Label.
*/
- public Builder<TYPE> defaultValue(Object defaultValue) throws ConversionException {
+ public Builder<TYPE> defaultValue(Object defaultValue, Object context)
+ throws ConversionException {
Preconditions.checkState(!valueSet, "the default value is already set");
- value = type.convert(defaultValue, "attribute " + name);
+ value = type.convert(defaultValue, "attribute " + name, context);
valueSet = true;
return this;
}
+ /** See value(TYPE) above. This method is only meant for Skylark usage. */
+ public Builder<TYPE> defaultValue(Object defaultValue) throws ConversionException {
+ return defaultValue(defaultValue, null);
+ }
+
public boolean isValueSet() {
return valueSet;
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/SkylarkAttr.java b/src/main/java/com/google/devtools/build/lib/rules/SkylarkAttr.java
index ea52e11..2e4bbb6 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/SkylarkAttr.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/SkylarkAttr.java
@@ -172,7 +172,7 @@
new SkylarkComputedDefaultTemplate(
type, callback.getParameterNames(), callback, ast.getLocation()));
} else {
- builder.defaultValue(defaultValue);
+ builder.defaultValue(defaultValue, env.getGlobals().label());
}
}
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 6d156f2..3387941 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
@@ -64,6 +64,28 @@
}
@Test
+ public void testRemoteLabelAsDefaultAttributeValue() throws Exception {
+ scratch.file(
+ "test/skylark/extension.bzl",
+ "def _impl(ctx):",
+ " pass",
+ "my_rule = rule(implementation = _impl,",
+ " attrs = { 'dep' : attr.label_list(default=[\"@r//:t\"]) })");
+
+ // We are only interested in whether the label string in the default value can be converted
+ // to a proper Label without an exception (see GitHub issue #1442).
+ // Consequently, we expect getTarget() to fail later since the repository does not exist.
+ checkError(
+ "test/skylark",
+ "the_rule",
+ "no such package '@r//': error loading package 'external': "
+ + "The repository named 'r' could not be resolved",
+ "load('/test/skylark/extension', 'my_rule')",
+ "",
+ "my_rule(name='the_rule')");
+ }
+
+ @Test
public void testSameMethodNames() throws Exception {
// The alias feature of load() may hide the fact that two methods in the stack trace have the
// same name. This is perfectly legal as long as these two methods are actually distinct.